* [PATCH v6 0/3] Support y2038 semctl_syscall() @ 2020-04-28 22:05 Alistair Francis 2020-04-28 22:05 ` [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds Alistair Francis ` (2 more replies) 0 siblings, 3 replies; 8+ messages in thread From: Alistair Francis @ 2020-04-28 22:05 UTC (permalink / raw) To: libc-alpha; +Cc: alistair23, Alistair Francis This series does three things: 1. Creates a bits/semid_ds_t.h file (in every arch) that specifies struct semid_ds so we no longer have to use macros defined in sem-pad.h. 2. Removes the sem-pad.h file as it is no longer needed. 3. Adds a new __semid_ds32 that is passed to the kernel (as part of a union) when running on 32-bit systems. If we are doing an IPC_STAT command then the 32-bit sem_{c,o}time{_high} values are combined to create a 64-bit value. The semctl_syscall() function passes a union semun to the kernel. The union includes struct semid_ds as a member. On 32-bit architectures the Linux kernel provides a *_high version of the 32-bit sem_otime and sem_ctime values. These can be combined to get a 64-bit version of the time. This patch adjusts the struct semid_ds to support the *_high versions of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t this can be used to get a 64-bit time from the two 32-bit values. This series was tested by running: ./scripts/build-many-glibcs.py ... compilers ./scripts/build-many-glibcs.py ... glibcs on my x86_64 machine. I also ran make check on RV32 and I only see a total of 9 test failures. v6: - Update the 3rd patch to pass a temp buffer to the kernel v5: - Address v4 review comments - Set the semid_ds struct from a temp struct v4: - Remove the __IPC_TIME64 macro - It was only used once and doesn't work if __IPC_64 is 0 (which is usually is) - Address failures pointed out by Vineet Gupta Alistair Francis (3): bits/sem.h: Split out struct semid_ds semctl: Remove the sem-pad.h file sysv: linux: Pass 64-bit version of semctl syscall sysdeps/unix/sysv/linux/Makefile | 3 +- sysdeps/unix/sysv/linux/bits/sem.h | 26 +--------- .../sysv/linux/bits/types/struct_semid_ds.h | 46 ++++++++++++++++++ .../bits/types/struct_semid_ds.h} | 31 ++++++------ .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++ .../bits/types/struct_semid_ds.h} | 20 +++++--- .../{bits/sem-pad.h => struct__semid_ds32.h} | 20 +++++--- .../unix/sysv/linux/powerpc/bits/sem-pad.h | 26 ---------- .../powerpc/bits/types/struct_semid_ds.h | 39 +++++++++++++++ .../sysv/linux/powerpc/struct__semid_ds32.h | 32 +++++++++++++ sysdeps/unix/sysv/linux/semctl.c | 47 +++++++++++++++++-- .../linux/sparc/bits/types/struct_semid_ds.h | 39 +++++++++++++++ .../sysv/linux/sparc/struct__semid_ds32.h | 32 +++++++++++++ sysdeps/unix/sysv/linux/struct__semid_ds32.h | 32 +++++++++++++ sysdeps/unix/sysv/linux/x86/bits/sem-pad.h | 24 ---------- .../bits/types/struct_semid_ds.h} | 22 ++++++--- .../unix/sysv/linux/x86/struct__semid_ds32.h | 32 +++++++++++++ 17 files changed, 389 insertions(+), 114 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h rename sysdeps/unix/sysv/linux/{bits/sem-pad.h => hppa/bits/types/struct_semid_ds.h} (51%) create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h rename sysdeps/unix/sysv/linux/{sparc/bits/sem-pad.h => mips/bits/types/struct_semid_ds.h} (56%) rename sysdeps/unix/sysv/linux/mips/{bits/sem-pad.h => struct__semid_ds32.h} (52%) delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h delete mode 100644 sysdeps/unix/sysv/linux/x86/bits/sem-pad.h rename sysdeps/unix/sysv/linux/{hppa/bits/sem-pad.h => x86/bits/types/struct_semid_ds.h} (53%) create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h -- 2.26.2 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds 2020-04-28 22:05 [PATCH v6 0/3] Support y2038 semctl_syscall() Alistair Francis @ 2020-04-28 22:05 ` Alistair Francis 2020-04-28 22:05 ` [PATCH v6 2/3] semctl: Remove the sem-pad.h file Alistair Francis 2020-04-28 22:05 ` [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Alistair Francis 2 siblings, 0 replies; 8+ messages in thread From: Alistair Francis @ 2020-04-28 22:05 UTC (permalink / raw) To: libc-alpha; +Cc: alistair23, Alistair Francis, Adhemerval Zanella Split out the struct semid_ds into it's own file. This will allow us to have architectures specify their own version. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> --- sysdeps/unix/sysv/linux/Makefile | 1 + sysdeps/unix/sysv/linux/bits/sem.h | 24 +---------- .../sysv/linux/bits/types/struct_semid_ds.h | 43 +++++++++++++++++++ 3 files changed, 45 insertions(+), 23 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 089a4899d5..db35c29351 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -90,6 +90,7 @@ sysdep_headers += sys/mount.h sys/acct.h \ bits/termios-baud.h bits/termios-c_cflag.h \ bits/termios-c_lflag.h bits/termios-tcflow.h \ bits/termios-misc.h \ + bits/types/struct_semid_ds.h \ bits/ipc-perm.h tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \ diff --git a/sysdeps/unix/sysv/linux/bits/sem.h b/sysdeps/unix/sysv/linux/bits/sem.h index e0f4155c67..0d1813ec67 100644 --- a/sysdeps/unix/sysv/linux/bits/sem.h +++ b/sysdeps/unix/sysv/linux/bits/sem.h @@ -21,6 +21,7 @@ #include <sys/types.h> #include <bits/sem-pad.h> +#include <bits/types/struct_semid_ds.h> /* Flags for `semop'. */ #define SEM_UNDO 0x1000 /* undo the operation on exit */ @@ -34,29 +35,6 @@ #define SETVAL 16 /* set semval */ #define SETALL 17 /* set all semval's */ - -#if __SEM_PAD_BEFORE_TIME -# define __SEM_PAD_TIME(NAME, RES) \ - __syscall_ulong_t __glibc_reserved ## RES; __time_t NAME -#elif __SEM_PAD_AFTER_TIME -# define __SEM_PAD_TIME(NAME, RES) \ - __time_t NAME; __syscall_ulong_t __glibc_reserved ## RES -#else -# define __SEM_PAD_TIME(NAME, RES) \ - __time_t NAME -#endif - -/* Data structure describing a set of semaphores. */ -struct semid_ds -{ - struct ipc_perm sem_perm; /* operation permission struct */ - __SEM_PAD_TIME (sem_otime, 1); /* last semop() time */ - __SEM_PAD_TIME (sem_ctime, 2); /* last time changed by semctl() */ - __syscall_ulong_t sem_nsems; /* number of semaphores in set */ - __syscall_ulong_t __glibc_reserved3; - __syscall_ulong_t __glibc_reserved4; -}; - /* The user should define a union like the following to use it for arguments for `semctl'. diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h new file mode 100644 index 0000000000..0e136961d5 --- /dev/null +++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h @@ -0,0 +1,43 @@ +/* Generic implementation of the semaphore struct semid_ds. + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_SEM_H +# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead." +#endif + +#if __SEM_PAD_BEFORE_TIME +# define __SEM_PAD_TIME(NAME, RES) \ + __syscall_ulong_t __glibc_reserved ## RES; __time_t NAME +#elif __SEM_PAD_AFTER_TIME +# define __SEM_PAD_TIME(NAME, RES) \ + __time_t NAME; __syscall_ulong_t __glibc_reserved ## RES +#else +# define __SEM_PAD_TIME(NAME, RES) \ + __time_t NAME +#endif + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __SEM_PAD_TIME (sem_otime, 1); /* last semop() time */ + __SEM_PAD_TIME (sem_ctime, 2); /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; -- 2.26.2 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 2/3] semctl: Remove the sem-pad.h file 2020-04-28 22:05 [PATCH v6 0/3] Support y2038 semctl_syscall() Alistair Francis 2020-04-28 22:05 ` [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds Alistair Francis @ 2020-04-28 22:05 ` Alistair Francis 2020-04-28 22:05 ` [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Alistair Francis 2 siblings, 0 replies; 8+ messages in thread From: Alistair Francis @ 2020-04-28 22:05 UTC (permalink / raw) To: libc-alpha; +Cc: alistair23, Alistair Francis, Adhemerval Zanella Remove the sem-pad.h file and instead have architectures override the struct semid_ds via the bits/types/struct_semid_ds.h file. Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org> --- sysdeps/unix/sysv/linux/Makefile | 2 +- sysdeps/unix/sysv/linux/bits/sem.h | 2 +- .../sysv/linux/bits/types/struct_semid_ds.h | 29 +++++++------- .../bits/types/struct_semid_ds.h} | 31 ++++++++------- sysdeps/unix/sysv/linux/mips/bits/sem-pad.h | 24 ------------ .../bits/types/struct_semid_ds.h} | 20 ++++++---- .../unix/sysv/linux/powerpc/bits/sem-pad.h | 26 ------------- .../powerpc/bits/types/struct_semid_ds.h | 39 +++++++++++++++++++ .../linux/sparc/bits/types/struct_semid_ds.h | 39 +++++++++++++++++++ sysdeps/unix/sysv/linux/x86/bits/sem-pad.h | 24 ------------ .../bits/types/struct_semid_ds.h} | 22 +++++++---- 11 files changed, 141 insertions(+), 117 deletions(-) rename sysdeps/unix/sysv/linux/{bits/sem-pad.h => hppa/bits/types/struct_semid_ds.h} (51%) delete mode 100644 sysdeps/unix/sysv/linux/mips/bits/sem-pad.h rename sysdeps/unix/sysv/linux/{sparc/bits/sem-pad.h => mips/bits/types/struct_semid_ds.h} (56%) delete mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h create mode 100644 sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h delete mode 100644 sysdeps/unix/sysv/linux/x86/bits/sem-pad.h rename sysdeps/unix/sysv/linux/{hppa/bits/sem-pad.h => x86/bits/types/struct_semid_ds.h} (53%) diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index db35c29351..434b008a91 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -84,7 +84,7 @@ sysdep_headers += sys/mount.h sys/acct.h \ bits/siginfo-arch.h bits/siginfo-consts-arch.h \ bits/procfs.h bits/procfs-id.h bits/procfs-extra.h \ bits/procfs-prregset.h bits/mman-map-flags-generic.h \ - bits/msq-pad.h bits/sem-pad.h bits/shmlba.h bits/shm-pad.h \ + bits/msq-pad.h bits/shmlba.h bits/shm-pad.h \ bits/termios-struct.h bits/termios-c_cc.h \ bits/termios-c_iflag.h bits/termios-c_oflag.h \ bits/termios-baud.h bits/termios-c_cflag.h \ diff --git a/sysdeps/unix/sysv/linux/bits/sem.h b/sysdeps/unix/sysv/linux/bits/sem.h index 0d1813ec67..ba1169fdb3 100644 --- a/sysdeps/unix/sysv/linux/bits/sem.h +++ b/sysdeps/unix/sysv/linux/bits/sem.h @@ -20,7 +20,7 @@ #endif #include <sys/types.h> -#include <bits/sem-pad.h> +#include <bits/timesize.h> #include <bits/types/struct_semid_ds.h> /* Flags for `semop'. */ diff --git a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h index 0e136961d5..4222e6a59f 100644 --- a/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h +++ b/sysdeps/unix/sysv/linux/bits/types/struct_semid_ds.h @@ -20,24 +20,27 @@ # error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead." #endif -#if __SEM_PAD_BEFORE_TIME -# define __SEM_PAD_TIME(NAME, RES) \ - __syscall_ulong_t __glibc_reserved ## RES; __time_t NAME -#elif __SEM_PAD_AFTER_TIME -# define __SEM_PAD_TIME(NAME, RES) \ - __time_t NAME; __syscall_ulong_t __glibc_reserved ## RES -#else -# define __SEM_PAD_TIME(NAME, RES) \ - __time_t NAME -#endif - /* Data structure describing a set of semaphores. */ +#if __TIMESIZE == 32 +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __syscall_ulong_t __glibc_reserved1; + __time_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t __glibc_reserved2; + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#else struct semid_ds { struct ipc_perm sem_perm; /* operation permission struct */ - __SEM_PAD_TIME (sem_otime, 1); /* last semop() time */ - __SEM_PAD_TIME (sem_ctime, 2); /* last time changed by semctl() */ + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ __syscall_ulong_t sem_nsems; /* number of semaphores in set */ __syscall_ulong_t __glibc_reserved3; __syscall_ulong_t __glibc_reserved4; }; +#endif diff --git a/sysdeps/unix/sysv/linux/bits/sem-pad.h b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h similarity index 51% rename from sysdeps/unix/sysv/linux/bits/sem-pad.h rename to sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h index 566ce039cc..d4c50b5ef8 100644 --- a/sysdeps/unix/sysv/linux/bits/sem-pad.h +++ b/sysdeps/unix/sysv/linux/hppa/bits/types/struct_semid_ds.h @@ -1,5 +1,5 @@ -/* Define where padding goes in struct semid_ds. Generic version. - Copyright (C) 2018-2020 Free Software Foundation, Inc. +/* HPPA implementation of the semaphore struct semid_ds + Copyright (C) 1995-2020 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,17 +17,20 @@ <https://www.gnu.org/licenses/>. */ #ifndef _SYS_SEM_H -# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead." +# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead." #endif -#include <bits/timesize.h> - -/* On most architectures, padding goes after time fields for 32-bit - systems and is omitted for 64-bit systems. Some architectures pad - before time fields instead, or omit padding despite being 32-bit, - or include it despite being 64-bit. This must match the layout - used for struct semid64_ds in <asm/sembuf.h>, as glibc does not do - layout conversions for this structure. */ - -#define __SEM_PAD_AFTER_TIME (__TIMESIZE == 32) -#define __SEM_PAD_BEFORE_TIME 0 +/* Data structure describing a set of semaphores. */ +#if __TIMESIZE == 32 +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t __glibc_reserved1; + __time_t sem_otime; /* last semop() time */ + __syscall_ulong_t __glibc_reserved2; + __time_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif diff --git a/sysdeps/unix/sysv/linux/mips/bits/sem-pad.h b/sysdeps/unix/sysv/linux/mips/bits/sem-pad.h deleted file mode 100644 index 4c581f7694..0000000000 --- a/sysdeps/unix/sysv/linux/mips/bits/sem-pad.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Define where padding goes in struct semid_ds. MIPS version. - Copyright (C) 2018-2020 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -#ifndef _SYS_SEM_H -# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead." -#endif - -#define __SEM_PAD_AFTER_TIME 0 -#define __SEM_PAD_BEFORE_TIME 0 diff --git a/sysdeps/unix/sysv/linux/sparc/bits/sem-pad.h b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h similarity index 56% rename from sysdeps/unix/sysv/linux/sparc/bits/sem-pad.h rename to sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h index 5f4e214d12..8954209a29 100644 --- a/sysdeps/unix/sysv/linux/sparc/bits/sem-pad.h +++ b/sysdeps/unix/sysv/linux/mips/bits/types/struct_semid_ds.h @@ -1,5 +1,5 @@ -/* Define where padding goes in struct semid_ds. SPARC version. - Copyright (C) 2018-2020 Free Software Foundation, Inc. +/* MIPS implementation of the semaphore struct semid_ds + Copyright (C) 1995-2020 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,10 +17,16 @@ <https://www.gnu.org/licenses/>. */ #ifndef _SYS_SEM_H -# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead." +# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead." #endif -#include <bits/timesize.h> - -#define __SEM_PAD_AFTER_TIME 0 -#define __SEM_PAD_BEFORE_TIME (__TIMESIZE == 32) +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h b/sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h deleted file mode 100644 index 42d8827906..0000000000 --- a/sysdeps/unix/sysv/linux/powerpc/bits/sem-pad.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Define where padding goes in struct semid_ds. PowerPC version. - Copyright (C) 2018-2020 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -#ifndef _SYS_SEM_H -# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead." -#endif - -#include <bits/timesize.h> - -#define __SEM_PAD_AFTER_TIME 0 -#define __SEM_PAD_BEFORE_TIME (__TIMESIZE == 32) diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h new file mode 100644 index 0000000000..300a9b98e9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/bits/types/struct_semid_ds.h @@ -0,0 +1,39 @@ +/* PowerPC implementation of the semaphore struct semid_ds. + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_SEM_H +# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead." +#endif + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ +#if __TIMESIZE == 32 + __syscall_ulong_t __glibc_reserved1; + __time_t sem_otime; /* last semop() time */ + __syscall_ulong_t __glibc_reserved2; + __time_t sem_ctime; /* last time changed by semctl() */ +#else + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ +#endif + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; diff --git a/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h new file mode 100644 index 0000000000..46fcd79fb6 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/bits/types/struct_semid_ds.h @@ -0,0 +1,39 @@ +/* Sparc implementation of the semaphore struct semid_ds + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _SYS_SEM_H +# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead." +#endif + +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ +#if __TIMESIZE == 32 + __syscall_ulong_t __glibc_reserved1; + __time_t sem_otime; /* last semop() time */ + __syscall_ulong_t __glibc_reserved2; + __time_t sem_ctime; /* last time changed by semctl() */ +#else + __time_t sem_otime; /* last semop() time */ + __time_t sem_ctime; /* last time changed by semctl() */ +#endif + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; diff --git a/sysdeps/unix/sysv/linux/x86/bits/sem-pad.h b/sysdeps/unix/sysv/linux/x86/bits/sem-pad.h deleted file mode 100644 index 102e226997..0000000000 --- a/sysdeps/unix/sysv/linux/x86/bits/sem-pad.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Define where padding goes in struct semid_ds. x86 version. - Copyright (C) 2018-2020 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, see - <https://www.gnu.org/licenses/>. */ - -#ifndef _SYS_SEM_H -# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead." -#endif - -#define __SEM_PAD_AFTER_TIME 1 -#define __SEM_PAD_BEFORE_TIME 0 diff --git a/sysdeps/unix/sysv/linux/hppa/bits/sem-pad.h b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h similarity index 53% rename from sysdeps/unix/sysv/linux/hppa/bits/sem-pad.h rename to sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h index ee0332325b..f7ec89d115 100644 --- a/sysdeps/unix/sysv/linux/hppa/bits/sem-pad.h +++ b/sysdeps/unix/sysv/linux/x86/bits/types/struct_semid_ds.h @@ -1,5 +1,5 @@ -/* Define where padding goes in struct semid_ds. HPPA version. - Copyright (C) 2018-2020 Free Software Foundation, Inc. +/* x86 implementation of the semaphore struct semid_ds. + Copyright (C) 1995-2020 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -17,10 +17,18 @@ <https://www.gnu.org/licenses/>. */ #ifndef _SYS_SEM_H -# error "Never use <bits/sem-pad.h> directly; include <sys/sem.h> instead." +# error "Never include <bits/types/struct_semid_ds.h> directly; use <sys/sem.h> instead." #endif -#include <bits/timesize.h> - -#define __SEM_PAD_AFTER_TIME 0 -#define __SEM_PAD_BEFORE_TIME (__TIMESIZE == 32) +/* Data structure describing a set of semaphores. */ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + __time_t sem_otime; /* last semop() time */ + __syscall_ulong_t __glibc_reserved1; + __time_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t __glibc_reserved2; + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; -- 2.26.2 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall 2020-04-28 22:05 [PATCH v6 0/3] Support y2038 semctl_syscall() Alistair Francis 2020-04-28 22:05 ` [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds Alistair Francis 2020-04-28 22:05 ` [PATCH v6 2/3] semctl: Remove the sem-pad.h file Alistair Francis @ 2020-04-28 22:05 ` Alistair Francis 2020-04-29 21:09 ` Adhemerval Zanella 2 siblings, 1 reply; 8+ messages in thread From: Alistair Francis @ 2020-04-28 22:05 UTC (permalink / raw) To: libc-alpha; +Cc: alistair23, Alistair Francis The semctl_syscall() function passes a union semun to the kernel. The union includes struct semid_ds as a member. On 32-bit architectures the Linux kernel provides a *_high version of the 32-bit sem_otime and sem_ctime values. These can be combined to get a 64-bit version of the time. This patch adjusts the struct semid_ds to support the *_high versions of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t this can be used to get a 64-bit time from the two 32-bit values. Due to alignment differences between 64-bit and 32-bit variables we also need to set nsems to ensure it's correct. --- .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++ .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++ .../sysv/linux/powerpc/struct__semid_ds32.h | 32 +++++++++++++ sysdeps/unix/sysv/linux/semctl.c | 47 +++++++++++++++++-- .../sysv/linux/sparc/struct__semid_ds32.h | 32 +++++++++++++ sysdeps/unix/sysv/linux/struct__semid_ds32.h | 32 +++++++++++++ .../unix/sysv/linux/x86/struct__semid_ds32.h | 32 +++++++++++++ 7 files changed, 233 insertions(+), 4 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h new file mode 100644 index 0000000000..9eceaaff2d --- /dev/null +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h @@ -0,0 +1,32 @@ +/* HPPA implementation of the semaphore struct __semid_ds32. + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h new file mode 100644 index 0000000000..2e3e2fc562 --- /dev/null +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h @@ -0,0 +1,30 @@ +/* MIPS implementation of the semaphore struct __semid_ds32. + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime; /* last semop time */ + __syscall_ulong_t sem_ctime; /* last change time */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t sem_otime_high; + __syscall_ulong_t sem_ctime_high; +}; +#endif diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h new file mode 100644 index 0000000000..f509db5a02 --- /dev/null +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h @@ -0,0 +1,32 @@ +/* PowerPC implementation of the semaphore struct __semid_ds32. + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c index 30571af49f..0634cc1abe 100644 --- a/sysdeps/unix/sysv/linux/semctl.c +++ b/sysdeps/unix/sysv/linux/semctl.c @@ -22,8 +22,13 @@ #include <sysdep.h> #include <shlib-compat.h> #include <errno.h> +#include <struct__semid_ds32.h> #include <linux/posix_types.h> /* For __kernel_mode_t. */ +#define IPC_TIME64 \ + (__WORDSIZE == 32 && __TIMESIZE == 64 \ + && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) + /* Define a `union semun' suitable for Linux here. */ union semun { @@ -44,13 +49,47 @@ union semun static int semctl_syscall (int semid, int semnum, int cmd, union semun arg) { + int ret; +#if IPC_TIME64 + struct __semid_ds32 tmp; + struct semid_ds *orig; + bool restore = false; + if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY) + { + tmp = (struct __semid_ds32) { + .sem_perm = arg.buf->sem_perm, + .sem_otime = arg.buf->sem_otime, + .sem_ctime = arg.buf->sem_ctime, + .sem_nsems = arg.buf->sem_nsems, + }; + orig = arg.buf; + arg.buf = (struct semid_ds*)&tmp; + restore = true; + } +#endif + #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, - arg.array); + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, + arg.array); #else - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, - SEMCTL_ARG_ADDRESS (arg)); + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, + SEMCTL_ARG_ADDRESS (arg)); #endif + +#if IPC_TIME64 + if (ret >= 0 && restore) + { + arg.buf = orig; + arg.buf->sem_perm = tmp.sem_perm; + arg.buf->sem_otime = tmp.sem_otime + | ((time_t) tmp.sem_otime_high << 32); + arg.buf->sem_ctime = tmp.sem_ctime + | ((time_t) tmp.sem_ctime_high << 32); + arg.buf->sem_nsems = tmp.sem_nsems; + } +#endif + + return ret; } int diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h new file mode 100644 index 0000000000..f641825d37 --- /dev/null +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h @@ -0,0 +1,32 @@ +/* Sparc implementation of the semaphore struct __semid_ds32. + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h new file mode 100644 index 0000000000..51ff83206d --- /dev/null +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h @@ -0,0 +1,32 @@ +/* Generic implementation of the semaphore struct __semid_ds32. + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#if __WORDSIZE == 32 +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h new file mode 100644 index 0000000000..f65c9fc877 --- /dev/null +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h @@ -0,0 +1,32 @@ +/* x86 implementation of the semaphore struct __semid_ds32. + Copyright (C) 1995-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifdef __i386__ +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ +struct __semid_ds32 { + struct ipc_perm sem_perm; /* operation permission struct */ + __syscall_ulong_t sem_otime; /* last semop() time */ + __syscall_ulong_t sem_otime_high; /* last semop() time high */ + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ + __syscall_ulong_t __glibc_reserved3; + __syscall_ulong_t __glibc_reserved4; +}; +#endif -- 2.26.2 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall 2020-04-28 22:05 ` [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Alistair Francis @ 2020-04-29 21:09 ` Adhemerval Zanella 2020-04-29 23:24 ` Alistair Francis 0 siblings, 1 reply; 8+ messages in thread From: Adhemerval Zanella @ 2020-04-29 21:09 UTC (permalink / raw) To: libc-alpha, Alistair Francis, Alistair Francis, Arnd Bergmann On 28/04/2020 19:05, Alistair Francis via Libc-alpha wrote: > The semctl_syscall() function passes a union semun to the kernel. The > union includes struct semid_ds as a member. On 32-bit architectures the > Linux kernel provides a *_high version of the 32-bit sem_otime and > sem_ctime values. These can be combined to get a 64-bit version of the > time. > > This patch adjusts the struct semid_ds to support the *_high versions > of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t > this can be used to get a 64-bit time from the two 32-bit values. > > Due to alignment differences between 64-bit and 32-bit variables we > also need to set nsems to ensure it's correct. I think this approach might trigger an issue on semid_ds definition for time64 that I only noticed now. Since the idea of semctl is not use a different entrypoint neither to add aditional flag when issuing the syscall (either semctl or ipc), with this change we need to assure that __TIMESIZE == 32 sem_otime alignment matches __TIMESIZE == 64 one. However for semid_ds and msqid_ds time_t members can't not properly aligned to be expanded to 64-bit (shmid_ds has a shm_segsz field before the timestamp fields) due to the ipc_perm header consisting of 9 32-bit words except on parisc/powerpc/sparc. The alignment difference will make semctl once programs states build against a semid_ds with time_t being an 64-bit type. So we have 2 options here: 1. Keep the semid_ds layout as the kernel expected one and add the newer time64 timestamps at the *end*, and redefine the command arguments that passes a struct semid_ds to use (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds is a time64 one. The IPC_64 bit might be a feasible hack since kernel won't use on possible new commands. 2. Add a new semctl64 to handle the time64 one semid_ds. > --- > .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++ > .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++ > .../sysv/linux/powerpc/struct__semid_ds32.h | 32 +++++++++++++ > sysdeps/unix/sysv/linux/semctl.c | 47 +++++++++++++++++-- > .../sysv/linux/sparc/struct__semid_ds32.h | 32 +++++++++++++ > sysdeps/unix/sysv/linux/struct__semid_ds32.h | 32 +++++++++++++ > .../unix/sysv/linux/x86/struct__semid_ds32.h | 32 +++++++++++++ > 7 files changed, 233 insertions(+), 4 deletions(-) > create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h > create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > > diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > new file mode 100644 > index 0000000000..9eceaaff2d > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > @@ -0,0 +1,32 @@ > +/* HPPA implementation of the semaphore struct __semid_ds32. > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif No need to define it for __WORDSIZE == 32, the ABI just supports it anyway. > diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > new file mode 100644 > index 0000000000..2e3e2fc562 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > @@ -0,0 +1,30 @@ > +/* MIPS implementation of the semaphore struct __semid_ds32. > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime; /* last semop time */ > + __syscall_ulong_t sem_ctime; /* last change time */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t sem_otime_high; > + __syscall_ulong_t sem_ctime_high; > +}; > +#endif Ok, it cover mips64-n32 as well. > diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > new file mode 100644 > index 0000000000..f509db5a02 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > @@ -0,0 +1,32 @@ > +/* PowerPC implementation of the semaphore struct __semid_ds32. > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif Ok. > diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c > index 30571af49f..0634cc1abe 100644 > --- a/sysdeps/unix/sysv/linux/semctl.c > +++ b/sysdeps/unix/sysv/linux/semctl.c > @@ -22,8 +22,13 @@ > #include <sysdep.h> > #include <shlib-compat.h> > #include <errno.h> > +#include <struct__semid_ds32.h> > #include <linux/posix_types.h> /* For __kernel_mode_t. */ > > +#define IPC_TIME64 \ > + (__WORDSIZE == 32 && __TIMESIZE == 64 \ > + && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) I think it would be better to move this definition to the common ipc_priv.h header since it will most likely be used on msgctl and shmctl y2038 support as well. > + > /* Define a `union semun' suitable for Linux here. */ > union semun > { > @@ -44,13 +49,47 @@ union semun > static int > semctl_syscall (int semid, int semnum, int cmd, union semun arg) > { > + int ret; > +#if IPC_TIME64 I think we shoul add a comment stating why we need a auxiliary buffer for STAT/STAT_ANY operations. Something like: A temporary buffer is used to avoid both an issue where the export semid_ds might not have follow kernel expected layout (due sem_{o,c}time alignment in 64-bit time case) and the issue where some kernel version might not clear the high bits when returning then sem_{o,c}time information. > + struct __semid_ds32 tmp; > + struct semid_ds *orig; > + bool restore = false; > + if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY) > + { > + tmp = (struct __semid_ds32) { > + .sem_perm = arg.buf->sem_perm, > + .sem_otime = arg.buf->sem_otime, > + .sem_ctime = arg.buf->sem_ctime, > + .sem_nsems = arg.buf->sem_nsems, > + }; We need to fully initialize the temporary struct to avoid a kernel issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where kernel does not clear the timestamps high bits. > + orig = arg.buf; > + arg.buf = (struct semid_ds*)&tmp; Space before &tmp. > + restore = true; > + } > +#endif > + > #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS > - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > - arg.array); > + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > + arg.array); > #else > - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > - SEMCTL_ARG_ADDRESS (arg)); > + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > + SEMCTL_ARG_ADDRESS (arg)); > #endif Ok. > + > +#if IPC_TIME64 > + if (ret >= 0 && restore) > + { > + arg.buf = orig; > + arg.buf->sem_perm = tmp.sem_perm; > + arg.buf->sem_otime = tmp.sem_otime > + | ((time_t) tmp.sem_otime_high << 32); > + arg.buf->sem_ctime = tmp.sem_ctime > + | ((time_t) tmp.sem_ctime_high << 32); > + arg.buf->sem_nsems = tmp.sem_nsems; I think it would be better to use __time64_t explicit here. > + } > +#endif > + > + return ret; > } > > int > diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > new file mode 100644 > index 0000000000..f641825d37 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > @@ -0,0 +1,32 @@ > +/* Sparc implementation of the semaphore struct __semid_ds32. > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif Ok. > diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h > new file mode 100644 > index 0000000000..51ff83206d > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h > @@ -0,0 +1,32 @@ > +/* Generic implementation of the semaphore struct __semid_ds32. > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#if __WORDSIZE == 32 > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif Ok. > diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > new file mode 100644 > index 0000000000..f65c9fc877 > --- /dev/null > +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > @@ -0,0 +1,32 @@ > +/* x86 implementation of the semaphore struct __semid_ds32. > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + <https://www.gnu.org/licenses/>. */ > + > +#ifdef __i386__ > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > +struct __semid_ds32 { > + struct ipc_perm sem_perm; /* operation permission struct */ > + __syscall_ulong_t sem_otime; /* last semop() time */ > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > + __syscall_ulong_t __glibc_reserved3; > + __syscall_ulong_t __glibc_reserved4; > +}; > +#endif > Ok. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall 2020-04-29 21:09 ` Adhemerval Zanella @ 2020-04-29 23:24 ` Alistair Francis 2020-04-30 15:06 ` Adhemerval Zanella 0 siblings, 1 reply; 8+ messages in thread From: Alistair Francis @ 2020-04-29 23:24 UTC (permalink / raw) To: Adhemerval Zanella; +Cc: GNU C Library, Alistair Francis, Arnd Bergmann On Wed, Apr 29, 2020 at 2:09 PM Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote: > > > > On 28/04/2020 19:05, Alistair Francis via Libc-alpha wrote: > > The semctl_syscall() function passes a union semun to the kernel. The > > union includes struct semid_ds as a member. On 32-bit architectures the > > Linux kernel provides a *_high version of the 32-bit sem_otime and > > sem_ctime values. These can be combined to get a 64-bit version of the > > time. > > > > This patch adjusts the struct semid_ds to support the *_high versions > > of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t > > this can be used to get a 64-bit time from the two 32-bit values. > > > > Due to alignment differences between 64-bit and 32-bit variables we > > also need to set nsems to ensure it's correct. > > I think this approach might trigger an issue on semid_ds definition for > time64 that I only noticed now. > > Since the idea of semctl is not use a different entrypoint neither to add > aditional flag when issuing the syscall (either semctl or ipc), with this > change we need to assure that __TIMESIZE == 32 sem_otime alignment matches > __TIMESIZE == 64 one. I don't follow. We don't assume that sem_otime has the same allignment for __TIMESIZE == 32 and 64. In fact for RV32 they are not alligned the same. > > However for semid_ds and msqid_ds time_t members can't not properly aligned > to be expanded to 64-bit (shmid_ds has a shm_segsz field before the > timestamp fields) due to the ipc_perm header consisting of 9 32-bit words > except on parisc/powerpc/sparc. The alignment difference will make > semctl once programs states build against a semid_ds with time_t > being an 64-bit type. I am missing something here as well, as that is exactly what RV32 is testing and the glibc tests are passing (and a LInux rootFS boots). > > So we have 2 options here: > > 1. Keep the semid_ds layout as the kernel expected one and add the > newer time64 timestamps at the *end*, and redefine the command > arguments that passes a struct semid_ds to use > (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds > is a time64 one. The IPC_64 bit might be a feasible hack since > kernel won't use on possible new commands. > > 2. Add a new semctl64 to handle the time64 one semid_ds. > > > --- > > .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++ > > .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++ > > .../sysv/linux/powerpc/struct__semid_ds32.h | 32 +++++++++++++ > > sysdeps/unix/sysv/linux/semctl.c | 47 +++++++++++++++++-- > > .../sysv/linux/sparc/struct__semid_ds32.h | 32 +++++++++++++ > > sysdeps/unix/sysv/linux/struct__semid_ds32.h | 32 +++++++++++++ > > .../unix/sysv/linux/x86/struct__semid_ds32.h | 32 +++++++++++++ > > 7 files changed, 233 insertions(+), 4 deletions(-) > > create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > > create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > > create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > > create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > > create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h > > create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > > > > diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > > new file mode 100644 > > index 0000000000..9eceaaff2d > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > > @@ -0,0 +1,32 @@ > > +/* HPPA implementation of the semaphore struct __semid_ds32. > > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > > + This file is part of the GNU C Library. > > + > > + The GNU C Library is free software; you can redistribute it and/or > > + modify it under the terms of the GNU Lesser General Public > > + License as published by the Free Software Foundation; either > > + version 2.1 of the License, or (at your option) any later version. > > + > > + The GNU C Library is distributed in the hope that it will be useful, > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + Lesser General Public License for more details. > > + > > + You should have received a copy of the GNU Lesser General Public > > + License along with the GNU C Library; if not, see > > + <https://www.gnu.org/licenses/>. */ > > + > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > No need to define it for __WORDSIZE == 32, the ABI just supports it > anyway. Ok, I have removed these. > > > diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > > new file mode 100644 > > index 0000000000..2e3e2fc562 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > > @@ -0,0 +1,30 @@ > > +/* MIPS implementation of the semaphore struct __semid_ds32. > > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > > + This file is part of the GNU C Library. > > + > > + The GNU C Library is free software; you can redistribute it and/or > > + modify it under the terms of the GNU Lesser General Public > > + License as published by the Free Software Foundation; either > > + version 2.1 of the License, or (at your option) any later version. > > + > > + The GNU C Library is distributed in the hope that it will be useful, > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + Lesser General Public License for more details. > > + > > + You should have received a copy of the GNU Lesser General Public > > + License along with the GNU C Library; if not, see > > + <https://www.gnu.org/licenses/>. */ > > + > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime; /* last semop time */ > > + __syscall_ulong_t sem_ctime; /* last change time */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t sem_otime_high; > > + __syscall_ulong_t sem_ctime_high; > > +}; > > +#endif > > Ok, it cover mips64-n32 as well. > > > diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > > new file mode 100644 > > index 0000000000..f509db5a02 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > > @@ -0,0 +1,32 @@ > > +/* PowerPC implementation of the semaphore struct __semid_ds32. > > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > > + This file is part of the GNU C Library. > > + > > + The GNU C Library is free software; you can redistribute it and/or > > + modify it under the terms of the GNU Lesser General Public > > + License as published by the Free Software Foundation; either > > + version 2.1 of the License, or (at your option) any later version. > > + > > + The GNU C Library is distributed in the hope that it will be useful, > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + Lesser General Public License for more details. > > + > > + You should have received a copy of the GNU Lesser General Public > > + License along with the GNU C Library; if not, see > > + <https://www.gnu.org/licenses/>. */ > > + > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c > > index 30571af49f..0634cc1abe 100644 > > --- a/sysdeps/unix/sysv/linux/semctl.c > > +++ b/sysdeps/unix/sysv/linux/semctl.c > > @@ -22,8 +22,13 @@ > > #include <sysdep.h> > > #include <shlib-compat.h> > > #include <errno.h> > > +#include <struct__semid_ds32.h> > > #include <linux/posix_types.h> /* For __kernel_mode_t. */ > > > > +#define IPC_TIME64 \ > > + (__WORDSIZE == 32 && __TIMESIZE == 64 \ > > + && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) > > I think it would be better to move this definition to the common > ipc_priv.h header since it will most likely be used on msgctl > and shmctl y2038 support as well. Done. > > > + > > /* Define a `union semun' suitable for Linux here. */ > > union semun > > { > > @@ -44,13 +49,47 @@ union semun > > static int > > semctl_syscall (int semid, int semnum, int cmd, union semun arg) > > { > > + int ret; > > +#if IPC_TIME64 > > I think we shoul add a comment stating why we need a auxiliary buffer > for STAT/STAT_ANY operations. Something like: > > A temporary buffer is used to avoid both an issue where the export > semid_ds might not have follow kernel expected layout (due > sem_{o,c}time alignment in 64-bit time case) and the issue where > some kernel version might not clear the high bits when returning > then sem_{o,c}time information. Added > > > + struct __semid_ds32 tmp; > > + struct semid_ds *orig; > > + bool restore = false; > > + if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY) > > + { > > + tmp = (struct __semid_ds32) { > > + .sem_perm = arg.buf->sem_perm, > > + .sem_otime = arg.buf->sem_otime, > > + .sem_ctime = arg.buf->sem_ctime, > > + .sem_nsems = arg.buf->sem_nsems, > > + }; > > We need to fully initialize the temporary struct to avoid a kernel > issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where > kernel does not clear the timestamps high bits. Added. > > > + orig = arg.buf; > > + arg.buf = (struct semid_ds*)&tmp; > > Space before &tmp. Added. > > > + restore = true; > > + } > > +#endif > > + > > #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS > > - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > > - arg.array); > > + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > > + arg.array); > > #else > > - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > > - SEMCTL_ARG_ADDRESS (arg)); > > + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > > + SEMCTL_ARG_ADDRESS (arg)); > > #endif > > Ok. > > > + > > +#if IPC_TIME64 > > + if (ret >= 0 && restore) > > + { > > + arg.buf = orig; > > + arg.buf->sem_perm = tmp.sem_perm; > > + arg.buf->sem_otime = tmp.sem_otime > > + | ((time_t) tmp.sem_otime_high << 32); > > + arg.buf->sem_ctime = tmp.sem_ctime > > + | ((time_t) tmp.sem_ctime_high << 32); > > + arg.buf->sem_nsems = tmp.sem_nsems; > > I think it would be better to use __time64_t explicit here. Done. Alistair > > > + } > > +#endif > > + > > + return ret; > > } > > > > int > > diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > > new file mode 100644 > > index 0000000000..f641825d37 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > > @@ -0,0 +1,32 @@ > > +/* Sparc implementation of the semaphore struct __semid_ds32. > > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > > + This file is part of the GNU C Library. > > + > > + The GNU C Library is free software; you can redistribute it and/or > > + modify it under the terms of the GNU Lesser General Public > > + License as published by the Free Software Foundation; either > > + version 2.1 of the License, or (at your option) any later version. > > + > > + The GNU C Library is distributed in the hope that it will be useful, > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + Lesser General Public License for more details. > > + > > + You should have received a copy of the GNU Lesser General Public > > + License along with the GNU C Library; if not, see > > + <https://www.gnu.org/licenses/>. */ > > + > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h > > new file mode 100644 > > index 0000000000..51ff83206d > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h > > @@ -0,0 +1,32 @@ > > +/* Generic implementation of the semaphore struct __semid_ds32. > > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > > + This file is part of the GNU C Library. > > + > > + The GNU C Library is free software; you can redistribute it and/or > > + modify it under the terms of the GNU Lesser General Public > > + License as published by the Free Software Foundation; either > > + version 2.1 of the License, or (at your option) any later version. > > + > > + The GNU C Library is distributed in the hope that it will be useful, > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + Lesser General Public License for more details. > > + > > + You should have received a copy of the GNU Lesser General Public > > + License along with the GNU C Library; if not, see > > + <https://www.gnu.org/licenses/>. */ > > + > > +#if __WORDSIZE == 32 > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > Ok. > > > diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > > new file mode 100644 > > index 0000000000..f65c9fc877 > > --- /dev/null > > +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > > @@ -0,0 +1,32 @@ > > +/* x86 implementation of the semaphore struct __semid_ds32. > > + Copyright (C) 1995-2020 Free Software Foundation, Inc. > > + This file is part of the GNU C Library. > > + > > + The GNU C Library is free software; you can redistribute it and/or > > + modify it under the terms of the GNU Lesser General Public > > + License as published by the Free Software Foundation; either > > + version 2.1 of the License, or (at your option) any later version. > > + > > + The GNU C Library is distributed in the hope that it will be useful, > > + but WITHOUT ANY WARRANTY; without even the implied warranty of > > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > + Lesser General Public License for more details. > > + > > + You should have received a copy of the GNU Lesser General Public > > + License along with the GNU C Library; if not, see > > + <https://www.gnu.org/licenses/>. */ > > + > > +#ifdef __i386__ > > +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > > + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > > +struct __semid_ds32 { > > + struct ipc_perm sem_perm; /* operation permission struct */ > > + __syscall_ulong_t sem_otime; /* last semop() time */ > > + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > > + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > > + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > > + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > > + __syscall_ulong_t __glibc_reserved3; > > + __syscall_ulong_t __glibc_reserved4; > > +}; > > +#endif > > > > Ok. > > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall 2020-04-29 23:24 ` Alistair Francis @ 2020-04-30 15:06 ` Adhemerval Zanella 2020-04-30 21:25 ` Alistair Francis 0 siblings, 1 reply; 8+ messages in thread From: Adhemerval Zanella @ 2020-04-30 15:06 UTC (permalink / raw) To: Alistair Francis; +Cc: GNU C Library, Alistair Francis, Arnd Bergmann On 29/04/2020 20:24, Alistair Francis wrote: > On Wed, Apr 29, 2020 at 2:09 PM Adhemerval Zanella > <adhemerval.zanella@linaro.org> wrote: >> >> >> >> On 28/04/2020 19:05, Alistair Francis via Libc-alpha wrote: >>> The semctl_syscall() function passes a union semun to the kernel. The >>> union includes struct semid_ds as a member. On 32-bit architectures the >>> Linux kernel provides a *_high version of the 32-bit sem_otime and >>> sem_ctime values. These can be combined to get a 64-bit version of the >>> time. >>> >>> This patch adjusts the struct semid_ds to support the *_high versions >>> of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t >>> this can be used to get a 64-bit time from the two 32-bit values. >>> >>> Due to alignment differences between 64-bit and 32-bit variables we >>> also need to set nsems to ensure it's correct. >> >> I think this approach might trigger an issue on semid_ds definition for >> time64 that I only noticed now. >> >> Since the idea of semctl is not use a different entrypoint neither to add >> aditional flag when issuing the syscall (either semctl or ipc), with this >> change we need to assure that __TIMESIZE == 32 sem_otime alignment matches >> __TIMESIZE == 64 one. > > I don't follow. We don't assume that sem_otime has the same allignment > for __TIMESIZE == 32 and 64. In fact for RV32 they are not alligned > the same. > >> >> However for semid_ds and msqid_ds time_t members can't not properly aligned >> to be expanded to 64-bit (shmid_ds has a shm_segsz field before the >> timestamp fields) due to the ipc_perm header consisting of 9 32-bit words >> except on parisc/powerpc/sparc. The alignment difference will make >> semctl once programs states build against a semid_ds with time_t >> being an 64-bit type. > > I am missing something here as well, as that is exactly what RV32 is > testing and the glibc tests are passing (and a LInux rootFS boots). The issue is for architectures that might select the __TIMESIZE at build time, so two different semid_ds structure might be used with semctl. For instance, on arm with current scheme: For __TIMESIZE == 32: sizeof (struct ipc_perm): 36 sizeof (struct semid_ds): 72 offsetof (struct semid_ds, sem_perm): 0 offsetof (struct semid_ds, sem_otime): 40 offsetof (struct semid_ds, sem_ctime): 48 offsetof (struct semid_ds, sem_nsems): 56 For __TIMESIZE == 64: sizeof (struct ipc_perm): 36 sizeof (struct semid_ds): 64 offsetof (struct semid_ds, sem_perm): 0 offsetof (struct semid_ds, sem_otime): 36 offsetof (struct semid_ds, sem_ctime): 44 offsetof (struct semid_ds, sem_nsems): 52 The syscall itself will use the expected structure, however the code: if (ret >= 0 && restore) { arg.buf = orig; arg.buf->sem_perm = tmp.sem_perm; arg.buf->sem_otime = tmp.sem_otime | ((time_t) tmp.sem_otime_high << 32); arg.buf->sem_ctime = tmp.sem_ctime | ((time_t) tmp.sem_ctime_high << 32); arg.buf->sem_nsems = tmp.sem_nsems; will write down the timestamps on wrong place for time64 timestamps. This is not an issue for 32-bit architectures that does not have support for 32-bit time_t (as RV32). > >> >> So we have 2 options here: >> >> 1. Keep the semid_ds layout as the kernel expected one and add the >> newer time64 timestamps at the *end*, and redefine the command >> arguments that passes a struct semid_ds to use >> (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds >> is a time64 one. The IPC_64 bit might be a feasible hack since >> kernel won't use on possible new commands. This solution would require to redefine IPC_STAT, SEM_STAT, SEM_STAT_ANY to a different value for when building for __TIMESIZE==64 on ABIs that support its selection. The easiest way would to parametrize the ipc commands that handle per architecture: /* On each ABI that supports __TIMESIZE==32. */ #if __TIMESIZE == 64 # define __IPC_CMD_TIME_64 0x100 /* Same as __IPC_64. */ #else # define __IPC_CMD_TIME_64 0x0 #endif #define __IPC_TIME_64 1 If fro architecture only support __TIMESIZE64 (default): #define __IPC_CMD_TIME64 0x0 #define __IPC_TIME_64 0 Then on Linux ipc.h: #define IPC_STAT (2 | __IPC_CMD_TIME_64) Same for sem.h: #define SEM_STAT (18 | __IPC_CMD_TIME_64) #define SEM_STAT_ANY (20 | __IPC_CMD_TIME_64) Then on semctl.c (totally untested): --- union semun { int val; /* value for SETVAL */ #if __IPC_TIME_64 struct __semid_ds32 *buf32; #endif struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ unsigned short int *array; /* array for GETALL & SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; int __new_semctl (int semid, int semnum, int cmd, ...) { /* POSIX states ipc_perm mode should have type of mode_t. */ _Static_assert (sizeof ((struct semid_ds){0}.sem_perm.mode) == sizeof (mode_t), "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)"); union semun arg = { 0 }; va_list ap; /* Get the argument only if required. Ignore the __IPC_STAT_64. */ switch (cmd & ~__IPC_CMD_TIME_64) { case SETVAL: /* arg.val */ case GETALL: /* arg.array */ case SETALL: case IPC_STAT & ~__IPC_CMD_TIME_64: /* arg.buf */ case IPC_SET: case SEM_STAT & ~__IPC_CMD_TIME_64: case IPC_INFO: /* arg.__buf */ case SEM_INFO: va_start (ap, cmd); arg = va_arg (ap, union semun); va_end (ap); break; } #ifdef __IPC_TIME_64 struct __semid_ds32 tmp32; struct __semid_ds64 *orig64; if (cmd & __IPC_STAT_64) { tmp32 = (struct __semid_ds32) { 0 }; orig64 = (struct __semid_ds64 *) arg.buf; arg.buf32 = tmp32; } #endif #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T struct semid_ds tmpds; if (cmd == IPC_SET) { tmpds = *arg.buf; tmpds.sem_perm.mode *= 0x10000U; arg.buf = &tmpds; } #endif int ret = semctl_syscall (semid, semnum, cmd & ~__IPC_CMD_TIME_64, arg); if (ret < 0) return ret; switch (cmd & ~__IPC_CMD_TIME_64) { case IPC_STAT: case SEM_STAT: case SEM_STAT_ANY: #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T # if __IPC_TIME_64 arg.buf32->sem_perm.mode >>= 16; # else arg.buf->sem_perm.mode >>= 16; # endif #else /* Old Linux kernel versions might not clear the mode padding. */ if (sizeof ((struct semid_ds){0}.sem_perm.mode) ! = sizeof (__kernel_mode_t)) # if __IPC_TIME_64 arg.buf32->sem_perm.mode &= 0xFFFF; # else arg.buf->sem_perm.mode &= 0xFFFF; # endif #endif } #ifdef __IPC_TIME_64 if (cmd & & ~__IPC_CMD_TIME_64) { orig64->sem_perm = tmp32.sem_perm; orig64->sem_otime = tmp32.sem_otime | ((__time64_t) tmp32.sem_otime_high << 32); orig64->sem_ctime = tmp32.sem_ctime | ((__time64_t) tmp32.sem_ctime_high << 32); orig64->sem_nsems = tmp32.sem_nsems; arg.buf = (struct semid_ds *) orig64; } #endif return ret; } --- So basically: 1. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with IPC_STAT without _IPC_CMD_TIME_64, the provided semid_ds buffe will be used directly on the syscall. This is the case for 64-bit architectures and 32-bit architecture without __TIMESIZE==32 support (RV32 for instance). 2. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with IPC_STAT with _IPC_CMD_TIME_64 then __TIMESIZE==64 is implied. A temporary __semid_ds32 will be used to issue the syscall and its contents will be copied to users semid_ds buffer (which is also implied to be the __TIMESIZE==64). There is the requeriment to use define __semid_ds64 that uses __time64_t explicitly for architecture that support __TIMESIZE==32. (The handling of __ASSUME_SYSVIPC_BROKEN_MODE_T and the kernel issue regarding sem_perm.mode clearing could be improved/simplified). >> >> 2. Add a new semctl64 to handle the time64 one semid_ds. >> >>> --- >>> .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++ >>> .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++ >>> .../sysv/linux/powerpc/struct__semid_ds32.h | 32 +++++++++++++ >>> sysdeps/unix/sysv/linux/semctl.c | 47 +++++++++++++++++-- >>> .../sysv/linux/sparc/struct__semid_ds32.h | 32 +++++++++++++ >>> sysdeps/unix/sysv/linux/struct__semid_ds32.h | 32 +++++++++++++ >>> .../unix/sysv/linux/x86/struct__semid_ds32.h | 32 +++++++++++++ >>> 7 files changed, 233 insertions(+), 4 deletions(-) >>> create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h >>> create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h >>> >>> diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..9eceaaff2d >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* HPPA implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. >>> + This file is part of the GNU C Library. >>> + >>> + The GNU C Library is free software; you can redistribute it and/or >>> + modify it under the terms of the GNU Lesser General Public >>> + License as published by the Free Software Foundation; either >>> + version 2.1 of the License, or (at your option) any later version. >>> + >>> + The GNU C Library is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>> + Lesser General Public License for more details. >>> + >>> + You should have received a copy of the GNU Lesser General Public >>> + License along with the GNU C Library; if not, see >>> + <https://www.gnu.org/licenses/>. */ >>> + >>> +#if __WORDSIZE == 32 >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ >>> +struct __semid_ds32 { >>> + struct ipc_perm sem_perm; /* operation permission struct */ >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ >>> + __syscall_ulong_t sem_otime; /* last semop() time */ >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ >>> + __syscall_ulong_t __glibc_reserved3; >>> + __syscall_ulong_t __glibc_reserved4; >>> +}; >>> +#endif >> >> No need to define it for __WORDSIZE == 32, the ABI just supports it >> anyway. > > Ok, I have removed these. > >> >>> diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..2e3e2fc562 >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h >>> @@ -0,0 +1,30 @@ >>> +/* MIPS implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. >>> + This file is part of the GNU C Library. >>> + >>> + The GNU C Library is free software; you can redistribute it and/or >>> + modify it under the terms of the GNU Lesser General Public >>> + License as published by the Free Software Foundation; either >>> + version 2.1 of the License, or (at your option) any later version. >>> + >>> + The GNU C Library is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>> + Lesser General Public License for more details. >>> + >>> + You should have received a copy of the GNU Lesser General Public >>> + License along with the GNU C Library; if not, see >>> + <https://www.gnu.org/licenses/>. */ >>> + >>> +#if __WORDSIZE == 32 >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ >>> +struct __semid_ds32 { >>> + struct ipc_perm sem_perm; /* operation permission struct */ >>> + __syscall_ulong_t sem_otime; /* last semop time */ >>> + __syscall_ulong_t sem_ctime; /* last change time */ >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ >>> + __syscall_ulong_t sem_otime_high; >>> + __syscall_ulong_t sem_ctime_high; >>> +}; >>> +#endif >> >> Ok, it cover mips64-n32 as well. >> >>> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..f509db5a02 >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* PowerPC implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. >>> + This file is part of the GNU C Library. >>> + >>> + The GNU C Library is free software; you can redistribute it and/or >>> + modify it under the terms of the GNU Lesser General Public >>> + License as published by the Free Software Foundation; either >>> + version 2.1 of the License, or (at your option) any later version. >>> + >>> + The GNU C Library is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>> + Lesser General Public License for more details. >>> + >>> + You should have received a copy of the GNU Lesser General Public >>> + License along with the GNU C Library; if not, see >>> + <https://www.gnu.org/licenses/>. */ >>> + >>> +#if __WORDSIZE == 32 >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ >>> +struct __semid_ds32 { >>> + struct ipc_perm sem_perm; /* operation permission struct */ >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ >>> + __syscall_ulong_t sem_otime; /* last semop() time */ >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ >>> + __syscall_ulong_t __glibc_reserved3; >>> + __syscall_ulong_t __glibc_reserved4; >>> +}; >>> +#endif >> >> Ok. >> >>> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c >>> index 30571af49f..0634cc1abe 100644 >>> --- a/sysdeps/unix/sysv/linux/semctl.c >>> +++ b/sysdeps/unix/sysv/linux/semctl.c >>> @@ -22,8 +22,13 @@ >>> #include <sysdep.h> >>> #include <shlib-compat.h> >>> #include <errno.h> >>> +#include <struct__semid_ds32.h> >>> #include <linux/posix_types.h> /* For __kernel_mode_t. */ >>> >>> +#define IPC_TIME64 \ >>> + (__WORDSIZE == 32 && __TIMESIZE == 64 \ >>> + && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) >> >> I think it would be better to move this definition to the common >> ipc_priv.h header since it will most likely be used on msgctl >> and shmctl y2038 support as well. > > Done. > >> >>> + >>> /* Define a `union semun' suitable for Linux here. */ >>> union semun >>> { >>> @@ -44,13 +49,47 @@ union semun >>> static int >>> semctl_syscall (int semid, int semnum, int cmd, union semun arg) >>> { >>> + int ret; >>> +#if IPC_TIME64 >> >> I think we shoul add a comment stating why we need a auxiliary buffer >> for STAT/STAT_ANY operations. Something like: >> >> A temporary buffer is used to avoid both an issue where the export >> semid_ds might not have follow kernel expected layout (due >> sem_{o,c}time alignment in 64-bit time case) and the issue where >> some kernel version might not clear the high bits when returning >> then sem_{o,c}time information. > > Added > >> >>> + struct __semid_ds32 tmp; >>> + struct semid_ds *orig; >>> + bool restore = false; >>> + if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY) >>> + { >>> + tmp = (struct __semid_ds32) { >>> + .sem_perm = arg.buf->sem_perm, >>> + .sem_otime = arg.buf->sem_otime, >>> + .sem_ctime = arg.buf->sem_ctime, >>> + .sem_nsems = arg.buf->sem_nsems, >>> + }; >> >> We need to fully initialize the temporary struct to avoid a kernel >> issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where >> kernel does not clear the timestamps high bits. > > Added. > >> >>> + orig = arg.buf; >>> + arg.buf = (struct semid_ds*)&tmp; >> >> Space before &tmp. > > Added. > >> >>> + restore = true; >>> + } >>> +#endif >>> + >>> #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS >>> - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, >>> - arg.array); >>> + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, >>> + arg.array); >>> #else >>> - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, >>> - SEMCTL_ARG_ADDRESS (arg)); >>> + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, >>> + SEMCTL_ARG_ADDRESS (arg)); >>> #endif >> >> Ok. >> >>> + >>> +#if IPC_TIME64 >>> + if (ret >= 0 && restore) >>> + { >>> + arg.buf = orig; >>> + arg.buf->sem_perm = tmp.sem_perm; >>> + arg.buf->sem_otime = tmp.sem_otime >>> + | ((time_t) tmp.sem_otime_high << 32); >>> + arg.buf->sem_ctime = tmp.sem_ctime >>> + | ((time_t) tmp.sem_ctime_high << 32); >>> + arg.buf->sem_nsems = tmp.sem_nsems; >> >> I think it would be better to use __time64_t explicit here. > > Done. > > Alistair > >> >>> + } >>> +#endif >>> + >>> + return ret; >>> } >>> >>> int >>> diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..f641825d37 >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* Sparc implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. >>> + This file is part of the GNU C Library. >>> + >>> + The GNU C Library is free software; you can redistribute it and/or >>> + modify it under the terms of the GNU Lesser General Public >>> + License as published by the Free Software Foundation; either >>> + version 2.1 of the License, or (at your option) any later version. >>> + >>> + The GNU C Library is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>> + Lesser General Public License for more details. >>> + >>> + You should have received a copy of the GNU Lesser General Public >>> + License along with the GNU C Library; if not, see >>> + <https://www.gnu.org/licenses/>. */ >>> + >>> +#if __WORDSIZE == 32 >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ >>> +struct __semid_ds32 { >>> + struct ipc_perm sem_perm; /* operation permission struct */ >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ >>> + __syscall_ulong_t sem_otime; /* last semop() time */ >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ >>> + __syscall_ulong_t __glibc_reserved3; >>> + __syscall_ulong_t __glibc_reserved4; >>> +}; >>> +#endif >> >> Ok. >> >>> diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..51ff83206d >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* Generic implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. >>> + This file is part of the GNU C Library. >>> + >>> + The GNU C Library is free software; you can redistribute it and/or >>> + modify it under the terms of the GNU Lesser General Public >>> + License as published by the Free Software Foundation; either >>> + version 2.1 of the License, or (at your option) any later version. >>> + >>> + The GNU C Library is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>> + Lesser General Public License for more details. >>> + >>> + You should have received a copy of the GNU Lesser General Public >>> + License along with the GNU C Library; if not, see >>> + <https://www.gnu.org/licenses/>. */ >>> + >>> +#if __WORDSIZE == 32 >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ >>> +struct __semid_ds32 { >>> + struct ipc_perm sem_perm; /* operation permission struct */ >>> + __syscall_ulong_t sem_otime; /* last semop() time */ >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ >>> + __syscall_ulong_t __glibc_reserved3; >>> + __syscall_ulong_t __glibc_reserved4; >>> +}; >>> +#endif >> >> Ok. >> >>> diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h >>> new file mode 100644 >>> index 0000000000..f65c9fc877 >>> --- /dev/null >>> +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h >>> @@ -0,0 +1,32 @@ >>> +/* x86 implementation of the semaphore struct __semid_ds32. >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. >>> + This file is part of the GNU C Library. >>> + >>> + The GNU C Library is free software; you can redistribute it and/or >>> + modify it under the terms of the GNU Lesser General Public >>> + License as published by the Free Software Foundation; either >>> + version 2.1 of the License, or (at your option) any later version. >>> + >>> + The GNU C Library is distributed in the hope that it will be useful, >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU >>> + Lesser General Public License for more details. >>> + >>> + You should have received a copy of the GNU Lesser General Public >>> + License along with the GNU C Library; if not, see >>> + <https://www.gnu.org/licenses/>. */ >>> + >>> +#ifdef __i386__ >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ >>> +struct __semid_ds32 { >>> + struct ipc_perm sem_perm; /* operation permission struct */ >>> + __syscall_ulong_t sem_otime; /* last semop() time */ >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ >>> + __syscall_ulong_t __glibc_reserved3; >>> + __syscall_ulong_t __glibc_reserved4; >>> +}; >>> +#endif >>> >> >> Ok. >> >> ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall 2020-04-30 15:06 ` Adhemerval Zanella @ 2020-04-30 21:25 ` Alistair Francis 0 siblings, 0 replies; 8+ messages in thread From: Alistair Francis @ 2020-04-30 21:25 UTC (permalink / raw) To: Adhemerval Zanella; +Cc: GNU C Library, Alistair Francis, Arnd Bergmann On Thu, Apr 30, 2020 at 8:06 AM Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote: > > > > On 29/04/2020 20:24, Alistair Francis wrote: > > On Wed, Apr 29, 2020 at 2:09 PM Adhemerval Zanella > > <adhemerval.zanella@linaro.org> wrote: > >> > >> > >> > >> On 28/04/2020 19:05, Alistair Francis via Libc-alpha wrote: > >>> The semctl_syscall() function passes a union semun to the kernel. The > >>> union includes struct semid_ds as a member. On 32-bit architectures the > >>> Linux kernel provides a *_high version of the 32-bit sem_otime and > >>> sem_ctime values. These can be combined to get a 64-bit version of the > >>> time. > >>> > >>> This patch adjusts the struct semid_ds to support the *_high versions > >>> of sem_otime and sem_ctime. For 32-bit systems with a 64-bit time_t > >>> this can be used to get a 64-bit time from the two 32-bit values. > >>> > >>> Due to alignment differences between 64-bit and 32-bit variables we > >>> also need to set nsems to ensure it's correct. > >> > >> I think this approach might trigger an issue on semid_ds definition for > >> time64 that I only noticed now. > >> > >> Since the idea of semctl is not use a different entrypoint neither to add > >> aditional flag when issuing the syscall (either semctl or ipc), with this > >> change we need to assure that __TIMESIZE == 32 sem_otime alignment matches > >> __TIMESIZE == 64 one. > > > > I don't follow. We don't assume that sem_otime has the same allignment > > for __TIMESIZE == 32 and 64. In fact for RV32 they are not alligned > > the same. > > > >> > >> However for semid_ds and msqid_ds time_t members can't not properly aligned > >> to be expanded to 64-bit (shmid_ds has a shm_segsz field before the > >> timestamp fields) due to the ipc_perm header consisting of 9 32-bit words > >> except on parisc/powerpc/sparc. The alignment difference will make > >> semctl once programs states build against a semid_ds with time_t > >> being an 64-bit type. > > > > I am missing something here as well, as that is exactly what RV32 is > > testing and the glibc tests are passing (and a LInux rootFS boots). > > The issue is for architectures that might select the __TIMESIZE at build > time, so two different semid_ds structure might be used with semctl. > For instance, on arm with current scheme: > > For __TIMESIZE == 32: > sizeof (struct ipc_perm): 36 > sizeof (struct semid_ds): 72 > offsetof (struct semid_ds, sem_perm): 0 > offsetof (struct semid_ds, sem_otime): 40 > offsetof (struct semid_ds, sem_ctime): 48 > offsetof (struct semid_ds, sem_nsems): 56 > > For __TIMESIZE == 64: > sizeof (struct ipc_perm): 36 > sizeof (struct semid_ds): 64 > offsetof (struct semid_ds, sem_perm): 0 > offsetof (struct semid_ds, sem_otime): 36 > offsetof (struct semid_ds, sem_ctime): 44 > offsetof (struct semid_ds, sem_nsems): 52 > > The syscall itself will use the expected structure, however the code: > > if (ret >= 0 && restore) > { > arg.buf = orig; > arg.buf->sem_perm = tmp.sem_perm; > arg.buf->sem_otime = tmp.sem_otime > | ((time_t) tmp.sem_otime_high << 32); > arg.buf->sem_ctime = tmp.sem_ctime > | ((time_t) tmp.sem_ctime_high << 32); > arg.buf->sem_nsems = tmp.sem_nsems; > > will write down the timestamps on wrong place for time64 timestamps. Ok, I think I understand now. > > This is not an issue for 32-bit architectures that does not have > support for 32-bit time_t (as RV32). > > > > >> > >> So we have 2 options here: > >> > >> 1. Keep the semid_ds layout as the kernel expected one and add the > >> newer time64 timestamps at the *end*, and redefine the command > >> arguments that passes a struct semid_ds to use > >> (IPC_STAT, SEM_STAT, SEM_STAT_ANY) to indicate that the semid_ds > >> is a time64 one. The IPC_64 bit might be a feasible hack since > >> kernel won't use on possible new commands. > > This solution would require to redefine IPC_STAT, SEM_STAT, SEM_STAT_ANY to > a different value for when building for __TIMESIZE==64 on ABIs that support > its selection. The easiest way would to parametrize the ipc commands > that handle per architecture: > > /* On each ABI that supports __TIMESIZE==32. */ > #if __TIMESIZE == 64 > # define __IPC_CMD_TIME_64 0x100 /* Same as __IPC_64. */ > #else > # define __IPC_CMD_TIME_64 0x0 > #endif > #define __IPC_TIME_64 1 So this should be for every __WORDSIZE ==32 except RV32? I'm not sure of a good place to put this though > > If fro architecture only support __TIMESIZE64 (default): > > #define __IPC_CMD_TIME64 0x0 > #define __IPC_TIME_64 0 For all __WORDSIZE == 64 and RV32. I have this in ipc_priv.h (before the include sys/ipc.h) but I'm not sure if that will work, testing now. > > Then on Linux ipc.h: > > #define IPC_STAT (2 | __IPC_CMD_TIME_64) Done. > > Same for sem.h: > > #define SEM_STAT (18 | __IPC_CMD_TIME_64) > #define SEM_STAT_ANY (20 | __IPC_CMD_TIME_64) Done. > > Then on semctl.c (totally untested): > > --- > union semun > { > int val; /* value for SETVAL */ > #if __IPC_TIME_64 > struct __semid_ds32 *buf32; > #endif > struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ > unsigned short int *array; /* array for GETALL & SETALL */ > struct seminfo *__buf; /* buffer for IPC_INFO */ > }; > > int > __new_semctl (int semid, int semnum, int cmd, ...) > { > /* POSIX states ipc_perm mode should have type of mode_t. */ > _Static_assert (sizeof ((struct semid_ds){0}.sem_perm.mode) > == sizeof (mode_t), > "sizeof (msqid_ds.msg_perm.mode) != sizeof (mode_t)"); > > union semun arg = { 0 }; > va_list ap; > > /* Get the argument only if required. Ignore the __IPC_STAT_64. */ > switch (cmd & ~__IPC_CMD_TIME_64) > { > case SETVAL: /* arg.val */ > case GETALL: /* arg.array */ > case SETALL: > case IPC_STAT & ~__IPC_CMD_TIME_64: /* arg.buf */ > case IPC_SET: > case SEM_STAT & ~__IPC_CMD_TIME_64: > case IPC_INFO: /* arg.__buf */ > case SEM_INFO: > va_start (ap, cmd); > arg = va_arg (ap, union semun); > va_end (ap); > break; > } > > #ifdef __IPC_TIME_64 > struct __semid_ds32 tmp32; > struct __semid_ds64 *orig64; > if (cmd & __IPC_STAT_64) > { > tmp32 = (struct __semid_ds32) { 0 }; > orig64 = (struct __semid_ds64 *) arg.buf; > arg.buf32 = tmp32; > } > #endif > > #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T > struct semid_ds tmpds; > if (cmd == IPC_SET) > { > tmpds = *arg.buf; > tmpds.sem_perm.mode *= 0x10000U; > arg.buf = &tmpds; > } > #endif > > int ret = semctl_syscall (semid, semnum, cmd & ~__IPC_CMD_TIME_64, arg); > if (ret < 0) > return ret; > > switch (cmd & ~__IPC_CMD_TIME_64) > { > case IPC_STAT: > case SEM_STAT: > case SEM_STAT_ANY: > #ifdef __ASSUME_SYSVIPC_BROKEN_MODE_T > # if __IPC_TIME_64 > arg.buf32->sem_perm.mode >>= 16; > # else > arg.buf->sem_perm.mode >>= 16; > # endif > #else > /* Old Linux kernel versions might not clear the mode padding. */ > if (sizeof ((struct semid_ds){0}.sem_perm.mode) > ! = sizeof (__kernel_mode_t)) > # if __IPC_TIME_64 > arg.buf32->sem_perm.mode &= 0xFFFF; > # else > arg.buf->sem_perm.mode &= 0xFFFF; > # endif > #endif > } > > #ifdef __IPC_TIME_64 > if (cmd & & ~__IPC_CMD_TIME_64) > { > orig64->sem_perm = tmp32.sem_perm; > orig64->sem_otime = tmp32.sem_otime > | ((__time64_t) tmp32.sem_otime_high << 32); > orig64->sem_ctime = tmp32.sem_ctime > | ((__time64_t) tmp32.sem_ctime_high << 32); > orig64->sem_nsems = tmp32.sem_nsems; > arg.buf = (struct semid_ds *) orig64; > } > #endif > > return ret; > } Ok, compile testing now. Alistair > --- > > So basically: > > 1. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with > IPC_STAT without _IPC_CMD_TIME_64, the provided semid_ds buffe > will be used directly on the syscall. This is the case for > 64-bit architectures and 32-bit architecture without > __TIMESIZE==32 support (RV32 for instance). > > 2. If an ABI issues 'semctl (semid, semnum, IPC_STAT, ...)' with > IPC_STAT with _IPC_CMD_TIME_64 then __TIMESIZE==64 is implied. > A temporary __semid_ds32 will be used to issue the syscall and its > contents will be copied to users semid_ds buffer (which is also > implied to be the __TIMESIZE==64). > > There is the requeriment to use define __semid_ds64 that uses __time64_t > explicitly for architecture that support __TIMESIZE==32. > > (The handling of __ASSUME_SYSVIPC_BROKEN_MODE_T and the kernel issue > regarding sem_perm.mode clearing could be improved/simplified). > > >> > >> 2. Add a new semctl64 to handle the time64 one semid_ds. > >> > >>> --- > >>> .../unix/sysv/linux/hppa/struct__semid_ds32.h | 32 +++++++++++++ > >>> .../unix/sysv/linux/mips/struct__semid_ds32.h | 30 ++++++++++++ > >>> .../sysv/linux/powerpc/struct__semid_ds32.h | 32 +++++++++++++ > >>> sysdeps/unix/sysv/linux/semctl.c | 47 +++++++++++++++++-- > >>> .../sysv/linux/sparc/struct__semid_ds32.h | 32 +++++++++++++ > >>> sysdeps/unix/sysv/linux/struct__semid_ds32.h | 32 +++++++++++++ > >>> .../unix/sysv/linux/x86/struct__semid_ds32.h | 32 +++++++++++++ > >>> 7 files changed, 233 insertions(+), 4 deletions(-) > >>> create mode 100644 sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > >>> create mode 100644 sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > >>> create mode 100644 sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > >>> create mode 100644 sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > >>> create mode 100644 sysdeps/unix/sysv/linux/struct__semid_ds32.h > >>> create mode 100644 sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > >>> > >>> diff --git a/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > >>> new file mode 100644 > >>> index 0000000000..9eceaaff2d > >>> --- /dev/null > >>> +++ b/sysdeps/unix/sysv/linux/hppa/struct__semid_ds32.h > >>> @@ -0,0 +1,32 @@ > >>> +/* HPPA implementation of the semaphore struct __semid_ds32. > >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. > >>> + This file is part of the GNU C Library. > >>> + > >>> + The GNU C Library is free software; you can redistribute it and/or > >>> + modify it under the terms of the GNU Lesser General Public > >>> + License as published by the Free Software Foundation; either > >>> + version 2.1 of the License, or (at your option) any later version. > >>> + > >>> + The GNU C Library is distributed in the hope that it will be useful, > >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of > >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > >>> + Lesser General Public License for more details. > >>> + > >>> + You should have received a copy of the GNU Lesser General Public > >>> + License along with the GNU C Library; if not, see > >>> + <https://www.gnu.org/licenses/>. */ > >>> + > >>> +#if __WORDSIZE == 32 > >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > >>> +struct __semid_ds32 { > >>> + struct ipc_perm sem_perm; /* operation permission struct */ > >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > >>> + __syscall_ulong_t sem_otime; /* last semop() time */ > >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > >>> + __syscall_ulong_t __glibc_reserved3; > >>> + __syscall_ulong_t __glibc_reserved4; > >>> +}; > >>> +#endif > >> > >> No need to define it for __WORDSIZE == 32, the ABI just supports it > >> anyway. > > > > Ok, I have removed these. > > > >> > >>> diff --git a/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > >>> new file mode 100644 > >>> index 0000000000..2e3e2fc562 > >>> --- /dev/null > >>> +++ b/sysdeps/unix/sysv/linux/mips/struct__semid_ds32.h > >>> @@ -0,0 +1,30 @@ > >>> +/* MIPS implementation of the semaphore struct __semid_ds32. > >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. > >>> + This file is part of the GNU C Library. > >>> + > >>> + The GNU C Library is free software; you can redistribute it and/or > >>> + modify it under the terms of the GNU Lesser General Public > >>> + License as published by the Free Software Foundation; either > >>> + version 2.1 of the License, or (at your option) any later version. > >>> + > >>> + The GNU C Library is distributed in the hope that it will be useful, > >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of > >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > >>> + Lesser General Public License for more details. > >>> + > >>> + You should have received a copy of the GNU Lesser General Public > >>> + License along with the GNU C Library; if not, see > >>> + <https://www.gnu.org/licenses/>. */ > >>> + > >>> +#if __WORDSIZE == 32 > >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > >>> +struct __semid_ds32 { > >>> + struct ipc_perm sem_perm; /* operation permission struct */ > >>> + __syscall_ulong_t sem_otime; /* last semop time */ > >>> + __syscall_ulong_t sem_ctime; /* last change time */ > >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > >>> + __syscall_ulong_t sem_otime_high; > >>> + __syscall_ulong_t sem_ctime_high; > >>> +}; > >>> +#endif > >> > >> Ok, it cover mips64-n32 as well. > >> > >>> diff --git a/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > >>> new file mode 100644 > >>> index 0000000000..f509db5a02 > >>> --- /dev/null > >>> +++ b/sysdeps/unix/sysv/linux/powerpc/struct__semid_ds32.h > >>> @@ -0,0 +1,32 @@ > >>> +/* PowerPC implementation of the semaphore struct __semid_ds32. > >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. > >>> + This file is part of the GNU C Library. > >>> + > >>> + The GNU C Library is free software; you can redistribute it and/or > >>> + modify it under the terms of the GNU Lesser General Public > >>> + License as published by the Free Software Foundation; either > >>> + version 2.1 of the License, or (at your option) any later version. > >>> + > >>> + The GNU C Library is distributed in the hope that it will be useful, > >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of > >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > >>> + Lesser General Public License for more details. > >>> + > >>> + You should have received a copy of the GNU Lesser General Public > >>> + License along with the GNU C Library; if not, see > >>> + <https://www.gnu.org/licenses/>. */ > >>> + > >>> +#if __WORDSIZE == 32 > >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > >>> +struct __semid_ds32 { > >>> + struct ipc_perm sem_perm; /* operation permission struct */ > >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > >>> + __syscall_ulong_t sem_otime; /* last semop() time */ > >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > >>> + __syscall_ulong_t __glibc_reserved3; > >>> + __syscall_ulong_t __glibc_reserved4; > >>> +}; > >>> +#endif > >> > >> Ok. > >> > >>> diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c > >>> index 30571af49f..0634cc1abe 100644 > >>> --- a/sysdeps/unix/sysv/linux/semctl.c > >>> +++ b/sysdeps/unix/sysv/linux/semctl.c > >>> @@ -22,8 +22,13 @@ > >>> #include <sysdep.h> > >>> #include <shlib-compat.h> > >>> #include <errno.h> > >>> +#include <struct__semid_ds32.h> > >>> #include <linux/posix_types.h> /* For __kernel_mode_t. */ > >>> > >>> +#define IPC_TIME64 \ > >>> + (__WORDSIZE == 32 && __TIMESIZE == 64 \ > >>> + && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) > >> > >> I think it would be better to move this definition to the common > >> ipc_priv.h header since it will most likely be used on msgctl > >> and shmctl y2038 support as well. > > > > Done. > > > >> > >>> + > >>> /* Define a `union semun' suitable for Linux here. */ > >>> union semun > >>> { > >>> @@ -44,13 +49,47 @@ union semun > >>> static int > >>> semctl_syscall (int semid, int semnum, int cmd, union semun arg) > >>> { > >>> + int ret; > >>> +#if IPC_TIME64 > >> > >> I think we shoul add a comment stating why we need a auxiliary buffer > >> for STAT/STAT_ANY operations. Something like: > >> > >> A temporary buffer is used to avoid both an issue where the export > >> semid_ds might not have follow kernel expected layout (due > >> sem_{o,c}time alignment in 64-bit time case) and the issue where > >> some kernel version might not clear the high bits when returning > >> then sem_{o,c}time information. > > > > Added > > > >> > >>> + struct __semid_ds32 tmp; > >>> + struct semid_ds *orig; > >>> + bool restore = false; > >>> + if (cmd == IPC_STAT || cmd == SEM_STAT || cmd == SEM_STAT_ANY) > >>> + { > >>> + tmp = (struct __semid_ds32) { > >>> + .sem_perm = arg.buf->sem_perm, > >>> + .sem_otime = arg.buf->sem_otime, > >>> + .sem_ctime = arg.buf->sem_ctime, > >>> + .sem_nsems = arg.buf->sem_nsems, > >>> + }; > >> > >> We need to fully initialize the temporary struct to avoid a kernel > >> issue fixed in 4693916846269d633a3664586650dbfac2c5562f (4.14) where > >> kernel does not clear the timestamps high bits. > > > > Added. > > > >> > >>> + orig = arg.buf; > >>> + arg.buf = (struct semid_ds*)&tmp; > >> > >> Space before &tmp. > > > > Added. > > > >> > >>> + restore = true; > >>> + } > >>> +#endif > >>> + > >>> #ifdef __ASSUME_DIRECT_SYSVIPC_SYSCALLS > >>> - return INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > >>> - arg.array); > >>> + ret = INLINE_SYSCALL_CALL (semctl, semid, semnum, cmd | __IPC_64, > >>> + arg.array); > >>> #else > >>> - return INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > >>> - SEMCTL_ARG_ADDRESS (arg)); > >>> + ret = INLINE_SYSCALL_CALL (ipc, IPCOP_semctl, semid, semnum, cmd | __IPC_64, > >>> + SEMCTL_ARG_ADDRESS (arg)); > >>> #endif > >> > >> Ok. > >> > >>> + > >>> +#if IPC_TIME64 > >>> + if (ret >= 0 && restore) > >>> + { > >>> + arg.buf = orig; > >>> + arg.buf->sem_perm = tmp.sem_perm; > >>> + arg.buf->sem_otime = tmp.sem_otime > >>> + | ((time_t) tmp.sem_otime_high << 32); > >>> + arg.buf->sem_ctime = tmp.sem_ctime > >>> + | ((time_t) tmp.sem_ctime_high << 32); > >>> + arg.buf->sem_nsems = tmp.sem_nsems; > >> > >> I think it would be better to use __time64_t explicit here. > > > > Done. > > > > Alistair > > > >> > >>> + } > >>> +#endif > >>> + > >>> + return ret; > >>> } > >>> > >>> int > >>> diff --git a/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > >>> new file mode 100644 > >>> index 0000000000..f641825d37 > >>> --- /dev/null > >>> +++ b/sysdeps/unix/sysv/linux/sparc/struct__semid_ds32.h > >>> @@ -0,0 +1,32 @@ > >>> +/* Sparc implementation of the semaphore struct __semid_ds32. > >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. > >>> + This file is part of the GNU C Library. > >>> + > >>> + The GNU C Library is free software; you can redistribute it and/or > >>> + modify it under the terms of the GNU Lesser General Public > >>> + License as published by the Free Software Foundation; either > >>> + version 2.1 of the License, or (at your option) any later version. > >>> + > >>> + The GNU C Library is distributed in the hope that it will be useful, > >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of > >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > >>> + Lesser General Public License for more details. > >>> + > >>> + You should have received a copy of the GNU Lesser General Public > >>> + License along with the GNU C Library; if not, see > >>> + <https://www.gnu.org/licenses/>. */ > >>> + > >>> +#if __WORDSIZE == 32 > >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > >>> +struct __semid_ds32 { > >>> + struct ipc_perm sem_perm; /* operation permission struct */ > >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > >>> + __syscall_ulong_t sem_otime; /* last semop() time */ > >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > >>> + __syscall_ulong_t __glibc_reserved3; > >>> + __syscall_ulong_t __glibc_reserved4; > >>> +}; > >>> +#endif > >> > >> Ok. > >> > >>> diff --git a/sysdeps/unix/sysv/linux/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/struct__semid_ds32.h > >>> new file mode 100644 > >>> index 0000000000..51ff83206d > >>> --- /dev/null > >>> +++ b/sysdeps/unix/sysv/linux/struct__semid_ds32.h > >>> @@ -0,0 +1,32 @@ > >>> +/* Generic implementation of the semaphore struct __semid_ds32. > >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. > >>> + This file is part of the GNU C Library. > >>> + > >>> + The GNU C Library is free software; you can redistribute it and/or > >>> + modify it under the terms of the GNU Lesser General Public > >>> + License as published by the Free Software Foundation; either > >>> + version 2.1 of the License, or (at your option) any later version. > >>> + > >>> + The GNU C Library is distributed in the hope that it will be useful, > >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of > >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > >>> + Lesser General Public License for more details. > >>> + > >>> + You should have received a copy of the GNU Lesser General Public > >>> + License along with the GNU C Library; if not, see > >>> + <https://www.gnu.org/licenses/>. */ > >>> + > >>> +#if __WORDSIZE == 32 > >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > >>> +struct __semid_ds32 { > >>> + struct ipc_perm sem_perm; /* operation permission struct */ > >>> + __syscall_ulong_t sem_otime; /* last semop() time */ > >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > >>> + __syscall_ulong_t __glibc_reserved3; > >>> + __syscall_ulong_t __glibc_reserved4; > >>> +}; > >>> +#endif > >> > >> Ok. > >> > >>> diff --git a/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > >>> new file mode 100644 > >>> index 0000000000..f65c9fc877 > >>> --- /dev/null > >>> +++ b/sysdeps/unix/sysv/linux/x86/struct__semid_ds32.h > >>> @@ -0,0 +1,32 @@ > >>> +/* x86 implementation of the semaphore struct __semid_ds32. > >>> + Copyright (C) 1995-2020 Free Software Foundation, Inc. > >>> + This file is part of the GNU C Library. > >>> + > >>> + The GNU C Library is free software; you can redistribute it and/or > >>> + modify it under the terms of the GNU Lesser General Public > >>> + License as published by the Free Software Foundation; either > >>> + version 2.1 of the License, or (at your option) any later version. > >>> + > >>> + The GNU C Library is distributed in the hope that it will be useful, > >>> + but WITHOUT ANY WARRANTY; without even the implied warranty of > >>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > >>> + Lesser General Public License for more details. > >>> + > >>> + You should have received a copy of the GNU Lesser General Public > >>> + License along with the GNU C Library; if not, see > >>> + <https://www.gnu.org/licenses/>. */ > >>> + > >>> +#ifdef __i386__ > >>> +/* This is the "new" y2038 types defined after the 5.1 kernel. It allows > >>> + the kernel to use {o,c}time{_high} values to support a 64-bit time_t. */ > >>> +struct __semid_ds32 { > >>> + struct ipc_perm sem_perm; /* operation permission struct */ > >>> + __syscall_ulong_t sem_otime; /* last semop() time */ > >>> + __syscall_ulong_t sem_otime_high; /* last semop() time high */ > >>> + __syscall_ulong_t sem_ctime; /* last time changed by semctl() */ > >>> + __syscall_ulong_t sem_ctime_high; /* last time changed by semctl() high */ > >>> + __syscall_ulong_t sem_nsems; /* number of semaphores in set */ > >>> + __syscall_ulong_t __glibc_reserved3; > >>> + __syscall_ulong_t __glibc_reserved4; > >>> +}; > >>> +#endif > >>> > >> > >> Ok. > >> > >> ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2020-04-30 21:33 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-04-28 22:05 [PATCH v6 0/3] Support y2038 semctl_syscall() Alistair Francis 2020-04-28 22:05 ` [PATCH v6 1/3] bits/sem.h: Split out struct semid_ds Alistair Francis 2020-04-28 22:05 ` [PATCH v6 2/3] semctl: Remove the sem-pad.h file Alistair Francis 2020-04-28 22:05 ` [PATCH v6 3/3] sysv: linux: Pass 64-bit version of semctl syscall Alistair Francis 2020-04-29 21:09 ` Adhemerval Zanella 2020-04-29 23:24 ` Alistair Francis 2020-04-30 15:06 ` Adhemerval Zanella 2020-04-30 21:25 ` Alistair Francis
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).