]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fix shmat() on Linux nanomips and x86
authorAnssi Hannula <anssi.hannula@bitwise.fi>
Thu, 2 Jul 2020 11:49:17 +0000 (14:49 +0300)
committerMark Wielaard <mark@klomp.org>
Wed, 3 Feb 2021 18:50:21 +0000 (19:50 +0100)
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

NEWS
coregrind/m_syswrap/syswrap-generic.c

diff --git a/NEWS b/NEWS
index c1de304ee7f075663c34984a6dab57f7d0ff861e..e196e8fecdfeb1f2437a0b4ce973e2517d55f00a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -59,6 +59,8 @@ n-i-bz  helgrind: If hg_cli__realloc fails, return NULL.
 397605  ioctl FICLONE mishandled
 408663  Suppression file for musl libc
 404076  s390x: z14 vector instructions not implemented
+410743  shmat() calls for 32-bit programs fail when running in 64-bit valgrind
+        (actually affected all x86 and nanomips regardless of host bitness)
 415293  Incorrect call-graph tracking due to new _dl_runtime_resolve_xsave*
 422174  unhandled instruction bytes: 0x48 0xE9 (REX prefixed JMP instruction)
 422623  epoll_ctl warns for uninitialized padding on non-amd64 64bit arches
index badb8c778dd2771a2cb9c1670785ac4071a8d95f..7d4b385a380befa59bf441c35ae91891cf3d58cf 100644 (file)
@@ -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