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.
This commit is contained in:
Adhemerval Zanella 2025-04-25 13:57:32 +00:00
parent fed92e28c5
commit 180cbc0cc9
10 changed files with 35 additions and 43 deletions

View File

@ -2,11 +2,11 @@
struct kernel_shmid64_ds struct kernel_shmid64_ds
{ {
struct ipc_perm shm_perm; /* operation permission struct */ 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_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_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 shm_ctime; /* time of last change by shmctl() */
unsigned long int __pad; unsigned long int __pad;
size_t shm_segsz; /* size of segment in bytes */ size_t shm_segsz; /* size of segment in bytes */

View File

@ -4,11 +4,11 @@ struct kernel_shmid64_ds
struct ipc_perm shm_perm; struct ipc_perm shm_perm;
size_t shm_segsz; size_t shm_segsz;
unsigned long int shm_atime; 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;
unsigned long int shm_dtime_high; unsigned long int __shm_dtime_high;
unsigned long int shm_ctime; unsigned long int shm_ctime;
unsigned long int shm_ctime_high; unsigned long int __shm_ctime_high;
__pid_t shm_cpid; __pid_t shm_cpid;
__pid_t shm_lpid; __pid_t shm_lpid;
unsigned long int shm_nattch; unsigned long int shm_nattch;

View File

@ -59,6 +59,9 @@ struct __old_ipc_perm
#if (__WORDSIZE == 32 \ #if (__WORDSIZE == 32 \
&& (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32))
# define __IPC_TIME64 1 # 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 #else
# define __IPC_TIME64 0 # define __IPC_TIME64 0
#endif #endif

View File

@ -19,9 +19,9 @@ struct kernel_shmid64_ds
unsigned long int __unused1; unsigned long int __unused1;
unsigned long int __unused2; unsigned long int __unused2;
#else #else
unsigned short int shm_atime_high; unsigned short int __shm_atime_high;
unsigned short int shm_dtime_high; unsigned short int __shm_dtime_high;
unsigned short int shm_ctime_high; unsigned short int __shm_ctime_high;
unsigned short int __ununsed1; unsigned short int __ununsed1;
#endif #endif
}; };

View File

@ -172,12 +172,9 @@ static void
msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq) msqid_to_msqid64 (struct __msqid64_ds *mq64, const struct msqid_ds *mq)
{ {
mq64->msg_perm = mq->msg_perm; mq64->msg_perm = mq->msg_perm;
mq64->msg_stime = mq->msg_stime mq64->msg_stime = IPC_HILO (mq, msg_stime);
| ((__time64_t) mq->__msg_stime_high << 32); mq64->msg_rtime = IPC_HILO (mq, msg_rtime);
mq64->msg_rtime = mq->msg_rtime mq64->msg_ctime = IPC_HILO (mq, msg_ctime);
| ((__time64_t) mq->__msg_rtime_high << 32);
mq64->msg_ctime = mq->msg_ctime
| ((__time64_t) mq->__msg_ctime_high << 32);
mq64->msg_cbytes = mq->msg_cbytes; mq64->msg_cbytes = mq->msg_cbytes;
mq64->msg_qnum = mq->msg_qnum; mq64->msg_qnum = mq->msg_qnum;
mq64->msg_qbytes = mq->msg_qbytes; mq64->msg_qbytes = mq->msg_qbytes;

View File

@ -2,11 +2,11 @@
struct kernel_shmid64_ds struct kernel_shmid64_ds
{ {
struct ipc_perm shm_perm; 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_atime;
unsigned long int shm_dtime_high; unsigned long int __shm_dtime_high;
unsigned long int shm_dtime; 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 shm_ctime;
unsigned long int __ununsed1; unsigned long int __ununsed1;
size_t shm_segsz; size_t shm_segsz;

View File

@ -222,10 +222,8 @@ static void
semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds) semid_to_semid64 (struct __semid64_ds *ds64, const struct semid_ds *ds)
{ {
ds64->sem_perm = ds->sem_perm; ds64->sem_perm = ds->sem_perm;
ds64->sem_otime = ds->sem_otime ds64->sem_otime = IPC_HILO (ds, sem_otime);
| ((__time64_t) ds->__sem_otime_high << 32); ds64->sem_ctime = IPC_HILO (ds, sem_ctime);
ds64->sem_ctime = ds->sem_ctime
| ((__time64_t) ds->__sem_ctime_high << 32);
ds64->sem_nsems = ds->sem_nsems; ds64->sem_nsems = ds->sem_nsems;
} }

View File

@ -40,11 +40,11 @@ shmid64_to_kshmid64 (const struct __shmid64_ds *shmid64,
kshmid->shm_perm = shmid64->shm_perm; kshmid->shm_perm = shmid64->shm_perm;
kshmid->shm_segsz = shmid64->shm_segsz; kshmid->shm_segsz = shmid64->shm_segsz;
kshmid->shm_atime = shmid64->shm_atime; 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 = 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 = 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_cpid = shmid64->shm_cpid;
kshmid->shm_lpid = shmid64->shm_lpid; kshmid->shm_lpid = shmid64->shm_lpid;
kshmid->shm_nattch = shmid64->shm_nattch; 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_perm = kshmid->shm_perm;
shmid64->shm_segsz = kshmid->shm_segsz; shmid64->shm_segsz = kshmid->shm_segsz;
shmid64->shm_atime = kshmid->shm_atime shmid64->shm_atime = IPC_HILO (kshmid, shm_atime);
| ((__time64_t) kshmid->shm_atime_high << 32); shmid64->shm_dtime = IPC_HILO (kshmid, shm_dtime);
shmid64->shm_dtime = kshmid->shm_dtime shmid64->shm_ctime = IPC_HILO (kshmid, shm_ctime);
| ((__time64_t) kshmid->shm_dtime_high << 32);
shmid64->shm_ctime = kshmid->shm_ctime
| ((__time64_t) kshmid->shm_ctime_high << 32);
shmid64->shm_cpid = kshmid->shm_cpid; shmid64->shm_cpid = kshmid->shm_cpid;
shmid64->shm_lpid = kshmid->shm_lpid; shmid64->shm_lpid = kshmid->shm_lpid;
shmid64->shm_nattch = kshmid->shm_nattch; 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_perm = shm->shm_perm;
shm64->shm_segsz = shm->shm_segsz; shm64->shm_segsz = shm->shm_segsz;
shm64->shm_atime = shm->shm_atime shm64->shm_atime = IPC_HILO (shm, shm_atime);
| ((__time64_t) shm->__shm_atime_high << 32); shm64->shm_dtime = IPC_HILO (shm, shm_dtime);
shm64->shm_dtime = shm->shm_dtime shm64->shm_ctime = IPC_HILO (shm, shm_ctime);
| ((__time64_t) shm->__shm_dtime_high << 32);
shm64->shm_ctime = shm->shm_ctime
| ((__time64_t) shm->__shm_ctime_high << 32);
shm64->shm_cpid = shm->shm_cpid; shm64->shm_cpid = shm->shm_cpid;
shm64->shm_lpid = shm->shm_lpid; shm64->shm_lpid = shm->shm_lpid;
shm64->shm_nattch = shm->shm_nattch; shm64->shm_nattch = shm->shm_nattch;

View File

@ -2,11 +2,11 @@
struct kernel_shmid64_ds struct kernel_shmid64_ds
{ {
struct ipc_perm shm_perm; 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_atime;
unsigned long int shm_dtime_high; unsigned long int __shm_dtime_high;
unsigned long int shm_dtime; 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 shm_ctime;
size_t shm_segsz; size_t shm_segsz;
__pid_t shm_cpid; __pid_t shm_cpid;

View File

@ -4,11 +4,11 @@ struct kernel_shmid64_ds
struct ipc_perm shm_perm; struct ipc_perm shm_perm;
size_t shm_segsz; size_t shm_segsz;
unsigned long int shm_atime; 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;
unsigned long int shm_dtime_high; unsigned long int __shm_dtime_high;
unsigned long int shm_ctime; unsigned long int shm_ctime;
unsigned long int shm_ctime_high; unsigned long int __shm_ctime_high;
__pid_t shm_cpid; __pid_t shm_cpid;
__pid_t shm_lpid; __pid_t shm_lpid;
unsigned long int shm_nattch; unsigned long int shm_nattch;