Browse Source

libc: fix struct msqid_ds layout for TIME64 on all common-header arches

The common bits/msq.h only emitted the split kernel-facing time layout
(msg_*time_internal_1/2 + the combined __time_t fields at the end, joined
by msgctl()) for __riscv.  Every other arch using the common header fell
into the #else branch, which overlays a single __time_t over the kernel's
split low/high words.  That happens to read correctly on little-endian
(csky, i386, microblaze pass tst-msgctl) but returns word-swapped times on
big-endian: tst-msgctl fails on m68k and or1k with the post-2038 date.

This mirrors the semid_ds/shmid_ds TIME64 fixes.  Gate the split layout on
__WORDSIZE == 32 && __UCLIBC_USE_TIME64__ for the whole common header and
expose __MSQID_DS_TIME64_SPLIT so msgctl() combines the words for every
such arch instead of only riscv (mips keeps its private variant).

Verified under qemu: tst-msgctl now passes on m68k (big-endian, was
failing) and still passes on microblaze (little-endian); tst-shmctl and
tst-semctl stay green on both.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
ramin 1 month ago
parent
commit
7b58f9f30e
2 changed files with 4 additions and 3 deletions
  1. 1 1
      libc/misc/sysvipc/msgq.c
  2. 3 2
      libc/sysdeps/linux/common/bits/msq.h

+ 1 - 1
libc/misc/sysvipc/msgq.c

@@ -26,7 +26,7 @@ int msgctl(int msqid, int cmd, struct msqid_ds *buf)
 {
 #ifdef __NR_msgctl
 	int __ret = __libc_msgctl(msqid, cmd | __IPC_64, buf);
-#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__) && (defined(__mips) || defined(__riscv))
+#if (__WORDSIZE == 32) && defined(__UCLIBC_USE_TIME64__) && (defined(__mips) || defined(__MSQID_DS_TIME64_SPLIT))
 	union msqun arg = {.buff = buf};
 	// When cmd is IPC_RMID, buf should be NULL.
 	if (arg.__pad != NULL) {

+ 3 - 2
libc/sysdeps/linux/common/bits/msq.h

@@ -37,7 +37,7 @@ typedef unsigned long int msglen_t;
 struct msqid_ds
 {
   struct ipc_perm msg_perm;	/* structure describing operation permission */
-#if (__WORDSIZE == 32 && defined(__riscv) && defined(__UCLIBC_USE_TIME64__))
+#if (__WORDSIZE == 32 && defined(__UCLIBC_USE_TIME64__))
   unsigned long int msg_stime_internal_1;
   unsigned long int msg_stime_internal_2;
   unsigned long int msg_rtime_internal_1;
@@ -57,10 +57,11 @@ struct msqid_ds
   msglen_t msg_qbytes;		/* max number of bytes allowed on queue */
   __pid_t msg_lspid;		/* pid of last msgsnd() */
   __pid_t msg_lrpid;		/* pid of last msgrcv() */
-#if (__WORDSIZE == 32 && defined(__riscv) && defined(__UCLIBC_USE_TIME64__))
+#if (__WORDSIZE == 32 && defined(__UCLIBC_USE_TIME64__))
   __time_t msg_stime;		/* time of last msgsnd command */
   __time_t msg_rtime;		/* time of last msgrcv command */
   __time_t msg_ctime;		/* time of last change */
+# define __MSQID_DS_TIME64_SPLIT 1
 #endif
   unsigned long int __uclibc_unused4;
   unsigned long int __uclibc_unused5;