Explorar o código

libc: pick IPC_64 by what the headers offer, not by the word size

sparc64 returns garbage from every *ctl call -- tst-semctl reports
sem_perm.uid as -2957503, sem_nsems as 0 and sem_otime in year ???? --
because the kernel filled the pre-IPC_64 structure.  ipc.h decides the
bit by word size, so 64-bit targets do not set it, and without the bit
sys_ipc's ipc_parse_version() selects the ancient layout.

Which is right depends on the route, and the route depends on the
headers.  sparc has no direct semctl in 4.19, only __NR_ipc 215, so the
call goes through the multiplexer where the kernel reads the bit out of
cmd; from the 6.x headers semctl is 394 and points at sys_semctl, which
sets IPC_64 itself and answers EINVAL to a cmd that carries the bit.

Measured with the same library, toolchain and qemu image, only the
headers swapped:

                4.19.56 headers      6.5.10 headers
  sparc32           4 pass              4 fail (EINVAL)
  sparc64           2 fail (garbage)    4 pass

A clean diagonal, and identical for both word sizes -- so __WORDSIZE was
never the criterion.  Use "#ifdef __NR_semctl" for the architectures
whose direct number points at sys_*ctl: i386, m68k, mips o32, sh,
powerpc, sparc, hppa.  It is more accurate than a configured version
number, because the headers are what the build actually sees.

That replaces the per-arch cascade this grew over the last months:
42c80560f gave i386 a __LINUX_KERNEL_VERSION test, e4391b9b8 made hppa an
unconditional 0x0, and 1cea0a036 with 97958e275 sorted out mips o32
against n32/n64.  Each was right for its target, but they were three
answers to one question -- and the version test coincides with the header
test anyway, since i386 and m68k got their direct numbers in 5.1.

Left alone deliberately: arm, xtensa, microblaze and alpha have had a
direct number all along, but it points at sys_old_*ctl, which parses the
version and wants the bit either way -- arm's semctl is 300 and was
sys_semctl in 4.19 and sys_old_semctl from 5.1, because that is when the
kernel swapped the two names.  mips n32/n64 keep their own case above,
and everything without ARCH_HAS_DEPRECATED_SYSCALLS keeps 0x0.

powerpc and sh had the same latent bug as sparc32, and this fixes them
too: their 394/396/402 point at sys_semctl, sys_shmctl and sys_msgctl,
read off the kernel's syscall.tbl the same way as the sys_old_semctl of
the four above, so the old word-size rule was right for them only for as
long as the build stayed on pre-5.1 headers.

Signed-off-by: Ramin Moussavi <lordrasmus@gmail.com>
ramin hai 1 semana
pai
achega
e31ac0f10f
Modificáronse 1 ficheiros con 11 adicións e 11 borrados
  1. 11 11
      libc/misc/sysvipc/ipc.h

+ 11 - 11
libc/misc/sysvipc/ipc.h

@@ -16,19 +16,19 @@
    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__ || defined __mips__
-/* 5.1+ uses the direct *ctl syscalls, which (unlike ipc()) do not strip
-   IPC_64 -- passing it would make them fail with EINVAL.  mips o32 got them
-   as 394/396/402 and belongs here; n32/n64 are handled above.  */
-# if __LINUX_KERNEL_VERSION < 0x050100
-#  define __IPC_64      0x100
-# else
+#elif defined __m68k__ || defined __i386__ || defined __mips__ \
+   || defined __sh__ || defined __powerpc__ || defined __sparc__ \
+   || defined __hppa__
+/* A direct semctl/msgctl/shmctl pointing at sys_*ctl sets IPC_64 in the
+   kernel and rejects a cmd that carries the bit; without such a number the
+   call goes through ipc(), which reads it out of cmd.  arm, xtensa,
+   microblaze and alpha stay out: their direct number is sys_old_*ctl, which
+   wants the bit either way.  */
+# ifdef __NR_semctl
 #  define __IPC_64      0x0
+# else
+#  define __IPC_64      0x100
 # endif
-#elif defined __hppa__
-/* parisc has no ARCH_WANT_IPC_PARSE_VERSION: the kernel never strips
-   IPC_64, so passing it makes semctl & co. fail with EINVAL.  */
-#  define __IPC_64	0x0
 #else
 # if __WORDSIZE == 32 || defined __alpha__
 #  define __IPC_64	0x100