From: Adhemerval Zanella Date: Fri, 25 Apr 2025 13:57:32 +0000 (+0000) Subject: sysvipc: Fix UB on time64 time support X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=180cbc0cc9cbc31f05ac2598cecf0ae498a76717;p=thirdparty%2Fglibc.git sysvipc: Fix UB on time64 time support Building with ubsan on 32 bit architecture without 64 bit time_t as default, it shows: UBSAN: Undefined behaviour in ../sysdeps/unix/sysv/linux/msgctl.c:180:45 left shift of 3935167480 by 32 cannot be represented in type 'long long int' Add a new macro, IPC_HILO, to handle this transparently by using unsigned shifts. --- diff --git a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h index 4d09fc7f62..c43b1e0462 100644 --- a/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h +++ b/sysdeps/unix/sysv/linux/hppa/struct_kernel_shmid64_ds.h @@ -2,11 +2,11 @@ struct kernel_shmid64_ds { struct ipc_perm shm_perm; /* operation permission struct */ - unsigned long int shm_atime_high; + unsigned long int __shm_atime_high; unsigned long int shm_atime; /* time of last shmat() */ - unsigned long int shm_dtime_high; + unsigned long int __shm_dtime_high; unsigned long int shm_dtime; /* time of last shmdt() */ - unsigned long int shm_ctime_high; + unsigned long int __shm_ctime_high; unsigned long int shm_ctime; /* time of last change by shmctl() */ unsigned long int __pad; size_t shm_segsz; /* size of segment in bytes */ diff --git a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h index 6a0a0d9c71..80b5f24005 100644 --- a/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h +++ b/sysdeps/unix/sysv/linux/i386/struct_kernel_shmid64_ds.h @@ -4,11 +4,11 @@ struct kernel_shmid64_ds struct ipc_perm shm_perm; size_t shm_segsz; unsigned long int shm_atime; - unsigned long int shm_atime_high; + unsigned long int __shm_atime_high; unsigned long int shm_dtime; - unsigned long int shm_dtime_high; + unsigned long int __shm_dtime_high; unsigned long int shm_ctime; - unsigned long int shm_ctime_high; + unsigned long int __shm_ctime_high; __pid_t shm_cpid; __pid_t shm_lpid; unsigned long int shm_nattch; diff --git a/sysdeps/unix/sysv/linux/ipc_priv.h b/sysdeps/unix/sysv/linux/ipc_priv.h index 6ace4b764d..8c27b744d7 100644 --- a/sysdeps/unix/sysv/linux/ipc_priv.h +++ b/sysdeps/unix/sysv/linux/ipc_priv.h @@ -59,6 +59,9 @@ struct __old_ipc_perm #if (__WORDSIZE == 32 \ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) # define __IPC_TIME64 1 +/* Left-shift using unsigned int, since __time64_t is signed. */ +# define IPC_HILO(__buf, __member) \ + ((__buf)->__member | (0ULL + (__buf)->__##__member##_high) << 32) #else # define __IPC_TIME64 0 #endif diff --git a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h index a4baa5614f..f79f1469be 100644 --- a/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h +++ b/sysdeps/unix/sysv/linux/mips/struct_kernel_shmid64_ds.h @@ -19,9 +19,9 @@ struct kernel_shmid64_ds unsigned long int __unused1; unsigned long int __unused2; #else - unsigned short int shm_atime_high; - unsigned short int shm_dtime_high; - unsigned short int shm_ctime_high; + unsigned short int __shm_atime_high; + unsigned short int __shm_dtime_high; + unsigned short int __shm_ctime_high; unsigned short int __ununsed1; #endif }; diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c index ee794c3423..d83a5c270d 100644 --- a/sysdeps/unix/sysv/linux/msgctl.c +++ b/sysdeps/unix/sysv/linux/msgctl.c @@ -172,12 +172,9 @@ static void msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq) { mq64->msg_perm = mq->msg_perm; - mq64->msg_stime = mq->msg_stime - | ((__time64_t) mq->__msg_stime_high << 32); - mq64->msg_rtime = mq->msg_rtime - | ((__time64_t) mq->__msg_rtime_high << 32); - mq64->msg_ctime = mq->msg_ctime - | ((__time64_t) mq->__msg_ctime_high << 32); + mq64->msg_stime = IPC_HILO (mq, msg_stime); + mq64->msg_rtime = IPC_HILO (mq, msg_rtime); + mq64->msg_ctime = IPC_HILO (mq, msg_ctime); mq64->msg_cbytes = mq->msg_cbytes; mq64->msg_qnum = mq->msg_qnum; mq64->msg_qbytes = mq->msg_qbytes; diff --git a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h index ae3f3987ac..c6946312ba 100644 --- a/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h +++ b/sysdeps/unix/sysv/linux/powerpc/struct_kernel_shmid64_ds.h @@ -2,11 +2,11 @@ struct kernel_shmid64_ds { struct ipc_perm shm_perm; - unsigned long int shm_atime_high; + unsigned long int __shm_atime_high; unsigned long int shm_atime; - unsigned long int shm_dtime_high; + unsigned long int __shm_dtime_high; unsigned long int shm_dtime; - unsigned long int shm_ctime_high; + unsigned long int __shm_ctime_high; unsigned long int shm_ctime; unsigned long int __ununsed1; size_t shm_segsz; diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c index feaf3fcdb1..0450138b96 100644 --- a/sysdeps/unix/sysv/linux/semctl.c +++ b/sysdeps/unix/sysv/linux/semctl.c @@ -222,10 +222,8 @@ static void semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds) { ds64->sem_perm = ds->sem_perm; - ds64->sem_otime = ds->sem_otime - | ((__time64_t) ds->__sem_otime_high << 32); - ds64->sem_ctime = ds->sem_ctime - | ((__time64_t) ds->__sem_ctime_high << 32); + ds64->sem_otime = IPC_HILO (ds, sem_otime); + ds64->sem_ctime = IPC_HILO (ds, sem_ctime); ds64->sem_nsems = ds->sem_nsems; } diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c index 2e8faaf03b..089a6727ca 100644 --- a/sysdeps/unix/sysv/linux/shmctl.c +++ b/sysdeps/unix/sysv/linux/shmctl.c @@ -40,11 +40,11 @@ shmid64_to_kshmid64 (const struct __shmid64_ds *shmid64, kshmid->shm_perm = shmid64->shm_perm; kshmid->shm_segsz = shmid64->shm_segsz; kshmid->shm_atime = shmid64->shm_atime; - kshmid->shm_atime_high = shmid64->shm_atime >> 32; + kshmid->__shm_atime_high = shmid64->shm_atime >> 32; kshmid->shm_dtime = shmid64->shm_dtime; - kshmid->shm_dtime_high = shmid64->shm_dtime >> 32; + kshmid->__shm_dtime_high = shmid64->shm_dtime >> 32; kshmid->shm_ctime = shmid64->shm_ctime; - kshmid->shm_ctime_high = shmid64->shm_ctime >> 32; + kshmid->__shm_ctime_high = shmid64->shm_ctime >> 32; kshmid->shm_cpid = shmid64->shm_cpid; kshmid->shm_lpid = shmid64->shm_lpid; kshmid->shm_nattch = shmid64->shm_nattch; @@ -56,12 +56,9 @@ kshmid64_to_shmid64 (const struct kernel_shmid64_ds *kshmid, { shmid64->shm_perm = kshmid->shm_perm; shmid64->shm_segsz = kshmid->shm_segsz; - shmid64->shm_atime = kshmid->shm_atime - | ((__time64_t) kshmid->shm_atime_high << 32); - shmid64->shm_dtime = kshmid->shm_dtime - | ((__time64_t) kshmid->shm_dtime_high << 32); - shmid64->shm_ctime = kshmid->shm_ctime - | ((__time64_t) kshmid->shm_ctime_high << 32); + shmid64->shm_atime = IPC_HILO (kshmid, shm_atime); + shmid64->shm_dtime = IPC_HILO (kshmid, shm_dtime); + shmid64->shm_ctime = IPC_HILO (kshmid, shm_ctime); shmid64->shm_cpid = kshmid->shm_cpid; shmid64->shm_lpid = kshmid->shm_lpid; shmid64->shm_nattch = kshmid->shm_nattch; @@ -176,12 +173,9 @@ shmid_to_shmid64 (struct __shmid64_ds *shm64, const struct shmid_ds *shm) { shm64->shm_perm = shm->shm_perm; shm64->shm_segsz = shm->shm_segsz; - shm64->shm_atime = shm->shm_atime - | ((__time64_t) shm->__shm_atime_high << 32); - shm64->shm_dtime = shm->shm_dtime - | ((__time64_t) shm->__shm_dtime_high << 32); - shm64->shm_ctime = shm->shm_ctime - | ((__time64_t) shm->__shm_ctime_high << 32); + shm64->shm_atime = IPC_HILO (shm, shm_atime); + shm64->shm_dtime = IPC_HILO (shm, shm_dtime); + shm64->shm_ctime = IPC_HILO (shm, shm_ctime); shm64->shm_cpid = shm->shm_cpid; shm64->shm_lpid = shm->shm_lpid; shm64->shm_nattch = shm->shm_nattch; diff --git a/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h index 333a410641..9029f8639b 100644 --- a/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h +++ b/sysdeps/unix/sysv/linux/sparc/struct_kernel_shmid64_ds.h @@ -2,11 +2,11 @@ struct kernel_shmid64_ds { struct ipc_perm shm_perm; - unsigned long int shm_atime_high; + unsigned long int __shm_atime_high; unsigned long int shm_atime; - unsigned long int shm_dtime_high; + unsigned long int __shm_dtime_high; unsigned long int shm_dtime; - unsigned long int shm_ctime_high; + unsigned long int __shm_ctime_high; unsigned long int shm_ctime; size_t shm_segsz; __pid_t shm_cpid; diff --git a/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h index 6fe67afccb..b4dbea030a 100644 --- a/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h +++ b/sysdeps/unix/sysv/linux/struct_kernel_shmid64_ds.h @@ -4,11 +4,11 @@ struct kernel_shmid64_ds struct ipc_perm shm_perm; size_t shm_segsz; unsigned long int shm_atime; - unsigned long int shm_atime_high; + unsigned long int __shm_atime_high; unsigned long int shm_dtime; - unsigned long int shm_dtime_high; + unsigned long int __shm_dtime_high; unsigned long int shm_ctime; - unsigned long int shm_ctime_high; + unsigned long int __shm_ctime_high; __pid_t shm_cpid; __pid_t shm_lpid; unsigned long int shm_nattch;