Просмотр исходного кода

mips: always set IPC_64 for the SysV IPC *ctl commands

mips routes semctl/shmctl/msgctl through sys_old_semctl & co. (n32 uses
the compat_sys_old_* variants), and those call ipc_parse_version(), which
strips the IPC_64 bit out of cmd to choose between the ancient and the
modern struct layout -- on every kernel version, n32 and n64 alike.  So
IPC_64 must always be set; without it the kernel returns the old struct
and e.g. semctl(IPC_STAT) reports sem_nsems == 0.

ipc.h had mips in the same kernel-version guard as i386/m68k (IPC_64 = 0
from 5.1 on), which is correct for those arches because 5.1+ routes their
*ctl through the direct sys_semctl (which does not parse the version) but
wrong for mips: built against >= 5.1 headers the bit was dropped and the
sem/tst-semctl/tst-shmctl tests failed on the mips64 n32/n64 targets.

Give mips its own branch that keeps IPC_64 = 0x100 unconditionally.
Verified on qemu-system-mips64 (mips64-be-n64, linux-6.1.60 headers): sem,
tst-semctl and tst-shmctl pass.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
ramin 4 дней назад
Родитель
Сommit
1cea0a036f
1 измененных файлов с 8 добавлено и 1 удалено
  1. 8 1
      libc/misc/sysvipc/ipc.h

+ 8 - 1
libc/misc/sysvipc/ipc.h

@@ -6,7 +6,14 @@
 
 #ifndef __ARCH_HAS_DEPRECATED_SYSCALLS__
 #  define __IPC_64	0x0
-#elif defined __mips__ || defined __m68k__ || defined __i386__
+#elif defined __mips__
+/* mips routes the *ctl syscalls through sys_old_*ctl (and the ipc()
+   multiplexer), which call ipc_parse_version() and so strip IPC_64 out of
+   cmd to select the layout on every kernel version -- including n64.  The
+   bit must therefore always be set, otherwise the kernel returns the
+   ancient struct and e.g. sem_nsems comes back as 0.  */
+#  define __IPC_64	0x100
+#elif defined __m68k__ || defined __i386__
 /* 5.1+ uses the direct *ctl syscalls, which (unlike ipc()) do not strip
    IPC_64 -- passing it would make them fail with EINVAL.  */
 # if __LINUX_KERNEL_VERSION < 0x050100