Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

y2038: mips: Extend sysvipc data structures

MIPS is the weirdest case for sysvipc, because each of the
three data structures is done differently:

* msqid64_ds has padding in the right place so we could in theory
extend this one to just have 64-bit values instead of time_t.
As this does not work for most of the other combinations,
we just handle it in the common manner though.

* semid64_ds has no padding for 64-bit time_t, but has two reserved
'long' fields, which are sufficient to extend the sem_otime
and sem_ctime fields to 64 bit. In order to do this, the libc
implementation will have to copy the data into another structure
that has the fields in a different order. MIPS is the only
architecture with this problem, so this is best done in MIPS
specific libc code.

* shmid64_ds is slightly worse than that, because it has three
time_t fields but only two unused 32-bit words. As a workaround,
we extend each field only by 16 bits, ending up with 48-bit
timestamps that user space again has to work around by itself.

The compat versions of the data structures are changed in the
same way.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+94 -41
+22 -18
arch/mips/include/asm/compat.h
··· 37 37 typedef s32 compat_timer_t; 38 38 typedef s32 compat_key_t; 39 39 40 + typedef s16 compat_short_t; 40 41 typedef s32 compat_int_t; 41 42 typedef s32 compat_long_t; 42 43 typedef s64 compat_s64; 44 + typedef u16 compat_ushort_t; 43 45 typedef u32 compat_uint_t; 44 46 typedef u32 compat_ulong_t; 45 47 typedef u64 compat_u64; ··· 159 157 160 158 struct compat_semid64_ds { 161 159 struct compat_ipc64_perm sem_perm; 162 - compat_time_t sem_otime; 163 - compat_time_t sem_ctime; 160 + compat_ulong_t sem_otime; 161 + compat_ulong_t sem_ctime; 164 162 compat_ulong_t sem_nsems; 165 - compat_ulong_t __unused1; 166 - compat_ulong_t __unused2; 163 + compat_ulong_t sem_otime_high; 164 + compat_ulong_t sem_ctime_high; 167 165 }; 168 166 169 167 struct compat_msqid64_ds { 170 168 struct compat_ipc64_perm msg_perm; 171 169 #ifndef CONFIG_CPU_LITTLE_ENDIAN 172 - compat_ulong_t __unused1; 170 + compat_ulong_t msg_stime_high; 173 171 #endif 174 - compat_time_t msg_stime; 172 + compat_ulong_t msg_stime; 175 173 #ifdef CONFIG_CPU_LITTLE_ENDIAN 176 - compat_ulong_t __unused1; 174 + compat_ulong_t msg_stime_high; 177 175 #endif 178 176 #ifndef CONFIG_CPU_LITTLE_ENDIAN 179 - compat_ulong_t __unused2; 177 + compat_ulong_t msg_rtime_high; 180 178 #endif 181 - compat_time_t msg_rtime; 179 + compat_ulong_t msg_rtime; 182 180 #ifdef CONFIG_CPU_LITTLE_ENDIAN 183 - compat_ulong_t __unused2; 181 + compat_ulong_t msg_rtime_high; 184 182 #endif 185 183 #ifndef CONFIG_CPU_LITTLE_ENDIAN 186 - compat_ulong_t __unused3; 184 + compat_ulong_t msg_ctime_high; 187 185 #endif 188 - compat_time_t msg_ctime; 186 + compat_ulong_t msg_ctime; 189 187 #ifdef CONFIG_CPU_LITTLE_ENDIAN 190 - compat_ulong_t __unused3; 188 + compat_ulong_t msg_ctime_high; 191 189 #endif 192 190 compat_ulong_t msg_cbytes; 193 191 compat_ulong_t msg_qnum; ··· 201 199 struct compat_shmid64_ds { 202 200 struct compat_ipc64_perm shm_perm; 203 201 compat_size_t shm_segsz; 204 - compat_time_t shm_atime; 205 - compat_time_t shm_dtime; 206 - compat_time_t shm_ctime; 202 + compat_ulong_t shm_atime; 203 + compat_ulong_t shm_dtime; 204 + compat_ulong_t shm_ctime; 207 205 compat_pid_t shm_cpid; 208 206 compat_pid_t shm_lpid; 209 207 compat_ulong_t shm_nattch; 210 - compat_ulong_t __unused1; 211 - compat_ulong_t __unused2; 208 + compat_ushort_t shm_atime_high; 209 + compat_ushort_t shm_dtime_high; 210 + compat_ushort_t shm_ctime_high; 211 + compat_ushort_t __unused2; 212 212 }; 213 213 214 214 /* MIPS has unusual order of fields in stack_t */
+38 -19
arch/mips/include/uapi/asm/msgbuf.h
··· 9 9 * between kernel and user space. 10 10 * 11 11 * Pad space is left for: 12 - * - extension of time_t to 64-bit on 32-bitsystem to solve the y2038 problem 13 12 * - 2 miscellaneous unsigned long values 14 13 */ 15 14 15 + #if defined(__mips64) 16 16 struct msqid64_ds { 17 17 struct ipc64_perm msg_perm; 18 - #if !defined(__mips64) && defined(__MIPSEB__) 19 - unsigned long __unused1; 20 - #endif 21 18 __kernel_time_t msg_stime; /* last msgsnd time */ 22 - #if !defined(__mips64) && defined(__MIPSEL__) 23 - unsigned long __unused1; 24 - #endif 25 - #if !defined(__mips64) && defined(__MIPSEB__) 26 - unsigned long __unused2; 27 - #endif 28 19 __kernel_time_t msg_rtime; /* last msgrcv time */ 29 - #if !defined(__mips64) && defined(__MIPSEL__) 30 - unsigned long __unused2; 31 - #endif 32 - #if !defined(__mips64) && defined(__MIPSEB__) 33 - unsigned long __unused3; 34 - #endif 35 20 __kernel_time_t msg_ctime; /* last change time */ 36 - #if !defined(__mips64) && defined(__MIPSEL__) 37 - unsigned long __unused3; 38 - #endif 39 21 unsigned long msg_cbytes; /* current number of bytes on queue */ 40 22 unsigned long msg_qnum; /* number of messages in queue */ 41 23 unsigned long msg_qbytes; /* max number of bytes on queue */ ··· 26 44 unsigned long __unused4; 27 45 unsigned long __unused5; 28 46 }; 47 + #elif defined (__MIPSEB__) 48 + struct msqid64_ds { 49 + struct ipc64_perm msg_perm; 50 + unsigned long msg_stime_high; 51 + unsigned long msg_stime; /* last msgsnd time */ 52 + unsigned long msg_rtime_high; 53 + unsigned long msg_rtime; /* last msgrcv time */ 54 + unsigned long msg_ctime_high; 55 + unsigned long msg_ctime; /* last change time */ 56 + unsigned long msg_cbytes; /* current number of bytes on queue */ 57 + unsigned long msg_qnum; /* number of messages in queue */ 58 + unsigned long msg_qbytes; /* max number of bytes on queue */ 59 + __kernel_pid_t msg_lspid; /* pid of last msgsnd */ 60 + __kernel_pid_t msg_lrpid; /* last receive pid */ 61 + unsigned long __unused4; 62 + unsigned long __unused5; 63 + }; 64 + #elif defined (__MIPSEL__) 65 + struct msqid64_ds { 66 + struct ipc64_perm msg_perm; 67 + unsigned long msg_stime; /* last msgsnd time */ 68 + unsigned long msg_stime_high; 69 + unsigned long msg_rtime; /* last msgrcv time */ 70 + unsigned long msg_rtime_high; 71 + unsigned long msg_ctime; /* last change time */ 72 + unsigned long msg_ctime_high; 73 + unsigned long msg_cbytes; /* current number of bytes on queue */ 74 + unsigned long msg_qnum; /* number of messages in queue */ 75 + unsigned long msg_qbytes; /* max number of bytes on queue */ 76 + __kernel_pid_t msg_lspid; /* pid of last msgsnd */ 77 + __kernel_pid_t msg_lrpid; /* last receive pid */ 78 + unsigned long __unused4; 79 + unsigned long __unused5; 80 + }; 81 + #else 82 + #warning no endianess set 83 + #endif 29 84 30 85 #endif /* _ASM_MSGBUF_H */
+13 -2
arch/mips/include/uapi/asm/sembuf.h
··· 7 7 * Note extra padding because this structure is passed back and forth 8 8 * between kernel and user space. 9 9 * 10 - * Pad space is left for: 11 - * - 2 miscellaneous 64-bit values 10 + * Pad space is left for 2 miscellaneous 64-bit values on mips64, 11 + * but used for the upper 32 bit of the time values on mips32. 12 12 */ 13 13 14 + #ifdef __mips64 14 15 struct semid64_ds { 15 16 struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 16 17 __kernel_time_t sem_otime; /* last semop time */ ··· 20 19 unsigned long __unused1; 21 20 unsigned long __unused2; 22 21 }; 22 + #else 23 + struct semid64_ds { 24 + struct ipc64_perm sem_perm; /* permissions .. see ipc.h */ 25 + unsigned long sem_otime; /* last semop time */ 26 + unsigned long sem_ctime; /* last change time */ 27 + unsigned long sem_nsems; /* no. of semaphores in array */ 28 + unsigned long sem_otime_high; 29 + unsigned long sem_ctime_high; 30 + }; 31 + #endif 23 32 24 33 #endif /* _ASM_SEMBUF_H */
+21 -2
arch/mips/include/uapi/asm/shmbuf.h
··· 7 7 * Note extra padding because this structure is passed back and forth 8 8 * between kernel and user space. 9 9 * 10 - * Pad space is left for: 11 - * - 2 miscellaneous 32-bit rsp. 64-bit values 10 + * As MIPS was lacking proper padding after shm_?time, we use 48 bits 11 + * of the padding at the end to store a few additional bits of the time. 12 + * libc implementations need to take care to convert this into a proper 13 + * data structure when moving to 64-bit time_t. 12 14 */ 13 15 16 + #ifdef __mips64 14 17 struct shmid64_ds { 15 18 struct ipc64_perm shm_perm; /* operation perms */ 16 19 size_t shm_segsz; /* size of segment (bytes) */ ··· 26 23 unsigned long __unused1; 27 24 unsigned long __unused2; 28 25 }; 26 + #else 27 + struct shmid64_ds { 28 + struct ipc64_perm shm_perm; /* operation perms */ 29 + size_t shm_segsz; /* size of segment (bytes) */ 30 + unsigned long shm_atime; /* last attach time */ 31 + unsigned long shm_dtime; /* last detach time */ 32 + unsigned long shm_ctime; /* last change time */ 33 + __kernel_pid_t shm_cpid; /* pid of creator */ 34 + __kernel_pid_t shm_lpid; /* pid of last operator */ 35 + unsigned long shm_nattch; /* no. of current attaches */ 36 + unsigned short shm_atime_high; 37 + unsigned short shm_dtime_high; 38 + unsigned short shm_ctime_high; 39 + unsigned short __unused1; 40 + }; 41 + #endif 29 42 30 43 struct shminfo64 { 31 44 unsigned long shmmax;