Parcourir la source

i386: do not set IPC_64 for the SysV IPC *ctl commands on 5.1+ kernels

Since Linux 5.1 i386 has direct semctl/msgctl/shmctl syscalls, and uClibc-ng
issues them when the kernel headers provide them.  Unlike the old ipc()
multiplexer, the direct *ctl syscalls do not run ipc_parse_version() and so
do not strip the IPC_64 bit from the command: SYSCALL_DEFINE4(semctl) calls
ksys_semctl(..., cmd, ..., IPC_64) with cmd unchanged, so IPC_STAT|IPC_64 no
longer matches the IPC_STAT case and the call fails with EINVAL.

ipc.h still defined __IPC_64 as 0x100 for i386 (the __WORDSIZE == 32 default),
so semctl(IPC_STAT) and friends failed on 5.1+ kernels -- e.g. the sem test of
the uClibc-ng test suite on i686 with linux-6.18.

Give i386 the kernel-version guard mips and m68k already use: keep 0x100 below
5.1 (the ipc() multiplexer strips the bit) and 0x0 from 5.1 on.

Verified on i686/TIME64 against linux-6.18.33 under qemu-system-i386: the sem
test passes and semctl no longer ORs IPC_64 into the command.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
Ramin Moussavi il y a 1 semaine
Parent
commit
42c80560ff
1 fichiers modifiés avec 3 ajouts et 1 suppressions
  1. 3 1
      libc/misc/sysvipc/ipc.h

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

@@ -6,7 +6,9 @@
 
 
 #ifndef __ARCH_HAS_DEPRECATED_SYSCALLS__
 #ifndef __ARCH_HAS_DEPRECATED_SYSCALLS__
 #  define __IPC_64	0x0
 #  define __IPC_64	0x0
-#elif defined __mips__ || defined __m68k__
+#elif defined __mips__ || 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
 # if __LINUX_KERNEL_VERSION < 0x050100
 #  define __IPC_64      0x100
 #  define __IPC_64      0x100
 # else
 # else