From patchwork Thu Mar 5 01:26:05 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alistair Francis X-Patchwork-Id: 38420 Received: (qmail 120003 invoked by alias); 5 Mar 2020 01:33:31 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 119848 invoked by uid 89); 5 Mar 2020 01:33:30 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy=2021 X-HELO: esa2.hgst.iphmx.com DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1583372009; x=1614908009; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YO6GJbg1J8q8Tho0IDzs3nDjwbPOJQMHOKqwLsBaank=; b=pKXwePhbqTui99OSdOd8+JlAn0jfuSpLysCPTJkKd0l8lYF0N1RllgEy 3uhSTsMb1ZRqpHCOD27pPQZpaCHC2QtH2zIUcx124r/+eMhyRvFd5k18H 9rJO37ankadrvexOxAvFIY38zKintZ6AtrsM57zFcAA+6KBoFBDwG69cE 0dTq+6me6AmnzyJx77RK3voVd3z3oi+KzkivFymYQaarUtFIpMYP5DSZ/ WZMoGhu50FTbhzQTZ+08JORElKWC0oFvFQEDUA3xO1uwJHNN6kY2wKUTN o3NVdCe10s16fwVlbSyIUO5tjDNTC1N1rMyykKT51xeo+jFcTeZ2AbZaB g==; IronPort-SDR: 47i9t/MBj3alTz2hRPXi+JaCBGn3GuL7vH0V3ht1rHsjGAPnlVnnS3M76YLsQTCiEJsLx9Z1o3 5VhN0ad18O5985rjrkUSUPNLwueOvuraeeoyUY7PQM3yi8xLx7NJ9/CuQlWhWNjQwm3DVJA6Ol HFRxKalrFhRi1xf474YQssgDmvZTj6MW181VJOLbhWkWY+SYH6H8SW1HawMjy5uZ4q+IJRCGlc xzE7Qz98wjlaN/b3V34pOBV56+DBE2JXVcysjtb2obNyv9kWDrE3dDYWRRp+bAvxzkvG9puf0q zyg= IronPort-SDR: yoe9Tf4000E+05KZL+n3B8yD0kjmtbPSgKrvUA+N6glUNzg5K8VaivprpjgQqisab/m77KqruT yH3upz71gQozINMCzVbLB3KyWadvlV69QSwxiUbdMujgCEOAy91s0FT4/QGZTXfu7PTTqW/x9U iY5BI5oLOiU2TxLWPf1qH8sFq6ElXMO8CX4B8lN+VE1ltTcqhP4pD25As3lGyf2WtjHlLQH+Tv /OSt5jncyf2fkBDCW+xuwUcUBRYD6G4Evi7EpE5Ci2dqavfJRwJ8nH7vnjN6N1Cbgc9abr9gbI GwJyTJRy1cEByg0if020yEBN IronPort-SDR: 2/nebodbudQbgfB6HaHoGPQMi3/l7IuxeDYKYhV2848QOTpW25sgsjuJh9WeV5o9QoYrfCmrk/ l124vAHoFb2IjNkzwkmur2CtEXDwRP4avkdCwDz8rgPQKU9SONiyEXs+cbWeBtk/lWxgCNxIiL zSsPf/qaoiWEuWhXRuGB6jcxOjh2opPuFjjtKOqGVWQOfQTlArcsa6OMrIXjO+KSREHy9dNgHR UEo0Nlz7YGYFXUSY9SJPFczJqY3v18GT8je3XMl6WnmnHF78+FHUAoPSoogiDbS7XD2rl9wDSu En0= WDCIronportException: Internal From: Alistair Francis To: libc-alpha@sourceware.org Cc: alistair23@gmail.com, Alistair Francis Subject: [PATCH v3 3/3] sysv: linux: Pass 64-bit version of semctl syscall Date: Wed, 4 Mar 2020 17:26:05 -0800 Message-Id: <20200305012605.26870-4-alistair.francis@wdc.com> In-Reply-To: <20200305012605.26870-1-alistair.francis@wdc.com> References: <20200305012605.26870-1-alistair.francis@wdc.com> MIME-Version: 1.0 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. We protect this new code via the __IPC_TIME64 marco, which is only true for 32-bit architectures with a 64-bit time_t. --- bits/ipc.h | 6 ++++- sysdeps/gnu/bits/ipc.h | 6 ++++- sysdeps/unix/sysv/linux/bits/ipc.h | 6 ++++- sysdeps/unix/sysv/linux/bits/semid_ds_t.h | 15 +++++++++++ .../unix/sysv/linux/hppa/bits/semid_ds_t.h | 15 +++++++++++ .../unix/sysv/linux/mips/bits/semid_ds_t.h | 13 ++++++++++ .../unix/sysv/linux/powerpc/bits/semid_ds_t.h | 15 +++++++++++ sysdeps/unix/sysv/linux/semctl.c | 25 ++++++++++++++++--- .../unix/sysv/linux/sparc/bits/semid_ds_t.h | 15 +++++++++++ sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h | 15 +++++++++++ 10 files changed, 124 insertions(+), 7 deletions(-) diff --git a/bits/ipc.h b/bits/ipc.h index e2981fd5c3..9ac8485193 100644 --- a/bits/ipc.h +++ b/bits/ipc.h @@ -29,7 +29,11 @@ /* Control commands for `msgctl', `semctl', and `shmctl'. */ #define IPC_RMID 0 /* remove identifier */ #define IPC_SET 1 /* set `ipc_perm' options */ -#define IPC_STAT 2 /* get `ipc_perm' options */ +#if __TIMESIZE == 64 && __WORDSIZE == 32 +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ +#else +# define IPC_STAT 2 /* Get `ipc_perm' options. */ +#endif /* Special key values. */ #define IPC_PRIVATE ((key_t) 0) /* private key */ diff --git a/sysdeps/gnu/bits/ipc.h b/sysdeps/gnu/bits/ipc.h index 47df305e1c..328c11a0d7 100644 --- a/sysdeps/gnu/bits/ipc.h +++ b/sysdeps/gnu/bits/ipc.h @@ -29,7 +29,11 @@ /* Control commands for `msgctl', `semctl', and `shmctl'. */ #define IPC_RMID 0 /* Remove identifier. */ #define IPC_SET 1 /* Set `ipc_perm' options. */ -#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#if __TIMESIZE == 64 && __WORDSIZE == 32 +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ +#else +# define IPC_STAT 2 /* Get `ipc_perm' options. */ +#endif #ifdef __USE_GNU # define IPC_INFO 3 /* See ipcs. */ #endif diff --git a/sysdeps/unix/sysv/linux/bits/ipc.h b/sysdeps/unix/sysv/linux/bits/ipc.h index 085dd628ac..44449de62f 100644 --- a/sysdeps/unix/sysv/linux/bits/ipc.h +++ b/sysdeps/unix/sysv/linux/bits/ipc.h @@ -29,7 +29,11 @@ /* Control commands for `msgctl', `semctl', and `shmctl'. */ #define IPC_RMID 0 /* Remove identifier. */ #define IPC_SET 1 /* Set `ipc_perm' options. */ -#define IPC_STAT 2 /* Get `ipc_perm' options. */ +#if __TIMESIZE == 64 && __WORDSIZE == 32 +# define IPC_STAT 0x102 /* Get `ipc_perm' options. */ +#else +# define IPC_STAT 2 /* Get `ipc_perm' options. */ +#endif #ifdef __USE_GNU # define IPC_INFO 3 /* See ipcs. */ #endif diff --git a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h index d9d902ed0d..b135301356 100644 --- a/sysdeps/unix/sysv/linux/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include directly; use instead." #endif +#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 + /* Data structure describing a set of semaphores. */ #if __TIMESIZE == 32 struct semid_ds diff --git a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h index 39c0e53f38..3613c5ec94 100644 --- a/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/hppa/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include directly; use instead." #endif +#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 + /* Data structure describing a set of semaphores. */ #if __TIMESIZE == 32 struct semid_ds diff --git a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h index 1ab16492dd..e26906a67f 100644 --- a/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/mips/bits/semid_ds_t.h @@ -20,6 +20,19 @@ # error "Never include directly; use instead." #endif +#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 + /* Data structure describing a set of semaphores. */ struct semid_ds { diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h index 79b4cba939..ec2ff552eb 100644 --- a/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/powerpc/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include directly; use instead." #endif +#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 + /* Data structure describing a set of semaphores. */ #if __TIMESIZE == 32 struct semid_ds diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c index 0c3eb0932f..3ac6d01b84 100644 --- a/sysdeps/unix/sysv/linux/semctl.c +++ b/sysdeps/unix/sysv/linux/semctl.c @@ -23,11 +23,16 @@ #include #include +#define __IPC_TIME64 (IPC_STAT & __IPC_64) + /* Define a `union semun' suitable for Linux here. */ union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ +#if __WORDSIZE == 32 + struct __semid_ds32 *buf32; /* 32-bit buffer for IPC_STAT & IPC_SET */ +#endif unsigned short int *array; /* array for GETALL & SETALL */ struct seminfo *__buf; /* buffer for IPC_INFO */ }; @@ -43,13 +48,25 @@ union semun static int semctl_syscall (int semid, int semnum, int cmd, union semun arg) { + int ret; #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 && (cmd & __IPC_TIME64)) + { + arg.buf->sem_ctime = arg.buf32->sem_ctime | + ((time_t) arg.buf32->sem_ctime_high << 32); + arg.buf->sem_otime = arg.buf32->sem_otime | + ((time_t) arg.buf32->sem_otime_high << 32); + } #endif + return ret; } int diff --git a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h index f8de676e79..b08fb8a79e 100644 --- a/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/sparc/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include directly; use instead." #endif +#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 + /* Data structure describing a set of semaphores. */ #if __TIMESIZE == 32 struct semid_ds diff --git a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h index 42694069d5..c7b9adce88 100644 --- a/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h +++ b/sysdeps/unix/sysv/linux/x86/bits/semid_ds_t.h @@ -20,6 +20,21 @@ # error "Never include directly; use instead." #endif +#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 + /* Data structure describing a set of semaphores. */ struct semid_ds {