Blob Blame History Raw
commit 232893d9b3c7d79d018db7f303aee219161a86d0
Author: Anssi Hannula <anssi.hannula@bitwise.fi>
Date:   Thu Jul 2 14:49:17 2020 +0300

    Fix shmat() on Linux nanomips and x86
    
    On Linux, there are two variants of the direct shmctl syscall:
    - sys_shmctl: always uses shmid64_ds, does not accept IPC_64
    - sys_old_shmctl: uses shmid_ds or shmid64_ds depending on IPC_64
    
    The following Linux ABIs have the sys_old_shmctl variant:
      alpha, arm, microblaze, mips n32/n64, xtensa
    
    Other ABIs (and future ABIs) have the sys_shmctl variant, including ABIs
    that only got sys_shmctl in Linux 5.1 (such as x86, mips o32, ppc,
    s390x).
    
    We incorrectly assume the sys_old_shmctl variant on nanomips and x86,
    causing shmat() calls under valgrind to fail with EINVAL.
    
    On x86, the issue was previously masked by the non-existence of
    __NR_shmctl until a9fc7bceeb0b0 ("Update Linux x86 system call number
    definitions") in 2019.
    
    On mips o32, ppc, and s390x this issue is not visible as our headers do
    not have __NR_shmctl for those ABIs (396 since Linux 5.1).
    
    Fix the issue by correcting the preprocessor check in get_shm_size() to
    only assume the old Linux sys_old_shmctl behavior on the specific
    affected platforms.
    
    Also, exclude the use of direct shmctl entirely on Linux x86, ppc,
    mips o32, s390x in order to keep compatibility with pre-5.1 kernel
    versions that did not yet have direct shmctl for those ABIs.
    This currently only has actual effect on x86 as only it has __NR_shmctl
    in our headers.
    
    Fixes tests mremap4, mremap5, mremap6.
    
    https://bugs.kde.org/show_bug.cgi?id=410743

diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
index badb8c778..7d4b385a3 100644
--- a/coregrind/m_syswrap/syswrap-generic.c
+++ b/coregrind/m_syswrap/syswrap-generic.c
@@ -1960,11 +1960,27 @@ ML_(generic_POST_sys_semctl) ( ThreadId tid,
 static
 SizeT get_shm_size ( Int shmid )
 {
-#if defined(__NR_shmctl)
+   /*
+    * The excluded platforms below gained direct shmctl in Linux 5.1. Keep
+    * using ipc-multiplexed shmctl to keep compatibility with older kernel
+    * versions.
+    */
+#if defined(__NR_shmctl) && \
+    !defined(VGP_x86_linux) && !defined(VGP_mips32_linux) && \
+    !defined(VGP_ppc32_linux) && !defined(VGP_ppc64be_linux) && \
+    !defined(VGP_ppc64le_linux) && !defined(VGP_s390x_linux)
 #  ifdef VKI_IPC_64
    struct vki_shmid64_ds buf;
-#    if defined(VGP_amd64_linux) || defined(VGP_arm64_linux)
-     /* See bug 222545 comment 7 */
+     /*
+      * On Linux, the following ABIs use old shmid_ds by default with direct
+      * shmctl and require IPC_64 for shmid64_ds (i.e. the direct syscall is
+      * mapped to sys_old_shmctl):
+      *    alpha, arm, microblaze, mips n32/n64, xtensa
+      * Other Linux ABIs use shmid64_ds by default and do not recognize IPC_64
+      * with the direct shmctl syscall (but still recognize it for the
+      * ipc-multiplexed version if that exists for the ABI).
+      */
+#    if defined(VGO_linux) && !defined(VGP_arm_linux) && !defined(VGP_mips64_linux)
      SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, 
                                      VKI_IPC_STAT, (UWord)&buf);
 #    else
commit 620dba22be67dea2ada9fa825b2ed4d61774af82
Author: Mark Wielaard <mark@klomp.org>
Date:   Wed Feb 3 16:56:14 2021 +0100

    syswrap-linux.c: Pass implicit VKI_IPC_64 for shmctl also on arm64.
    
    The shmctl syscall on amd64, arm64 and riscv (but we don't have a port
    for that last one) always use IPC_64. Explicitly pass it to the generic
    PRE/POST handlers so they select the correct (64bit) data structures on
    those architectures.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1909548

diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
index 328e02a98..52074149d 100644
--- a/coregrind/m_syswrap/syswrap-linux.c
+++ b/coregrind/m_syswrap/syswrap-linux.c
@@ -5127,7 +5127,7 @@ PRE(sys_shmctl)
    PRINT("sys_shmctl ( %ld, %ld, %#" FMT_REGWORD "x )", SARG1, SARG2, ARG3);
    PRE_REG_READ3(long, "shmctl",
                  int, shmid, int, cmd, struct shmid_ds *, buf);
-#ifdef VGP_amd64_linux
+#if defined(VGP_amd64_linux) || defined(VGP_arm64_linux)
    ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2|VKI_IPC_64,ARG3);
 #else
    ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
@@ -5136,7 +5136,7 @@ PRE(sys_shmctl)
 
 POST(sys_shmctl)
 {
-#ifdef VGP_amd64_linux
+#if defined(VGP_amd64_linux) || defined(VGP_arm64_linux)
    ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2|VKI_IPC_64,ARG3);
 #else
    ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);