Merge branch 'work.ipc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull ipc compat cleanup and 64-bit time_t from Al Viro:
"IPC copyin/copyout sanitizing, including 64bit time_t work from Deepa
Dinamani"

* 'work.ipc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
utimes: Make utimes y2038 safe
ipc: shm: Make shmid_kernel timestamps y2038 safe
ipc: sem: Make sem_array timestamps y2038 safe
ipc: msg: Make msg_queue timestamps y2038 safe
ipc: mqueue: Replace timespec with timespec64
ipc: Make sys_semtimedop() y2038 safe
get rid of SYSVIPC_COMPAT on ia64
semtimedop(): move compat to native
shmat(2): move compat to native
msgrcv(2), msgsnd(2): move compat to native
ipc(2): move compat to native
ipc: make use of compat ipc_perm helpers
semctl(): move compat to native
semctl(): separate all layout-dependent copyin/copyout
msgctl(): move compat to native
msgctl(): split the actual work from copyin/copyout
ipc: move compat shmctl to native
shmctl: split the work from copyin/copyout

+1066 -1217
-5
arch/ia64/Kconfig.debug
··· 56 56 and restore instructions. It's useful for tracking down spinlock 57 57 problems, but slow! If you're unsure, select N. 58 58 59 - config SYSVIPC_COMPAT 60 - bool 61 - depends on COMPAT && SYSVIPC 62 - default y 63 - 64 59 endmenu
+12 -11
fs/utimes.c
··· 22 22 */ 23 23 SYSCALL_DEFINE2(utime, char __user *, filename, struct utimbuf __user *, times) 24 24 { 25 - struct timespec tv[2]; 25 + struct timespec64 tv[2]; 26 26 27 27 if (times) { 28 28 if (get_user(tv[0].tv_sec, &times->actime) || ··· 44 44 return nsec >= 0 && nsec <= 999999999; 45 45 } 46 46 47 - static int utimes_common(const struct path *path, struct timespec *times) 47 + static int utimes_common(const struct path *path, struct timespec64 *times) 48 48 { 49 49 int error; 50 50 struct iattr newattrs; ··· 115 115 * must be owner or have write permission. 116 116 * Else, update from *times, must be owner or super user. 117 117 */ 118 - long do_utimes(int dfd, const char __user *filename, struct timespec *times, 118 + long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, 119 119 int flags) 120 120 { 121 121 int error = -EINVAL; ··· 167 167 SYSCALL_DEFINE4(utimensat, int, dfd, const char __user *, filename, 168 168 struct timespec __user *, utimes, int, flags) 169 169 { 170 - struct timespec tstimes[2]; 170 + struct timespec64 tstimes[2]; 171 171 172 172 if (utimes) { 173 - if (copy_from_user(&tstimes, utimes, sizeof(tstimes))) 173 + if ((get_timespec64(&tstimes[0], &utimes[0]) || 174 + get_timespec64(&tstimes[1], &utimes[1]))) 174 175 return -EFAULT; 175 176 176 177 /* Nothing to do, we must not even check the path. */ ··· 187 186 struct timeval __user *, utimes) 188 187 { 189 188 struct timeval times[2]; 190 - struct timespec tstimes[2]; 189 + struct timespec64 tstimes[2]; 191 190 192 191 if (utimes) { 193 192 if (copy_from_user(&times, utimes, sizeof(times))) ··· 225 224 COMPAT_SYSCALL_DEFINE2(utime, const char __user *, filename, 226 225 struct compat_utimbuf __user *, t) 227 226 { 228 - struct timespec tv[2]; 227 + struct timespec64 tv[2]; 229 228 230 229 if (t) { 231 230 if (get_user(tv[0].tv_sec, &t->actime) || ··· 239 238 240 239 COMPAT_SYSCALL_DEFINE4(utimensat, unsigned int, dfd, const char __user *, filename, struct compat_timespec __user *, t, int, flags) 241 240 { 242 - struct timespec tv[2]; 241 + struct timespec64 tv[2]; 243 242 244 243 if (t) { 245 - if (compat_get_timespec(&tv[0], &t[0]) || 246 - compat_get_timespec(&tv[1], &t[1])) 244 + if (compat_get_timespec64(&tv[0], &t[0]) || 245 + compat_get_timespec64(&tv[1], &t[1])) 247 246 return -EFAULT; 248 247 249 248 if (tv[0].tv_nsec == UTIME_OMIT && tv[1].tv_nsec == UTIME_OMIT) ··· 254 253 255 254 COMPAT_SYSCALL_DEFINE3(futimesat, unsigned int, dfd, const char __user *, filename, struct compat_timeval __user *, t) 256 255 { 257 - struct timespec tv[2]; 256 + struct timespec64 tv[2]; 258 257 259 258 if (t) { 260 259 if (get_user(tv[0].tv_sec, &t[0].tv_sec) ||
+3 -3
include/linux/audit.h
··· 351 351 extern int __audit_sockaddr(int len, void *addr); 352 352 extern void __audit_fd_pair(int fd1, int fd2); 353 353 extern void __audit_mq_open(int oflag, umode_t mode, struct mq_attr *attr); 354 - extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout); 354 + extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout); 355 355 extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification); 356 356 extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); 357 357 extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm, ··· 412 412 if (unlikely(!audit_dummy_context())) 413 413 __audit_mq_open(oflag, mode, attr); 414 414 } 415 - static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) 415 + static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec64 *abs_timeout) 416 416 { 417 417 if (unlikely(!audit_dummy_context())) 418 418 __audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout); ··· 549 549 { } 550 550 static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, 551 551 unsigned int msg_prio, 552 - const struct timespec *abs_timeout) 552 + const struct timespec64 *abs_timeout) 553 553 { } 554 554 static inline void audit_mq_notify(mqd_t mqdes, 555 555 const struct sigevent *notification)
-9
include/linux/compat.h
··· 171 171 extern int put_compat_itimerspec64(const struct itimerspec64 *its, 172 172 struct compat_itimerspec __user *uits); 173 173 174 - /* 175 - * This function convert a timespec if necessary and returns a *user 176 - * space* pointer. If no conversion is necessary, it returns the 177 - * initial pointer. NULL is a legitimate argument and will always 178 - * output NULL. 179 - */ 180 - extern int compat_convert_timespec(struct timespec __user **, 181 - const void __user *); 182 - 183 174 struct compat_iovec { 184 175 compat_uptr_t iov_base; 185 176 compat_size_t iov_len;
+4 -11
include/linux/msg.h
··· 2 2 #define _LINUX_MSG_H 3 3 4 4 #include <linux/list.h> 5 + #include <linux/time64.h> 5 6 #include <uapi/linux/msg.h> 6 7 7 8 /* one msg_msg structure for each message */ ··· 18 17 /* one msq_queue structure for each present queue on the system */ 19 18 struct msg_queue { 20 19 struct kern_ipc_perm q_perm; 21 - time_t q_stime; /* last msgsnd time */ 22 - time_t q_rtime; /* last msgrcv time */ 23 - time_t q_ctime; /* last change time */ 20 + time64_t q_stime; /* last msgsnd time */ 21 + time64_t q_rtime; /* last msgrcv time */ 22 + time64_t q_ctime; /* last change time */ 24 23 unsigned long q_cbytes; /* current number of bytes on queue */ 25 24 unsigned long q_qnum; /* number of messages in queue */ 26 25 unsigned long q_qbytes; /* max number of bytes on queue */ ··· 31 30 struct list_head q_receivers; 32 31 struct list_head q_senders; 33 32 } __randomize_layout; 34 - 35 - /* Helper routines for sys_msgsnd and sys_msgrcv */ 36 - extern long do_msgsnd(int msqid, long mtype, void __user *mtext, 37 - size_t msgsz, int msgflg); 38 - extern long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, 39 - int msgflg, 40 - long (*msg_fill)(void __user *, struct msg_msg *, 41 - size_t)); 42 33 43 34 #endif /* _LINUX_MSG_H */
+2 -1
include/linux/sem.h
··· 4 4 #include <linux/atomic.h> 5 5 #include <linux/rcupdate.h> 6 6 #include <linux/cache.h> 7 + #include <linux/time64.h> 7 8 #include <uapi/linux/sem.h> 8 9 9 10 struct task_struct; ··· 31 30 /* One sem_array data structure for each set of semaphores in the system. */ 32 31 struct sem_array { 33 32 struct kern_ipc_perm sem_perm; /* permissions .. see ipc.h */ 34 - time_t sem_ctime; /* create/last semctl() time */ 33 + time64_t sem_ctime; /* create/last semctl() time */ 35 34 struct list_head pending_alter; /* pending operations */ 36 35 /* that alter the array */ 37 36 struct list_head pending_const; /* pending complex operations */
+3 -3
include/linux/shm.h
··· 12 12 struct file *shm_file; 13 13 unsigned long shm_nattch; 14 14 unsigned long shm_segsz; 15 - time_t shm_atim; 16 - time_t shm_dtim; 17 - time_t shm_ctim; 15 + time64_t shm_atim; 16 + time64_t shm_dtim; 17 + time64_t shm_ctim; 18 18 pid_t shm_cprid; 19 19 pid_t shm_lprid; 20 20 struct user_struct *mlock_user;
+1 -1
include/linux/time.h
··· 178 178 struct itimerval *ovalue); 179 179 extern int do_getitimer(int which, struct itimerval *value); 180 180 181 - extern long do_utimes(int dfd, const char __user *filename, struct timespec *times, int flags); 181 + extern long do_utimes(int dfd, const char __user *filename, struct timespec64 *times, int flags); 182 182 183 183 /* 184 184 * Similar to the struct tm in userspace <time.h>, but it needs to be here so
+1 -1
init/initramfs.c
··· 110 110 111 111 static long __init do_utime(char *filename, time_t mtime) 112 112 { 113 - struct timespec t[2]; 113 + struct timespec64 t[2]; 114 114 115 115 t[0].tv_sec = mtime; 116 116 t[0].tv_nsec = 0;
+32 -708
ipc/compat.c
··· 34 34 35 35 #include "util.h" 36 36 37 - struct compat_msgbuf { 38 - compat_long_t mtype; 39 - char mtext[1]; 40 - }; 41 - 42 - struct compat_ipc_perm { 43 - key_t key; 44 - __compat_uid_t uid; 45 - __compat_gid_t gid; 46 - __compat_uid_t cuid; 47 - __compat_gid_t cgid; 48 - compat_mode_t mode; 49 - unsigned short seq; 50 - }; 51 - 52 - struct compat_semid_ds { 53 - struct compat_ipc_perm sem_perm; 54 - compat_time_t sem_otime; 55 - compat_time_t sem_ctime; 56 - compat_uptr_t sem_base; 57 - compat_uptr_t sem_pending; 58 - compat_uptr_t sem_pending_last; 59 - compat_uptr_t undo; 60 - unsigned short sem_nsems; 61 - }; 62 - 63 - struct compat_msqid_ds { 64 - struct compat_ipc_perm msg_perm; 65 - compat_uptr_t msg_first; 66 - compat_uptr_t msg_last; 67 - compat_time_t msg_stime; 68 - compat_time_t msg_rtime; 69 - compat_time_t msg_ctime; 70 - compat_ulong_t msg_lcbytes; 71 - compat_ulong_t msg_lqbytes; 72 - unsigned short msg_cbytes; 73 - unsigned short msg_qnum; 74 - unsigned short msg_qbytes; 75 - compat_ipc_pid_t msg_lspid; 76 - compat_ipc_pid_t msg_lrpid; 77 - }; 78 - 79 - struct compat_shmid_ds { 80 - struct compat_ipc_perm shm_perm; 81 - int shm_segsz; 82 - compat_time_t shm_atime; 83 - compat_time_t shm_dtime; 84 - compat_time_t shm_ctime; 85 - compat_ipc_pid_t shm_cpid; 86 - compat_ipc_pid_t shm_lpid; 87 - unsigned short shm_nattch; 88 - unsigned short shm_unused; 89 - compat_uptr_t shm_unused2; 90 - compat_uptr_t shm_unused3; 91 - }; 92 - 93 - struct compat_ipc_kludge { 94 - compat_uptr_t msgp; 95 - compat_long_t msgtyp; 96 - }; 97 - 98 - struct compat_shminfo64 { 99 - compat_ulong_t shmmax; 100 - compat_ulong_t shmmin; 101 - compat_ulong_t shmmni; 102 - compat_ulong_t shmseg; 103 - compat_ulong_t shmall; 104 - compat_ulong_t __unused1; 105 - compat_ulong_t __unused2; 106 - compat_ulong_t __unused3; 107 - compat_ulong_t __unused4; 108 - }; 109 - 110 - struct compat_shm_info { 111 - compat_int_t used_ids; 112 - compat_ulong_t shm_tot, shm_rss, shm_swp; 113 - compat_ulong_t swap_attempts, swap_successes; 114 - }; 115 - 116 - static inline int compat_ipc_parse_version(int *cmd) 37 + int get_compat_ipc64_perm(struct ipc64_perm *to, 38 + struct compat_ipc64_perm __user *from) 117 39 { 118 - #ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION 119 - int version = *cmd & IPC_64; 120 - 121 - /* this is tricky: architectures that have support for the old 122 - * ipc structures in 64 bit binaries need to have IPC_64 set 123 - * in cmd, the others need to have it cleared */ 124 - #ifndef ipc_parse_version 125 - *cmd |= IPC_64; 126 - #else 127 - *cmd &= ~IPC_64; 128 - #endif 129 - return version; 130 - #else 131 - /* With the asm-generic APIs, we always use the 64-bit versions. */ 132 - return IPC_64; 133 - #endif 134 - } 135 - 136 - static inline int __get_compat_ipc64_perm(struct ipc64_perm *p64, 137 - struct compat_ipc64_perm __user *up64) 138 - { 139 - int err; 140 - 141 - err = __get_user(p64->uid, &up64->uid); 142 - err |= __get_user(p64->gid, &up64->gid); 143 - err |= __get_user(p64->mode, &up64->mode); 144 - return err; 145 - } 146 - 147 - static inline int __get_compat_ipc_perm(struct ipc64_perm *p, 148 - struct compat_ipc_perm __user *up) 149 - { 150 - int err; 151 - 152 - err = __get_user(p->uid, &up->uid); 153 - err |= __get_user(p->gid, &up->gid); 154 - err |= __get_user(p->mode, &up->mode); 155 - return err; 156 - } 157 - 158 - static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64, 159 - struct compat_ipc64_perm __user *up64) 160 - { 161 - int err; 162 - 163 - err = __put_user(p64->key, &up64->key); 164 - err |= __put_user(p64->uid, &up64->uid); 165 - err |= __put_user(p64->gid, &up64->gid); 166 - err |= __put_user(p64->cuid, &up64->cuid); 167 - err |= __put_user(p64->cgid, &up64->cgid); 168 - err |= __put_user(p64->mode, &up64->mode); 169 - err |= __put_user(p64->seq, &up64->seq); 170 - return err; 171 - } 172 - 173 - static inline int __put_compat_ipc_perm(struct ipc64_perm *p, 174 - struct compat_ipc_perm __user *uip) 175 - { 176 - int err; 177 - __compat_uid_t u; 178 - __compat_gid_t g; 179 - 180 - err = __put_user(p->key, &uip->key); 181 - SET_UID(u, p->uid); 182 - err |= __put_user(u, &uip->uid); 183 - SET_GID(g, p->gid); 184 - err |= __put_user(g, &uip->gid); 185 - SET_UID(u, p->cuid); 186 - err |= __put_user(u, &uip->cuid); 187 - SET_GID(g, p->cgid); 188 - err |= __put_user(g, &uip->cgid); 189 - err |= __put_user(p->mode, &uip->mode); 190 - err |= __put_user(p->seq, &uip->seq); 191 - return err; 192 - } 193 - 194 - static inline int get_compat_semid64_ds(struct semid64_ds *sem64, 195 - struct compat_semid64_ds __user *up64) 196 - { 197 - if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) 40 + struct compat_ipc64_perm v; 41 + if (copy_from_user(&v, from, sizeof(v))) 198 42 return -EFAULT; 199 - return __get_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm); 43 + to->uid = v.uid; 44 + to->gid = v.gid; 45 + to->mode = v.mode; 46 + return 0; 200 47 } 201 48 202 - static inline int get_compat_semid_ds(struct semid64_ds *s, 203 - struct compat_semid_ds __user *up) 49 + int get_compat_ipc_perm(struct ipc64_perm *to, 50 + struct compat_ipc_perm __user *from) 204 51 { 205 - if (!access_ok(VERIFY_READ, up, sizeof(*up))) 52 + struct compat_ipc_perm v; 53 + if (copy_from_user(&v, from, sizeof(v))) 206 54 return -EFAULT; 207 - return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm); 55 + to->uid = v.uid; 56 + to->gid = v.gid; 57 + to->mode = v.mode; 58 + return 0; 208 59 } 209 60 210 - static inline int put_compat_semid64_ds(struct semid64_ds *sem64, 211 - struct compat_semid64_ds __user *up64) 61 + void to_compat_ipc64_perm(struct compat_ipc64_perm *to, struct ipc64_perm *from) 212 62 { 213 - int err; 214 - 215 - if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 216 - return -EFAULT; 217 - err = __put_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm); 218 - err |= __put_user(sem64->sem_otime, &up64->sem_otime); 219 - err |= __put_user(sem64->sem_ctime, &up64->sem_ctime); 220 - err |= __put_user(sem64->sem_nsems, &up64->sem_nsems); 221 - return err; 63 + to->key = from->key; 64 + to->uid = from->uid; 65 + to->gid = from->gid; 66 + to->cuid = from->cuid; 67 + to->cgid = from->cgid; 68 + to->mode = from->mode; 69 + to->seq = from->seq; 222 70 } 223 71 224 - static inline int put_compat_semid_ds(struct semid64_ds *s, 225 - struct compat_semid_ds __user *up) 72 + void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from) 226 73 { 227 - int err; 228 - 229 - if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 230 - return -EFAULT; 231 - err = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm); 232 - err |= __put_user(s->sem_otime, &up->sem_otime); 233 - err |= __put_user(s->sem_ctime, &up->sem_ctime); 234 - err |= __put_user(s->sem_nsems, &up->sem_nsems); 235 - return err; 236 - } 237 - 238 - static long do_compat_semctl(int first, int second, int third, u32 pad) 239 - { 240 - unsigned long fourth; 241 - int err, err2; 242 - struct semid64_ds sem64; 243 - struct semid64_ds __user *up64; 244 - int version = compat_ipc_parse_version(&third); 245 - 246 - memset(&sem64, 0, sizeof(sem64)); 247 - 248 - if ((third & (~IPC_64)) == SETVAL) 249 - #ifdef __BIG_ENDIAN 250 - fourth = (unsigned long)pad << 32; 251 - #else 252 - fourth = pad; 253 - #endif 254 - else 255 - fourth = (unsigned long)compat_ptr(pad); 256 - switch (third & (~IPC_64)) { 257 - case IPC_INFO: 258 - case IPC_RMID: 259 - case SEM_INFO: 260 - case GETVAL: 261 - case GETPID: 262 - case GETNCNT: 263 - case GETZCNT: 264 - case GETALL: 265 - case SETVAL: 266 - case SETALL: 267 - err = sys_semctl(first, second, third, fourth); 268 - break; 269 - 270 - case IPC_STAT: 271 - case SEM_STAT: 272 - up64 = compat_alloc_user_space(sizeof(sem64)); 273 - fourth = (unsigned long)up64; 274 - err = sys_semctl(first, second, third, fourth); 275 - if (err < 0) 276 - break; 277 - if (copy_from_user(&sem64, up64, sizeof(sem64))) 278 - err2 = -EFAULT; 279 - else if (version == IPC_64) 280 - err2 = put_compat_semid64_ds(&sem64, compat_ptr(pad)); 281 - else 282 - err2 = put_compat_semid_ds(&sem64, compat_ptr(pad)); 283 - if (err2) 284 - err = -EFAULT; 285 - break; 286 - 287 - case IPC_SET: 288 - if (version == IPC_64) 289 - err = get_compat_semid64_ds(&sem64, compat_ptr(pad)); 290 - else 291 - err = get_compat_semid_ds(&sem64, compat_ptr(pad)); 292 - 293 - up64 = compat_alloc_user_space(sizeof(sem64)); 294 - if (copy_to_user(up64, &sem64, sizeof(sem64))) 295 - err = -EFAULT; 296 - if (err) 297 - break; 298 - 299 - fourth = (unsigned long)up64; 300 - err = sys_semctl(first, second, third, fourth); 301 - break; 302 - 303 - default: 304 - err = -EINVAL; 305 - break; 306 - } 307 - return err; 308 - } 309 - 310 - static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) 311 - { 312 - struct compat_msgbuf __user *msgp = dest; 313 - size_t msgsz; 314 - 315 - if (put_user(msg->m_type, &msgp->mtype)) 316 - return -EFAULT; 317 - 318 - msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz; 319 - if (store_msg(msgp->mtext, msg, msgsz)) 320 - return -EFAULT; 321 - return msgsz; 322 - } 323 - 324 - #ifndef COMPAT_SHMLBA 325 - #define COMPAT_SHMLBA SHMLBA 326 - #endif 327 - 328 - #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC 329 - COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second, 330 - u32, third, compat_uptr_t, ptr, u32, fifth) 331 - { 332 - int version; 333 - u32 pad; 334 - 335 - version = call >> 16; /* hack for backward compatibility */ 336 - call &= 0xffff; 337 - 338 - switch (call) { 339 - case SEMOP: 340 - /* struct sembuf is the same on 32 and 64bit :)) */ 341 - return sys_semtimedop(first, compat_ptr(ptr), second, NULL); 342 - case SEMTIMEDOP: 343 - return compat_sys_semtimedop(first, compat_ptr(ptr), second, 344 - compat_ptr(fifth)); 345 - case SEMGET: 346 - return sys_semget(first, second, third); 347 - case SEMCTL: 348 - if (!ptr) 349 - return -EINVAL; 350 - if (get_user(pad, (u32 __user *) compat_ptr(ptr))) 351 - return -EFAULT; 352 - return do_compat_semctl(first, second, third, pad); 353 - 354 - case MSGSND: { 355 - struct compat_msgbuf __user *up = compat_ptr(ptr); 356 - compat_long_t type; 357 - 358 - if (first < 0 || second < 0) 359 - return -EINVAL; 360 - 361 - if (get_user(type, &up->mtype)) 362 - return -EFAULT; 363 - 364 - return do_msgsnd(first, type, up->mtext, second, third); 365 - } 366 - case MSGRCV: { 367 - void __user *uptr = compat_ptr(ptr); 368 - 369 - if (first < 0 || second < 0) 370 - return -EINVAL; 371 - 372 - if (!version) { 373 - struct compat_ipc_kludge ipck; 374 - if (!uptr) 375 - return -EINVAL; 376 - if (copy_from_user(&ipck, uptr, sizeof(ipck))) 377 - return -EFAULT; 378 - uptr = compat_ptr(ipck.msgp); 379 - fifth = ipck.msgtyp; 380 - } 381 - return do_msgrcv(first, uptr, second, (s32)fifth, third, 382 - compat_do_msg_fill); 383 - } 384 - case MSGGET: 385 - return sys_msgget(first, second); 386 - case MSGCTL: 387 - return compat_sys_msgctl(first, second, compat_ptr(ptr)); 388 - 389 - case SHMAT: { 390 - int err; 391 - unsigned long raddr; 392 - 393 - if (version == 1) 394 - return -EINVAL; 395 - err = do_shmat(first, compat_ptr(ptr), second, &raddr, 396 - COMPAT_SHMLBA); 397 - if (err < 0) 398 - return err; 399 - return put_user(raddr, (compat_ulong_t *)compat_ptr(third)); 400 - } 401 - case SHMDT: 402 - return sys_shmdt(compat_ptr(ptr)); 403 - case SHMGET: 404 - return sys_shmget(first, (unsigned)second, third); 405 - case SHMCTL: 406 - return compat_sys_shmctl(first, second, compat_ptr(ptr)); 407 - } 408 - 409 - return -ENOSYS; 410 - } 411 - #endif 412 - 413 - COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg) 414 - { 415 - return do_compat_semctl(semid, semnum, cmd, arg); 416 - } 417 - 418 - COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp, 419 - compat_ssize_t, msgsz, int, msgflg) 420 - { 421 - struct compat_msgbuf __user *up = compat_ptr(msgp); 422 - compat_long_t mtype; 423 - 424 - if (get_user(mtype, &up->mtype)) 425 - return -EFAULT; 426 - return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg); 427 - } 428 - 429 - COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp, 430 - compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg) 431 - { 432 - return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp, 433 - msgflg, compat_do_msg_fill); 434 - } 435 - 436 - static inline int get_compat_msqid64(struct msqid64_ds *m64, 437 - struct compat_msqid64_ds __user *up64) 438 - { 439 - int err; 440 - 441 - if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) 442 - return -EFAULT; 443 - err = __get_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm); 444 - err |= __get_user(m64->msg_qbytes, &up64->msg_qbytes); 445 - return err; 446 - } 447 - 448 - static inline int get_compat_msqid(struct msqid64_ds *m, 449 - struct compat_msqid_ds __user *up) 450 - { 451 - int err; 452 - 453 - if (!access_ok(VERIFY_READ, up, sizeof(*up))) 454 - return -EFAULT; 455 - err = __get_compat_ipc_perm(&m->msg_perm, &up->msg_perm); 456 - err |= __get_user(m->msg_qbytes, &up->msg_qbytes); 457 - return err; 458 - } 459 - 460 - static inline int put_compat_msqid64_ds(struct msqid64_ds *m64, 461 - struct compat_msqid64_ds __user *up64) 462 - { 463 - int err; 464 - 465 - if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 466 - return -EFAULT; 467 - err = __put_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm); 468 - err |= __put_user(m64->msg_stime, &up64->msg_stime); 469 - err |= __put_user(m64->msg_rtime, &up64->msg_rtime); 470 - err |= __put_user(m64->msg_ctime, &up64->msg_ctime); 471 - err |= __put_user(m64->msg_cbytes, &up64->msg_cbytes); 472 - err |= __put_user(m64->msg_qnum, &up64->msg_qnum); 473 - err |= __put_user(m64->msg_qbytes, &up64->msg_qbytes); 474 - err |= __put_user(m64->msg_lspid, &up64->msg_lspid); 475 - err |= __put_user(m64->msg_lrpid, &up64->msg_lrpid); 476 - return err; 477 - } 478 - 479 - static inline int put_compat_msqid_ds(struct msqid64_ds *m, 480 - struct compat_msqid_ds __user *up) 481 - { 482 - int err; 483 - 484 - if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 485 - return -EFAULT; 486 - err = __put_compat_ipc_perm(&m->msg_perm, &up->msg_perm); 487 - err |= __put_user(m->msg_stime, &up->msg_stime); 488 - err |= __put_user(m->msg_rtime, &up->msg_rtime); 489 - err |= __put_user(m->msg_ctime, &up->msg_ctime); 490 - err |= __put_user(m->msg_cbytes, &up->msg_cbytes); 491 - err |= __put_user(m->msg_qnum, &up->msg_qnum); 492 - err |= __put_user(m->msg_qbytes, &up->msg_qbytes); 493 - err |= __put_user(m->msg_lspid, &up->msg_lspid); 494 - err |= __put_user(m->msg_lrpid, &up->msg_lrpid); 495 - return err; 496 - } 497 - 498 - COMPAT_SYSCALL_DEFINE3(msgctl, int, first, int, second, void __user *, uptr) 499 - { 500 - int err, err2; 501 - struct msqid64_ds m64; 502 - int version = compat_ipc_parse_version(&second); 503 - void __user *p; 504 - 505 - memset(&m64, 0, sizeof(m64)); 506 - 507 - switch (second & (~IPC_64)) { 508 - case IPC_INFO: 509 - case IPC_RMID: 510 - case MSG_INFO: 511 - err = sys_msgctl(first, second, uptr); 512 - break; 513 - 514 - case IPC_SET: 515 - if (version == IPC_64) 516 - err = get_compat_msqid64(&m64, uptr); 517 - else 518 - err = get_compat_msqid(&m64, uptr); 519 - 520 - if (err) 521 - break; 522 - p = compat_alloc_user_space(sizeof(m64)); 523 - if (copy_to_user(p, &m64, sizeof(m64))) 524 - err = -EFAULT; 525 - else 526 - err = sys_msgctl(first, second, p); 527 - break; 528 - 529 - case IPC_STAT: 530 - case MSG_STAT: 531 - p = compat_alloc_user_space(sizeof(m64)); 532 - err = sys_msgctl(first, second, p); 533 - if (err < 0) 534 - break; 535 - if (copy_from_user(&m64, p, sizeof(m64))) 536 - err2 = -EFAULT; 537 - else if (version == IPC_64) 538 - err2 = put_compat_msqid64_ds(&m64, uptr); 539 - else 540 - err2 = put_compat_msqid_ds(&m64, uptr); 541 - if (err2) 542 - err = -EFAULT; 543 - break; 544 - 545 - default: 546 - err = -EINVAL; 547 - break; 548 - } 549 - return err; 550 - } 551 - 552 - COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg) 553 - { 554 - unsigned long ret; 555 - long err; 556 - 557 - err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA); 558 - if (err) 559 - return err; 560 - force_successful_syscall_return(); 561 - return (long)ret; 562 - } 563 - 564 - static inline int get_compat_shmid64_ds(struct shmid64_ds *sem64, 565 - struct compat_shmid64_ds __user *up64) 566 - { 567 - if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) 568 - return -EFAULT; 569 - return __get_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm); 570 - } 571 - 572 - static inline int get_compat_shmid_ds(struct shmid64_ds *s, 573 - struct compat_shmid_ds __user *up) 574 - { 575 - if (!access_ok(VERIFY_READ, up, sizeof(*up))) 576 - return -EFAULT; 577 - return __get_compat_ipc_perm(&s->shm_perm, &up->shm_perm); 578 - } 579 - 580 - static inline int put_compat_shmid64_ds(struct shmid64_ds *sem64, 581 - struct compat_shmid64_ds __user *up64) 582 - { 583 - int err; 584 - 585 - if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 586 - return -EFAULT; 587 - err = __put_compat_ipc64_perm(&sem64->shm_perm, &up64->shm_perm); 588 - err |= __put_user(sem64->shm_atime, &up64->shm_atime); 589 - err |= __put_user(sem64->shm_dtime, &up64->shm_dtime); 590 - err |= __put_user(sem64->shm_ctime, &up64->shm_ctime); 591 - err |= __put_user(sem64->shm_segsz, &up64->shm_segsz); 592 - err |= __put_user(sem64->shm_nattch, &up64->shm_nattch); 593 - err |= __put_user(sem64->shm_cpid, &up64->shm_cpid); 594 - err |= __put_user(sem64->shm_lpid, &up64->shm_lpid); 595 - return err; 596 - } 597 - 598 - static inline int put_compat_shmid_ds(struct shmid64_ds *s, 599 - struct compat_shmid_ds __user *up) 600 - { 601 - int err; 602 - 603 - if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 604 - return -EFAULT; 605 - err = __put_compat_ipc_perm(&s->shm_perm, &up->shm_perm); 606 - err |= __put_user(s->shm_atime, &up->shm_atime); 607 - err |= __put_user(s->shm_dtime, &up->shm_dtime); 608 - err |= __put_user(s->shm_ctime, &up->shm_ctime); 609 - err |= __put_user(s->shm_segsz, &up->shm_segsz); 610 - err |= __put_user(s->shm_nattch, &up->shm_nattch); 611 - err |= __put_user(s->shm_cpid, &up->shm_cpid); 612 - err |= __put_user(s->shm_lpid, &up->shm_lpid); 613 - return err; 614 - } 615 - 616 - static inline int put_compat_shminfo64(struct shminfo64 *smi, 617 - struct compat_shminfo64 __user *up64) 618 - { 619 - int err; 620 - 621 - if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) 622 - return -EFAULT; 623 - if (smi->shmmax > INT_MAX) 624 - smi->shmmax = INT_MAX; 625 - err = __put_user(smi->shmmax, &up64->shmmax); 626 - err |= __put_user(smi->shmmin, &up64->shmmin); 627 - err |= __put_user(smi->shmmni, &up64->shmmni); 628 - err |= __put_user(smi->shmseg, &up64->shmseg); 629 - err |= __put_user(smi->shmall, &up64->shmall); 630 - return err; 631 - } 632 - 633 - static inline int put_compat_shminfo(struct shminfo64 *smi, 634 - struct shminfo __user *up) 635 - { 636 - int err; 637 - 638 - if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 639 - return -EFAULT; 640 - if (smi->shmmax > INT_MAX) 641 - smi->shmmax = INT_MAX; 642 - err = __put_user(smi->shmmax, &up->shmmax); 643 - err |= __put_user(smi->shmmin, &up->shmmin); 644 - err |= __put_user(smi->shmmni, &up->shmmni); 645 - err |= __put_user(smi->shmseg, &up->shmseg); 646 - err |= __put_user(smi->shmall, &up->shmall); 647 - return err; 648 - } 649 - 650 - static inline int put_compat_shm_info(struct shm_info __user *ip, 651 - struct compat_shm_info __user *uip) 652 - { 653 - int err; 654 - struct shm_info si; 655 - 656 - if (!access_ok(VERIFY_WRITE, uip, sizeof(*uip)) || 657 - copy_from_user(&si, ip, sizeof(si))) 658 - return -EFAULT; 659 - err = __put_user(si.used_ids, &uip->used_ids); 660 - err |= __put_user(si.shm_tot, &uip->shm_tot); 661 - err |= __put_user(si.shm_rss, &uip->shm_rss); 662 - err |= __put_user(si.shm_swp, &uip->shm_swp); 663 - err |= __put_user(si.swap_attempts, &uip->swap_attempts); 664 - err |= __put_user(si.swap_successes, &uip->swap_successes); 665 - return err; 666 - } 667 - 668 - COMPAT_SYSCALL_DEFINE3(shmctl, int, first, int, second, void __user *, uptr) 669 - { 670 - void __user *p; 671 - struct shmid64_ds sem64; 672 - struct shminfo64 smi; 673 - int err, err2; 674 - int version = compat_ipc_parse_version(&second); 675 - 676 - memset(&sem64, 0, sizeof(sem64)); 677 - 678 - switch (second & (~IPC_64)) { 679 - case IPC_RMID: 680 - case SHM_LOCK: 681 - case SHM_UNLOCK: 682 - err = sys_shmctl(first, second, uptr); 683 - break; 684 - 685 - case IPC_INFO: 686 - p = compat_alloc_user_space(sizeof(smi)); 687 - err = sys_shmctl(first, second, p); 688 - if (err < 0) 689 - break; 690 - if (copy_from_user(&smi, p, sizeof(smi))) 691 - err2 = -EFAULT; 692 - else if (version == IPC_64) 693 - err2 = put_compat_shminfo64(&smi, uptr); 694 - else 695 - err2 = put_compat_shminfo(&smi, uptr); 696 - if (err2) 697 - err = -EFAULT; 698 - break; 699 - 700 - 701 - case IPC_SET: 702 - if (version == IPC_64) 703 - err = get_compat_shmid64_ds(&sem64, uptr); 704 - else 705 - err = get_compat_shmid_ds(&sem64, uptr); 706 - 707 - if (err) 708 - break; 709 - p = compat_alloc_user_space(sizeof(sem64)); 710 - if (copy_to_user(p, &sem64, sizeof(sem64))) 711 - err = -EFAULT; 712 - else 713 - err = sys_shmctl(first, second, p); 714 - break; 715 - 716 - case IPC_STAT: 717 - case SHM_STAT: 718 - p = compat_alloc_user_space(sizeof(sem64)); 719 - err = sys_shmctl(first, second, p); 720 - if (err < 0) 721 - break; 722 - if (copy_from_user(&sem64, p, sizeof(sem64))) 723 - err2 = -EFAULT; 724 - else if (version == IPC_64) 725 - err2 = put_compat_shmid64_ds(&sem64, uptr); 726 - else 727 - err2 = put_compat_shmid_ds(&sem64, uptr); 728 - if (err2) 729 - err = -EFAULT; 730 - break; 731 - 732 - case SHM_INFO: 733 - p = compat_alloc_user_space(sizeof(struct shm_info)); 734 - err = sys_shmctl(first, second, p); 735 - if (err < 0) 736 - break; 737 - err2 = put_compat_shm_info(p, uptr); 738 - if (err2) 739 - err = -EFAULT; 740 - break; 741 - 742 - default: 743 - err = -EINVAL; 744 - break; 745 - } 746 - return err; 747 - } 748 - 749 - COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems, 750 - unsigned, nsops, 751 - const struct compat_timespec __user *, timeout) 752 - { 753 - struct timespec __user *ts64; 754 - if (compat_convert_timespec(&ts64, timeout)) 755 - return -EFAULT; 756 - return sys_semtimedop(semid, tsems, nsops, ts64); 74 + to->key = from->key; 75 + SET_UID(to->uid, from->uid); 76 + SET_GID(to->gid, from->gid); 77 + SET_UID(to->cuid, from->cuid); 78 + SET_GID(to->cgid, from->cgid); 79 + to->mode = from->mode; 80 + to->seq = from->seq; 757 81 }
+14 -14
ipc/mqueue.c
··· 668 668 } 669 669 670 670 static int prepare_timeout(const struct timespec __user *u_abs_timeout, 671 - struct timespec *ts) 671 + struct timespec64 *ts) 672 672 { 673 - if (copy_from_user(ts, u_abs_timeout, sizeof(struct timespec))) 673 + if (get_timespec64(ts, u_abs_timeout)) 674 674 return -EFAULT; 675 - if (!timespec_valid(ts)) 675 + if (!timespec64_valid(ts)) 676 676 return -EINVAL; 677 677 return 0; 678 678 } ··· 962 962 963 963 static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, 964 964 size_t msg_len, unsigned int msg_prio, 965 - struct timespec *ts) 965 + struct timespec64 *ts) 966 966 { 967 967 struct fd f; 968 968 struct inode *inode; ··· 979 979 return -EINVAL; 980 980 981 981 if (ts) { 982 - expires = timespec_to_ktime(*ts); 982 + expires = timespec64_to_ktime(*ts); 983 983 timeout = &expires; 984 984 } 985 985 ··· 1080 1080 1081 1081 static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, 1082 1082 size_t msg_len, unsigned int __user *u_msg_prio, 1083 - struct timespec *ts) 1083 + struct timespec64 *ts) 1084 1084 { 1085 1085 ssize_t ret; 1086 1086 struct msg_msg *msg_ptr; ··· 1092 1092 struct posix_msg_tree_node *new_leaf = NULL; 1093 1093 1094 1094 if (ts) { 1095 - expires = timespec_to_ktime(*ts); 1095 + expires = timespec64_to_ktime(*ts); 1096 1096 timeout = &expires; 1097 1097 } 1098 1098 ··· 1184 1184 size_t, msg_len, unsigned int, msg_prio, 1185 1185 const struct timespec __user *, u_abs_timeout) 1186 1186 { 1187 - struct timespec ts, *p = NULL; 1187 + struct timespec64 ts, *p = NULL; 1188 1188 if (u_abs_timeout) { 1189 1189 int res = prepare_timeout(u_abs_timeout, &ts); 1190 1190 if (res) ··· 1198 1198 size_t, msg_len, unsigned int __user *, u_msg_prio, 1199 1199 const struct timespec __user *, u_abs_timeout) 1200 1200 { 1201 - struct timespec ts, *p = NULL; 1201 + struct timespec64 ts, *p = NULL; 1202 1202 if (u_abs_timeout) { 1203 1203 int res = prepare_timeout(u_abs_timeout, &ts); 1204 1204 if (res) ··· 1475 1475 } 1476 1476 1477 1477 static int compat_prepare_timeout(const struct compat_timespec __user *p, 1478 - struct timespec *ts) 1478 + struct timespec64 *ts) 1479 1479 { 1480 - if (compat_get_timespec(ts, p)) 1480 + if (compat_get_timespec64(ts, p)) 1481 1481 return -EFAULT; 1482 - if (!timespec_valid(ts)) 1482 + if (!timespec64_valid(ts)) 1483 1483 return -EINVAL; 1484 1484 return 0; 1485 1485 } ··· 1489 1489 compat_size_t, msg_len, unsigned int, msg_prio, 1490 1490 const struct compat_timespec __user *, u_abs_timeout) 1491 1491 { 1492 - struct timespec ts, *p = NULL; 1492 + struct timespec64 ts, *p = NULL; 1493 1493 if (u_abs_timeout) { 1494 1494 int res = compat_prepare_timeout(u_abs_timeout, &ts); 1495 1495 if (res) ··· 1504 1504 compat_size_t, msg_len, unsigned int __user *, u_msg_prio, 1505 1505 const struct compat_timespec __user *, u_abs_timeout) 1506 1506 { 1507 - struct timespec ts, *p = NULL; 1507 + struct timespec64 ts, *p = NULL; 1508 1508 if (u_abs_timeout) { 1509 1509 int res = compat_prepare_timeout(u_abs_timeout, &ts); 1510 1510 if (res)
+258 -114
ipc/msg.c
··· 133 133 } 134 134 135 135 msq->q_stime = msq->q_rtime = 0; 136 - msq->q_ctime = get_seconds(); 136 + msq->q_ctime = ktime_get_real_seconds(); 137 137 msq->q_cbytes = msq->q_qnum = 0; 138 138 msq->q_qbytes = ns->msg_ctlmnb; 139 139 msq->q_lspid = msq->q_lrpid = 0; ··· 361 361 * NOTE: no locks must be held, the rwsem is taken inside this function. 362 362 */ 363 363 static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, 364 - struct msqid_ds __user *buf, int version) 364 + struct msqid64_ds *msqid64) 365 365 { 366 366 struct kern_ipc_perm *ipcp; 367 - struct msqid64_ds uninitialized_var(msqid64); 368 367 struct msg_queue *msq; 369 368 int err; 370 - 371 - if (cmd == IPC_SET) { 372 - if (copy_msqid_from_user(&msqid64, buf, version)) 373 - return -EFAULT; 374 - } 375 369 376 370 down_write(&msg_ids(ns).rwsem); 377 371 rcu_read_lock(); 378 372 379 373 ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd, 380 - &msqid64.msg_perm, msqid64.msg_qbytes); 374 + &msqid64->msg_perm, msqid64->msg_qbytes); 381 375 if (IS_ERR(ipcp)) { 382 376 err = PTR_ERR(ipcp); 383 377 goto out_unlock1; ··· 393 399 { 394 400 DEFINE_WAKE_Q(wake_q); 395 401 396 - if (msqid64.msg_qbytes > ns->msg_ctlmnb && 402 + if (msqid64->msg_qbytes > ns->msg_ctlmnb && 397 403 !capable(CAP_SYS_RESOURCE)) { 398 404 err = -EPERM; 399 405 goto out_unlock1; 400 406 } 401 407 402 408 ipc_lock_object(&msq->q_perm); 403 - err = ipc_update_perm(&msqid64.msg_perm, ipcp); 409 + err = ipc_update_perm(&msqid64->msg_perm, ipcp); 404 410 if (err) 405 411 goto out_unlock0; 406 412 407 - msq->q_qbytes = msqid64.msg_qbytes; 413 + msq->q_qbytes = msqid64->msg_qbytes; 408 414 409 - msq->q_ctime = get_seconds(); 415 + msq->q_ctime = ktime_get_real_seconds(); 410 416 /* 411 417 * Sleeping receivers might be excluded by 412 418 * stricter permissions. ··· 436 442 return err; 437 443 } 438 444 439 - static int msgctl_nolock(struct ipc_namespace *ns, int msqid, 440 - int cmd, int version, void __user *buf) 445 + static int msgctl_info(struct ipc_namespace *ns, int msqid, 446 + int cmd, struct msginfo *msginfo) 447 + { 448 + int err; 449 + int max_id; 450 + 451 + /* 452 + * We must not return kernel stack data. 453 + * due to padding, it's not enough 454 + * to set all member fields. 455 + */ 456 + err = security_msg_queue_msgctl(NULL, cmd); 457 + if (err) 458 + return err; 459 + 460 + memset(msginfo, 0, sizeof(*msginfo)); 461 + msginfo->msgmni = ns->msg_ctlmni; 462 + msginfo->msgmax = ns->msg_ctlmax; 463 + msginfo->msgmnb = ns->msg_ctlmnb; 464 + msginfo->msgssz = MSGSSZ; 465 + msginfo->msgseg = MSGSEG; 466 + down_read(&msg_ids(ns).rwsem); 467 + if (cmd == MSG_INFO) { 468 + msginfo->msgpool = msg_ids(ns).in_use; 469 + msginfo->msgmap = atomic_read(&ns->msg_hdrs); 470 + msginfo->msgtql = atomic_read(&ns->msg_bytes); 471 + } else { 472 + msginfo->msgmap = MSGMAP; 473 + msginfo->msgpool = MSGPOOL; 474 + msginfo->msgtql = MSGTQL; 475 + } 476 + max_id = ipc_get_maxid(&msg_ids(ns)); 477 + up_read(&msg_ids(ns).rwsem); 478 + return (max_id < 0) ? 0 : max_id; 479 + } 480 + 481 + static int msgctl_stat(struct ipc_namespace *ns, int msqid, 482 + int cmd, struct msqid64_ds *p) 441 483 { 442 484 int err; 443 485 struct msg_queue *msq; 486 + int success_return; 444 487 445 - switch (cmd) { 446 - case IPC_INFO: 447 - case MSG_INFO: 448 - { 449 - struct msginfo msginfo; 450 - int max_id; 488 + memset(p, 0, sizeof(*p)); 451 489 452 - if (!buf) 453 - return -EFAULT; 454 - 455 - /* 456 - * We must not return kernel stack data. 457 - * due to padding, it's not enough 458 - * to set all member fields. 459 - */ 460 - err = security_msg_queue_msgctl(NULL, cmd); 461 - if (err) 462 - return err; 463 - 464 - memset(&msginfo, 0, sizeof(msginfo)); 465 - msginfo.msgmni = ns->msg_ctlmni; 466 - msginfo.msgmax = ns->msg_ctlmax; 467 - msginfo.msgmnb = ns->msg_ctlmnb; 468 - msginfo.msgssz = MSGSSZ; 469 - msginfo.msgseg = MSGSEG; 470 - down_read(&msg_ids(ns).rwsem); 471 - if (cmd == MSG_INFO) { 472 - msginfo.msgpool = msg_ids(ns).in_use; 473 - msginfo.msgmap = atomic_read(&ns->msg_hdrs); 474 - msginfo.msgtql = atomic_read(&ns->msg_bytes); 475 - } else { 476 - msginfo.msgmap = MSGMAP; 477 - msginfo.msgpool = MSGPOOL; 478 - msginfo.msgtql = MSGTQL; 479 - } 480 - max_id = ipc_get_maxid(&msg_ids(ns)); 481 - up_read(&msg_ids(ns).rwsem); 482 - if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) 483 - return -EFAULT; 484 - return (max_id < 0) ? 0 : max_id; 485 - } 486 - 487 - case MSG_STAT: 488 - case IPC_STAT: 489 - { 490 - struct msqid64_ds tbuf; 491 - int success_return; 492 - 493 - if (!buf) 494 - return -EFAULT; 495 - 496 - memset(&tbuf, 0, sizeof(tbuf)); 497 - 498 - rcu_read_lock(); 499 - if (cmd == MSG_STAT) { 500 - msq = msq_obtain_object(ns, msqid); 501 - if (IS_ERR(msq)) { 502 - err = PTR_ERR(msq); 503 - goto out_unlock; 504 - } 505 - success_return = msq->q_perm.id; 506 - } else { 507 - msq = msq_obtain_object_check(ns, msqid); 508 - if (IS_ERR(msq)) { 509 - err = PTR_ERR(msq); 510 - goto out_unlock; 511 - } 512 - success_return = 0; 513 - } 514 - 515 - err = -EACCES; 516 - if (ipcperms(ns, &msq->q_perm, S_IRUGO)) 490 + rcu_read_lock(); 491 + if (cmd == MSG_STAT) { 492 + msq = msq_obtain_object(ns, msqid); 493 + if (IS_ERR(msq)) { 494 + err = PTR_ERR(msq); 517 495 goto out_unlock; 518 - 519 - err = security_msg_queue_msgctl(msq, cmd); 520 - if (err) 496 + } 497 + success_return = msq->q_perm.id; 498 + } else { 499 + msq = msq_obtain_object_check(ns, msqid); 500 + if (IS_ERR(msq)) { 501 + err = PTR_ERR(msq); 521 502 goto out_unlock; 522 - 523 - kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm); 524 - tbuf.msg_stime = msq->q_stime; 525 - tbuf.msg_rtime = msq->q_rtime; 526 - tbuf.msg_ctime = msq->q_ctime; 527 - tbuf.msg_cbytes = msq->q_cbytes; 528 - tbuf.msg_qnum = msq->q_qnum; 529 - tbuf.msg_qbytes = msq->q_qbytes; 530 - tbuf.msg_lspid = msq->q_lspid; 531 - tbuf.msg_lrpid = msq->q_lrpid; 532 - rcu_read_unlock(); 533 - 534 - if (copy_msqid_to_user(buf, &tbuf, version)) 535 - return -EFAULT; 536 - return success_return; 503 + } 504 + success_return = 0; 537 505 } 538 506 539 - default: 540 - return -EINVAL; 541 - } 507 + err = -EACCES; 508 + if (ipcperms(ns, &msq->q_perm, S_IRUGO)) 509 + goto out_unlock; 542 510 543 - return err; 511 + err = security_msg_queue_msgctl(msq, cmd); 512 + if (err) 513 + goto out_unlock; 514 + 515 + kernel_to_ipc64_perm(&msq->q_perm, &p->msg_perm); 516 + p->msg_stime = msq->q_stime; 517 + p->msg_rtime = msq->q_rtime; 518 + p->msg_ctime = msq->q_ctime; 519 + p->msg_cbytes = msq->q_cbytes; 520 + p->msg_qnum = msq->q_qnum; 521 + p->msg_qbytes = msq->q_qbytes; 522 + p->msg_lspid = msq->q_lspid; 523 + p->msg_lrpid = msq->q_lrpid; 524 + rcu_read_unlock(); 525 + 526 + return success_return; 527 + 544 528 out_unlock: 545 529 rcu_read_unlock(); 546 530 return err; ··· 528 556 { 529 557 int version; 530 558 struct ipc_namespace *ns; 559 + struct msqid64_ds msqid64; 560 + int err; 531 561 532 562 if (msqid < 0 || cmd < 0) 533 563 return -EINVAL; ··· 539 565 540 566 switch (cmd) { 541 567 case IPC_INFO: 542 - case MSG_INFO: 568 + case MSG_INFO: { 569 + struct msginfo msginfo; 570 + err = msgctl_info(ns, msqid, cmd, &msginfo); 571 + if (err < 0) 572 + return err; 573 + if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) 574 + err = -EFAULT; 575 + return err; 576 + } 543 577 case MSG_STAT: /* msqid is an index rather than a msg queue id */ 544 578 case IPC_STAT: 545 - return msgctl_nolock(ns, msqid, cmd, version, buf); 579 + err = msgctl_stat(ns, msqid, cmd, &msqid64); 580 + if (err < 0) 581 + return err; 582 + if (copy_msqid_to_user(buf, &msqid64, version)) 583 + err = -EFAULT; 584 + return err; 546 585 case IPC_SET: 586 + if (copy_msqid_from_user(&msqid64, buf, version)) 587 + return -EFAULT; 588 + /* fallthru */ 547 589 case IPC_RMID: 548 - return msgctl_down(ns, msqid, cmd, buf, version); 590 + return msgctl_down(ns, msqid, cmd, &msqid64); 549 591 default: 550 592 return -EINVAL; 551 593 } 552 594 } 595 + 596 + #ifdef CONFIG_COMPAT 597 + 598 + struct compat_msqid_ds { 599 + struct compat_ipc_perm msg_perm; 600 + compat_uptr_t msg_first; 601 + compat_uptr_t msg_last; 602 + compat_time_t msg_stime; 603 + compat_time_t msg_rtime; 604 + compat_time_t msg_ctime; 605 + compat_ulong_t msg_lcbytes; 606 + compat_ulong_t msg_lqbytes; 607 + unsigned short msg_cbytes; 608 + unsigned short msg_qnum; 609 + unsigned short msg_qbytes; 610 + compat_ipc_pid_t msg_lspid; 611 + compat_ipc_pid_t msg_lrpid; 612 + }; 613 + 614 + static int copy_compat_msqid_from_user(struct msqid64_ds *out, void __user *buf, 615 + int version) 616 + { 617 + memset(out, 0, sizeof(*out)); 618 + if (version == IPC_64) { 619 + struct compat_msqid64_ds *p = buf; 620 + if (get_compat_ipc64_perm(&out->msg_perm, &p->msg_perm)) 621 + return -EFAULT; 622 + if (get_user(out->msg_qbytes, &p->msg_qbytes)) 623 + return -EFAULT; 624 + } else { 625 + struct compat_msqid_ds *p = buf; 626 + if (get_compat_ipc_perm(&out->msg_perm, &p->msg_perm)) 627 + return -EFAULT; 628 + if (get_user(out->msg_qbytes, &p->msg_qbytes)) 629 + return -EFAULT; 630 + } 631 + return 0; 632 + } 633 + 634 + static int copy_compat_msqid_to_user(void __user *buf, struct msqid64_ds *in, 635 + int version) 636 + { 637 + if (version == IPC_64) { 638 + struct compat_msqid64_ds v; 639 + memset(&v, 0, sizeof(v)); 640 + to_compat_ipc64_perm(&v.msg_perm, &in->msg_perm); 641 + v.msg_stime = in->msg_stime; 642 + v.msg_rtime = in->msg_rtime; 643 + v.msg_ctime = in->msg_ctime; 644 + v.msg_cbytes = in->msg_cbytes; 645 + v.msg_qnum = in->msg_qnum; 646 + v.msg_qbytes = in->msg_qbytes; 647 + v.msg_lspid = in->msg_lspid; 648 + v.msg_lrpid = in->msg_lrpid; 649 + return copy_to_user(buf, &v, sizeof(v)); 650 + } else { 651 + struct compat_msqid_ds v; 652 + memset(&v, 0, sizeof(v)); 653 + to_compat_ipc_perm(&v.msg_perm, &in->msg_perm); 654 + v.msg_stime = in->msg_stime; 655 + v.msg_rtime = in->msg_rtime; 656 + v.msg_ctime = in->msg_ctime; 657 + v.msg_cbytes = in->msg_cbytes; 658 + v.msg_qnum = in->msg_qnum; 659 + v.msg_qbytes = in->msg_qbytes; 660 + v.msg_lspid = in->msg_lspid; 661 + v.msg_lrpid = in->msg_lrpid; 662 + return copy_to_user(buf, &v, sizeof(v)); 663 + } 664 + } 665 + 666 + COMPAT_SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, void __user *, uptr) 667 + { 668 + struct ipc_namespace *ns; 669 + int err; 670 + struct msqid64_ds msqid64; 671 + int version = compat_ipc_parse_version(&cmd); 672 + 673 + ns = current->nsproxy->ipc_ns; 674 + 675 + if (msqid < 0 || cmd < 0) 676 + return -EINVAL; 677 + 678 + switch (cmd & (~IPC_64)) { 679 + case IPC_INFO: 680 + case MSG_INFO: { 681 + struct msginfo msginfo; 682 + err = msgctl_info(ns, msqid, cmd, &msginfo); 683 + if (err < 0) 684 + return err; 685 + if (copy_to_user(uptr, &msginfo, sizeof(struct msginfo))) 686 + err = -EFAULT; 687 + return err; 688 + } 689 + case IPC_STAT: 690 + case MSG_STAT: 691 + err = msgctl_stat(ns, msqid, cmd, &msqid64); 692 + if (err < 0) 693 + return err; 694 + if (copy_compat_msqid_to_user(uptr, &msqid64, version)) 695 + err = -EFAULT; 696 + return err; 697 + case IPC_SET: 698 + if (copy_compat_msqid_from_user(&msqid64, uptr, version)) 699 + return -EFAULT; 700 + /* fallthru */ 701 + case IPC_RMID: 702 + return msgctl_down(ns, msqid, cmd, &msqid64); 703 + default: 704 + return -EINVAL; 705 + } 706 + } 707 + #endif 553 708 554 709 static int testmsg(struct msg_msg *msg, long type, int mode) 555 710 { ··· 730 627 return 0; 731 628 } 732 629 733 - long do_msgsnd(int msqid, long mtype, void __user *mtext, 630 + static long do_msgsnd(int msqid, long mtype, void __user *mtext, 734 631 size_t msgsz, int msgflg) 735 632 { 736 633 struct msg_queue *msq; ··· 853 750 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); 854 751 } 855 752 753 + #ifdef CONFIG_COMPAT 754 + 755 + struct compat_msgbuf { 756 + compat_long_t mtype; 757 + char mtext[1]; 758 + }; 759 + 760 + COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp, 761 + compat_ssize_t, msgsz, int, msgflg) 762 + { 763 + struct compat_msgbuf __user *up = compat_ptr(msgp); 764 + compat_long_t mtype; 765 + 766 + if (get_user(mtype, &up->mtype)) 767 + return -EFAULT; 768 + return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg); 769 + } 770 + #endif 771 + 856 772 static inline int convert_mode(long *msgtyp, int msgflg) 857 773 { 858 774 if (msgflg & MSG_COPY) ··· 968 846 return found ?: ERR_PTR(-EAGAIN); 969 847 } 970 848 971 - long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg, 849 + static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg, 972 850 long (*msg_handler)(void __user *, struct msg_msg *, size_t)) 973 851 { 974 852 int mode; ··· 1132 1010 return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); 1133 1011 } 1134 1012 1013 + #ifdef CONFIG_COMPAT 1014 + static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz) 1015 + { 1016 + struct compat_msgbuf __user *msgp = dest; 1017 + size_t msgsz; 1018 + 1019 + if (put_user(msg->m_type, &msgp->mtype)) 1020 + return -EFAULT; 1021 + 1022 + msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz; 1023 + if (store_msg(msgp->mtext, msg, msgsz)) 1024 + return -EFAULT; 1025 + return msgsz; 1026 + } 1027 + 1028 + COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp, 1029 + compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg) 1030 + { 1031 + return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp, 1032 + msgflg, compat_do_msg_fill); 1033 + } 1034 + #endif 1135 1035 1136 1036 int msg_init_ns(struct ipc_namespace *ns) 1137 1037 { ··· 1183 1039 struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); 1184 1040 1185 1041 seq_printf(s, 1186 - "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", 1042 + "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10llu %10llu %10llu\n", 1187 1043 msq->q_perm.key, 1188 1044 msq->q_perm.id, 1189 1045 msq->q_perm.mode,
+233 -121
ipc/sem.c
··· 512 512 INIT_LIST_HEAD(&sma->pending_const); 513 513 INIT_LIST_HEAD(&sma->list_id); 514 514 sma->sem_nsems = nsems; 515 - sma->sem_ctime = get_seconds(); 515 + sma->sem_ctime = ktime_get_real_seconds(); 516 516 517 517 retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni); 518 518 if (retval < 0) { ··· 1163 1163 } 1164 1164 } 1165 1165 1166 - static time_t get_semotime(struct sem_array *sma) 1166 + static time64_t get_semotime(struct sem_array *sma) 1167 1167 { 1168 1168 int i; 1169 - time_t res; 1169 + time64_t res; 1170 1170 1171 1171 res = sma->sems[0].sem_otime; 1172 1172 for (i = 1; i < sma->sem_nsems; i++) { 1173 - time_t to = sma->sems[i].sem_otime; 1173 + time64_t to = sma->sems[i].sem_otime; 1174 1174 1175 1175 if (to > res) 1176 1176 res = to; ··· 1178 1178 return res; 1179 1179 } 1180 1180 1181 - static int semctl_nolock(struct ipc_namespace *ns, int semid, 1182 - int cmd, int version, void __user *p) 1181 + static int semctl_stat(struct ipc_namespace *ns, int semid, 1182 + int cmd, struct semid64_ds *semid64) 1183 1183 { 1184 - int err; 1185 1184 struct sem_array *sma; 1185 + int id = 0; 1186 + int err; 1186 1187 1187 - switch (cmd) { 1188 - case IPC_INFO: 1189 - case SEM_INFO: 1190 - { 1191 - struct seminfo seminfo; 1192 - int max_id; 1188 + memset(semid64, 0, sizeof(*semid64)); 1193 1189 1194 - err = security_sem_semctl(NULL, cmd); 1195 - if (err) 1196 - return err; 1197 - 1198 - memset(&seminfo, 0, sizeof(seminfo)); 1199 - seminfo.semmni = ns->sc_semmni; 1200 - seminfo.semmns = ns->sc_semmns; 1201 - seminfo.semmsl = ns->sc_semmsl; 1202 - seminfo.semopm = ns->sc_semopm; 1203 - seminfo.semvmx = SEMVMX; 1204 - seminfo.semmnu = SEMMNU; 1205 - seminfo.semmap = SEMMAP; 1206 - seminfo.semume = SEMUME; 1207 - down_read(&sem_ids(ns).rwsem); 1208 - if (cmd == SEM_INFO) { 1209 - seminfo.semusz = sem_ids(ns).in_use; 1210 - seminfo.semaem = ns->used_sems; 1211 - } else { 1212 - seminfo.semusz = SEMUSZ; 1213 - seminfo.semaem = SEMAEM; 1214 - } 1215 - max_id = ipc_get_maxid(&sem_ids(ns)); 1216 - up_read(&sem_ids(ns).rwsem); 1217 - if (copy_to_user(p, &seminfo, sizeof(struct seminfo))) 1218 - return -EFAULT; 1219 - return (max_id < 0) ? 0 : max_id; 1220 - } 1221 - case IPC_STAT: 1222 - case SEM_STAT: 1223 - { 1224 - struct semid64_ds tbuf; 1225 - int id = 0; 1226 - 1227 - memset(&tbuf, 0, sizeof(tbuf)); 1228 - 1229 - rcu_read_lock(); 1230 - if (cmd == SEM_STAT) { 1231 - sma = sem_obtain_object(ns, semid); 1232 - if (IS_ERR(sma)) { 1233 - err = PTR_ERR(sma); 1234 - goto out_unlock; 1235 - } 1236 - id = sma->sem_perm.id; 1237 - } else { 1238 - sma = sem_obtain_object_check(ns, semid); 1239 - if (IS_ERR(sma)) { 1240 - err = PTR_ERR(sma); 1241 - goto out_unlock; 1242 - } 1243 - } 1244 - 1245 - err = -EACCES; 1246 - if (ipcperms(ns, &sma->sem_perm, S_IRUGO)) 1190 + rcu_read_lock(); 1191 + if (cmd == SEM_STAT) { 1192 + sma = sem_obtain_object(ns, semid); 1193 + if (IS_ERR(sma)) { 1194 + err = PTR_ERR(sma); 1247 1195 goto out_unlock; 1248 - 1249 - err = security_sem_semctl(sma, cmd); 1250 - if (err) 1196 + } 1197 + id = sma->sem_perm.id; 1198 + } else { 1199 + sma = sem_obtain_object_check(ns, semid); 1200 + if (IS_ERR(sma)) { 1201 + err = PTR_ERR(sma); 1251 1202 goto out_unlock; 1203 + } 1204 + } 1252 1205 1253 - kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); 1254 - tbuf.sem_otime = get_semotime(sma); 1255 - tbuf.sem_ctime = sma->sem_ctime; 1256 - tbuf.sem_nsems = sma->sem_nsems; 1257 - rcu_read_unlock(); 1258 - if (copy_semid_to_user(p, &tbuf, version)) 1259 - return -EFAULT; 1260 - return id; 1261 - } 1262 - default: 1263 - return -EINVAL; 1264 - } 1206 + err = -EACCES; 1207 + if (ipcperms(ns, &sma->sem_perm, S_IRUGO)) 1208 + goto out_unlock; 1209 + 1210 + err = security_sem_semctl(sma, cmd); 1211 + if (err) 1212 + goto out_unlock; 1213 + 1214 + kernel_to_ipc64_perm(&sma->sem_perm, &semid64->sem_perm); 1215 + semid64->sem_otime = get_semotime(sma); 1216 + semid64->sem_ctime = sma->sem_ctime; 1217 + semid64->sem_nsems = sma->sem_nsems; 1218 + rcu_read_unlock(); 1219 + return id; 1220 + 1265 1221 out_unlock: 1266 1222 rcu_read_unlock(); 1267 1223 return err; 1268 1224 } 1269 1225 1226 + static int semctl_info(struct ipc_namespace *ns, int semid, 1227 + int cmd, void __user *p) 1228 + { 1229 + struct seminfo seminfo; 1230 + int max_id; 1231 + int err; 1232 + 1233 + err = security_sem_semctl(NULL, cmd); 1234 + if (err) 1235 + return err; 1236 + 1237 + memset(&seminfo, 0, sizeof(seminfo)); 1238 + seminfo.semmni = ns->sc_semmni; 1239 + seminfo.semmns = ns->sc_semmns; 1240 + seminfo.semmsl = ns->sc_semmsl; 1241 + seminfo.semopm = ns->sc_semopm; 1242 + seminfo.semvmx = SEMVMX; 1243 + seminfo.semmnu = SEMMNU; 1244 + seminfo.semmap = SEMMAP; 1245 + seminfo.semume = SEMUME; 1246 + down_read(&sem_ids(ns).rwsem); 1247 + if (cmd == SEM_INFO) { 1248 + seminfo.semusz = sem_ids(ns).in_use; 1249 + seminfo.semaem = ns->used_sems; 1250 + } else { 1251 + seminfo.semusz = SEMUSZ; 1252 + seminfo.semaem = SEMAEM; 1253 + } 1254 + max_id = ipc_get_maxid(&sem_ids(ns)); 1255 + up_read(&sem_ids(ns).rwsem); 1256 + if (copy_to_user(p, &seminfo, sizeof(struct seminfo))) 1257 + return -EFAULT; 1258 + return (max_id < 0) ? 0 : max_id; 1259 + } 1260 + 1270 1261 static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum, 1271 - unsigned long arg) 1262 + int val) 1272 1263 { 1273 1264 struct sem_undo *un; 1274 1265 struct sem_array *sma; 1275 1266 struct sem *curr; 1276 - int err, val; 1267 + int err; 1277 1268 DEFINE_WAKE_Q(wake_q); 1278 - 1279 - #if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN) 1280 - /* big-endian 64bit */ 1281 - val = arg >> 32; 1282 - #else 1283 - /* 32bit or little-endian 64bit */ 1284 - val = arg; 1285 - #endif 1286 1269 1287 1270 if (val > SEMVMX || val < 0) 1288 1271 return -ERANGE; ··· 1310 1327 1311 1328 curr->semval = val; 1312 1329 curr->sempid = task_tgid_vnr(current); 1313 - sma->sem_ctime = get_seconds(); 1330 + sma->sem_ctime = ktime_get_real_seconds(); 1314 1331 /* maybe some queued-up processes were waiting for this */ 1315 1332 do_smart_update(sma, NULL, 0, 0, &wake_q); 1316 1333 sem_unlock(sma, -1); ··· 1438 1455 for (i = 0; i < nsems; i++) 1439 1456 un->semadj[i] = 0; 1440 1457 } 1441 - sma->sem_ctime = get_seconds(); 1458 + sma->sem_ctime = ktime_get_real_seconds(); 1442 1459 /* maybe some queued-up processes were waiting for this */ 1443 1460 do_smart_update(sma, NULL, 0, 0, &wake_q); 1444 1461 err = 0; ··· 1515 1532 * NOTE: no locks must be held, the rwsem is taken inside this function. 1516 1533 */ 1517 1534 static int semctl_down(struct ipc_namespace *ns, int semid, 1518 - int cmd, int version, void __user *p) 1535 + int cmd, struct semid64_ds *semid64) 1519 1536 { 1520 1537 struct sem_array *sma; 1521 1538 int err; 1522 - struct semid64_ds semid64; 1523 1539 struct kern_ipc_perm *ipcp; 1524 - 1525 - if (cmd == IPC_SET) { 1526 - if (copy_semid_from_user(&semid64, p, version)) 1527 - return -EFAULT; 1528 - } 1529 1540 1530 1541 down_write(&sem_ids(ns).rwsem); 1531 1542 rcu_read_lock(); 1532 1543 1533 1544 ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd, 1534 - &semid64.sem_perm, 0); 1545 + &semid64->sem_perm, 0); 1535 1546 if (IS_ERR(ipcp)) { 1536 1547 err = PTR_ERR(ipcp); 1537 1548 goto out_unlock1; ··· 1545 1568 goto out_up; 1546 1569 case IPC_SET: 1547 1570 sem_lock(sma, NULL, -1); 1548 - err = ipc_update_perm(&semid64.sem_perm, ipcp); 1571 + err = ipc_update_perm(&semid64->sem_perm, ipcp); 1549 1572 if (err) 1550 1573 goto out_unlock0; 1551 - sma->sem_ctime = get_seconds(); 1574 + sma->sem_ctime = ktime_get_real_seconds(); 1552 1575 break; 1553 1576 default: 1554 1577 err = -EINVAL; ··· 1569 1592 int version; 1570 1593 struct ipc_namespace *ns; 1571 1594 void __user *p = (void __user *)arg; 1595 + struct semid64_ds semid64; 1596 + int err; 1572 1597 1573 1598 if (semid < 0) 1574 1599 return -EINVAL; ··· 1581 1602 switch (cmd) { 1582 1603 case IPC_INFO: 1583 1604 case SEM_INFO: 1605 + return semctl_info(ns, semid, cmd, p); 1584 1606 case IPC_STAT: 1585 1607 case SEM_STAT: 1586 - return semctl_nolock(ns, semid, cmd, version, p); 1608 + err = semctl_stat(ns, semid, cmd, &semid64); 1609 + if (err < 0) 1610 + return err; 1611 + if (copy_semid_to_user(p, &semid64, version)) 1612 + err = -EFAULT; 1613 + return err; 1587 1614 case GETALL: 1588 1615 case GETVAL: 1589 1616 case GETPID: ··· 1597 1612 case GETZCNT: 1598 1613 case SETALL: 1599 1614 return semctl_main(ns, semid, semnum, cmd, p); 1600 - case SETVAL: 1601 - return semctl_setval(ns, semid, semnum, arg); 1602 - case IPC_RMID: 1615 + case SETVAL: { 1616 + int val; 1617 + #if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN) 1618 + /* big-endian 64bit */ 1619 + val = arg >> 32; 1620 + #else 1621 + /* 32bit or little-endian 64bit */ 1622 + val = arg; 1623 + #endif 1624 + return semctl_setval(ns, semid, semnum, val); 1625 + } 1603 1626 case IPC_SET: 1604 - return semctl_down(ns, semid, cmd, version, p); 1627 + if (copy_semid_from_user(&semid64, p, version)) 1628 + return -EFAULT; 1629 + case IPC_RMID: 1630 + return semctl_down(ns, semid, cmd, &semid64); 1605 1631 default: 1606 1632 return -EINVAL; 1607 1633 } 1608 1634 } 1635 + 1636 + #ifdef CONFIG_COMPAT 1637 + 1638 + struct compat_semid_ds { 1639 + struct compat_ipc_perm sem_perm; 1640 + compat_time_t sem_otime; 1641 + compat_time_t sem_ctime; 1642 + compat_uptr_t sem_base; 1643 + compat_uptr_t sem_pending; 1644 + compat_uptr_t sem_pending_last; 1645 + compat_uptr_t undo; 1646 + unsigned short sem_nsems; 1647 + }; 1648 + 1649 + static int copy_compat_semid_from_user(struct semid64_ds *out, void __user *buf, 1650 + int version) 1651 + { 1652 + memset(out, 0, sizeof(*out)); 1653 + if (version == IPC_64) { 1654 + struct compat_semid64_ds *p = buf; 1655 + return get_compat_ipc64_perm(&out->sem_perm, &p->sem_perm); 1656 + } else { 1657 + struct compat_semid_ds *p = buf; 1658 + return get_compat_ipc_perm(&out->sem_perm, &p->sem_perm); 1659 + } 1660 + } 1661 + 1662 + static int copy_compat_semid_to_user(void __user *buf, struct semid64_ds *in, 1663 + int version) 1664 + { 1665 + if (version == IPC_64) { 1666 + struct compat_semid64_ds v; 1667 + memset(&v, 0, sizeof(v)); 1668 + to_compat_ipc64_perm(&v.sem_perm, &in->sem_perm); 1669 + v.sem_otime = in->sem_otime; 1670 + v.sem_ctime = in->sem_ctime; 1671 + v.sem_nsems = in->sem_nsems; 1672 + return copy_to_user(buf, &v, sizeof(v)); 1673 + } else { 1674 + struct compat_semid_ds v; 1675 + memset(&v, 0, sizeof(v)); 1676 + to_compat_ipc_perm(&v.sem_perm, &in->sem_perm); 1677 + v.sem_otime = in->sem_otime; 1678 + v.sem_ctime = in->sem_ctime; 1679 + v.sem_nsems = in->sem_nsems; 1680 + return copy_to_user(buf, &v, sizeof(v)); 1681 + } 1682 + } 1683 + 1684 + COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg) 1685 + { 1686 + void __user *p = compat_ptr(arg); 1687 + struct ipc_namespace *ns; 1688 + struct semid64_ds semid64; 1689 + int version = compat_ipc_parse_version(&cmd); 1690 + int err; 1691 + 1692 + ns = current->nsproxy->ipc_ns; 1693 + 1694 + if (semid < 0) 1695 + return -EINVAL; 1696 + 1697 + switch (cmd & (~IPC_64)) { 1698 + case IPC_INFO: 1699 + case SEM_INFO: 1700 + return semctl_info(ns, semid, cmd, p); 1701 + case IPC_STAT: 1702 + case SEM_STAT: 1703 + err = semctl_stat(ns, semid, cmd, &semid64); 1704 + if (err < 0) 1705 + return err; 1706 + if (copy_compat_semid_to_user(p, &semid64, version)) 1707 + err = -EFAULT; 1708 + return err; 1709 + case GETVAL: 1710 + case GETPID: 1711 + case GETNCNT: 1712 + case GETZCNT: 1713 + case GETALL: 1714 + case SETALL: 1715 + return semctl_main(ns, semid, semnum, cmd, p); 1716 + case SETVAL: 1717 + return semctl_setval(ns, semid, semnum, arg); 1718 + case IPC_SET: 1719 + if (copy_compat_semid_from_user(&semid64, p, version)) 1720 + return -EFAULT; 1721 + /* fallthru */ 1722 + case IPC_RMID: 1723 + return semctl_down(ns, semid, cmd, &semid64); 1724 + default: 1725 + return -EINVAL; 1726 + } 1727 + } 1728 + #endif 1609 1729 1610 1730 /* If the task doesn't already have a undo_list, then allocate one 1611 1731 * here. We guarantee there is only one thread using this undo list, ··· 1856 1766 return un; 1857 1767 } 1858 1768 1859 - SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, 1860 - unsigned, nsops, const struct timespec __user *, timeout) 1769 + static long do_semtimedop(int semid, struct sembuf __user *tsops, 1770 + unsigned nsops, const struct timespec64 *timeout) 1861 1771 { 1862 1772 int error = -EINVAL; 1863 1773 struct sem_array *sma; ··· 1888 1798 } 1889 1799 1890 1800 if (timeout) { 1891 - struct timespec _timeout; 1892 - if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) { 1893 - error = -EFAULT; 1894 - goto out_free; 1895 - } 1896 - if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 || 1897 - _timeout.tv_nsec >= 1000000000L) { 1801 + if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 || 1802 + timeout->tv_nsec >= 1000000000L) { 1898 1803 error = -EINVAL; 1899 1804 goto out_free; 1900 1805 } 1901 - jiffies_left = timespec_to_jiffies(&_timeout); 1806 + jiffies_left = timespec64_to_jiffies(timeout); 1902 1807 } 1903 1808 1904 1809 max = 0; ··· 2108 2023 return error; 2109 2024 } 2110 2025 2026 + SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, 2027 + unsigned, nsops, const struct timespec __user *, timeout) 2028 + { 2029 + if (timeout) { 2030 + struct timespec64 ts; 2031 + if (get_timespec64(&ts, timeout)) 2032 + return -EFAULT; 2033 + return do_semtimedop(semid, tsops, nsops, &ts); 2034 + } 2035 + return do_semtimedop(semid, tsops, nsops, NULL); 2036 + } 2037 + 2038 + #ifdef CONFIG_COMPAT 2039 + COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems, 2040 + unsigned, nsops, 2041 + const struct compat_timespec __user *, timeout) 2042 + { 2043 + if (timeout) { 2044 + struct timespec64 ts; 2045 + if (compat_get_timespec64(&ts, timeout)) 2046 + return -EFAULT; 2047 + return do_semtimedop(semid, tsems, nsops, &ts); 2048 + } 2049 + return do_semtimedop(semid, tsems, nsops, NULL); 2050 + } 2051 + #endif 2052 + 2111 2053 SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops, 2112 2054 unsigned, nsops) 2113 2055 { 2114 - return sys_semtimedop(semid, tsops, nsops, NULL); 2056 + return do_semtimedop(semid, tsops, nsops, NULL); 2115 2057 } 2116 2058 2117 2059 /* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between ··· 2295 2183 struct user_namespace *user_ns = seq_user_ns(s); 2296 2184 struct kern_ipc_perm *ipcp = it; 2297 2185 struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm); 2298 - time_t sem_otime; 2186 + time64_t sem_otime; 2299 2187 2300 2188 /* 2301 2189 * The proc interface isn't aware of sem_lock(), it calls ··· 2308 2196 sem_otime = get_semotime(sma); 2309 2197 2310 2198 seq_printf(s, 2311 - "%10d %10d %4o %10u %5u %5u %5u %5u %10lu %10lu\n", 2199 + "%10d %10d %4o %10u %5u %5u %5u %5u %10llu %10llu\n", 2312 2200 sma->sem_perm.key, 2313 2201 sma->sem_perm.id, 2314 2202 sma->sem_perm.mode,
+377 -184
ipc/shm.c
··· 202 202 if (IS_ERR(shp)) 203 203 return PTR_ERR(shp); 204 204 205 - shp->shm_atim = get_seconds(); 205 + shp->shm_atim = ktime_get_real_seconds(); 206 206 shp->shm_lprid = task_tgid_vnr(current); 207 207 shp->shm_nattch++; 208 208 shm_unlock(shp); ··· 289 289 goto done; /* no-op */ 290 290 291 291 shp->shm_lprid = task_tgid_vnr(current); 292 - shp->shm_dtim = get_seconds(); 292 + shp->shm_dtim = ktime_get_real_seconds(); 293 293 shp->shm_nattch--; 294 294 if (shm_may_destroy(ns, shp)) 295 295 shm_destroy(ns, shp); ··· 594 594 shp->shm_cprid = task_tgid_vnr(current); 595 595 shp->shm_lprid = 0; 596 596 shp->shm_atim = shp->shm_dtim = 0; 597 - shp->shm_ctim = get_seconds(); 597 + shp->shm_ctim = ktime_get_real_seconds(); 598 598 shp->shm_segsz = size; 599 599 shp->shm_nattch = 0; 600 600 shp->shm_file = file; ··· 815 815 * NOTE: no locks must be held, the rwsem is taken inside this function. 816 816 */ 817 817 static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, 818 - struct shmid_ds __user *buf, int version) 818 + struct shmid64_ds *shmid64) 819 819 { 820 820 struct kern_ipc_perm *ipcp; 821 - struct shmid64_ds shmid64; 822 821 struct shmid_kernel *shp; 823 822 int err; 824 - 825 - if (cmd == IPC_SET) { 826 - if (copy_shmid_from_user(&shmid64, buf, version)) 827 - return -EFAULT; 828 - } 829 823 830 824 down_write(&shm_ids(ns).rwsem); 831 825 rcu_read_lock(); 832 826 833 827 ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd, 834 - &shmid64.shm_perm, 0); 828 + &shmid64->shm_perm, 0); 835 829 if (IS_ERR(ipcp)) { 836 830 err = PTR_ERR(ipcp); 837 831 goto out_unlock1; ··· 845 851 goto out_up; 846 852 case IPC_SET: 847 853 ipc_lock_object(&shp->shm_perm); 848 - err = ipc_update_perm(&shmid64.shm_perm, ipcp); 854 + err = ipc_update_perm(&shmid64->shm_perm, ipcp); 849 855 if (err) 850 856 goto out_unlock0; 851 - shp->shm_ctim = get_seconds(); 857 + shp->shm_ctim = ktime_get_real_seconds(); 852 858 break; 853 859 default: 854 860 err = -EINVAL; ··· 864 870 return err; 865 871 } 866 872 867 - static int shmctl_nolock(struct ipc_namespace *ns, int shmid, 868 - int cmd, int version, void __user *buf) 873 + static int shmctl_ipc_info(struct ipc_namespace *ns, 874 + struct shminfo64 *shminfo) 869 875 { 870 - int err; 871 - struct shmid_kernel *shp; 872 - 873 - /* preliminary security checks for *_INFO */ 874 - if (cmd == IPC_INFO || cmd == SHM_INFO) { 875 - err = security_shm_shmctl(NULL, cmd); 876 - if (err) 877 - return err; 878 - } 879 - 880 - switch (cmd) { 881 - case IPC_INFO: 882 - { 883 - struct shminfo64 shminfo; 884 - 885 - memset(&shminfo, 0, sizeof(shminfo)); 886 - shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; 887 - shminfo.shmmax = ns->shm_ctlmax; 888 - shminfo.shmall = ns->shm_ctlall; 889 - 890 - shminfo.shmmin = SHMMIN; 891 - if (copy_shminfo_to_user(buf, &shminfo, version)) 892 - return -EFAULT; 893 - 876 + int err = security_shm_shmctl(NULL, IPC_INFO); 877 + if (!err) { 878 + memset(shminfo, 0, sizeof(*shminfo)); 879 + shminfo->shmmni = shminfo->shmseg = ns->shm_ctlmni; 880 + shminfo->shmmax = ns->shm_ctlmax; 881 + shminfo->shmall = ns->shm_ctlall; 882 + shminfo->shmmin = SHMMIN; 894 883 down_read(&shm_ids(ns).rwsem); 895 884 err = ipc_get_maxid(&shm_ids(ns)); 896 885 up_read(&shm_ids(ns).rwsem); 897 - 898 886 if (err < 0) 899 887 err = 0; 900 - goto out; 901 888 } 902 - case SHM_INFO: 903 - { 904 - struct shm_info shm_info; 889 + return err; 890 + } 905 891 906 - memset(&shm_info, 0, sizeof(shm_info)); 892 + static int shmctl_shm_info(struct ipc_namespace *ns, 893 + struct shm_info *shm_info) 894 + { 895 + int err = security_shm_shmctl(NULL, SHM_INFO); 896 + if (!err) { 897 + memset(shm_info, 0, sizeof(*shm_info)); 907 898 down_read(&shm_ids(ns).rwsem); 908 - shm_info.used_ids = shm_ids(ns).in_use; 909 - shm_get_stat(ns, &shm_info.shm_rss, &shm_info.shm_swp); 910 - shm_info.shm_tot = ns->shm_tot; 911 - shm_info.swap_attempts = 0; 912 - shm_info.swap_successes = 0; 899 + shm_info->used_ids = shm_ids(ns).in_use; 900 + shm_get_stat(ns, &shm_info->shm_rss, &shm_info->shm_swp); 901 + shm_info->shm_tot = ns->shm_tot; 902 + shm_info->swap_attempts = 0; 903 + shm_info->swap_successes = 0; 913 904 err = ipc_get_maxid(&shm_ids(ns)); 914 905 up_read(&shm_ids(ns).rwsem); 915 - if (copy_to_user(buf, &shm_info, sizeof(shm_info))) { 916 - err = -EFAULT; 917 - goto out; 918 - } 919 - 920 - err = err < 0 ? 0 : err; 921 - goto out; 906 + if (err < 0) 907 + err = 0; 922 908 } 923 - case SHM_STAT: 924 - case IPC_STAT: 925 - { 926 - struct shmid64_ds tbuf; 927 - int result; 909 + return err; 910 + } 928 911 929 - rcu_read_lock(); 930 - if (cmd == SHM_STAT) { 931 - shp = shm_obtain_object(ns, shmid); 932 - if (IS_ERR(shp)) { 933 - err = PTR_ERR(shp); 934 - goto out_unlock; 935 - } 936 - result = shp->shm_perm.id; 937 - } else { 938 - shp = shm_obtain_object_check(ns, shmid); 939 - if (IS_ERR(shp)) { 940 - err = PTR_ERR(shp); 941 - goto out_unlock; 942 - } 943 - result = 0; 944 - } 912 + static int shmctl_stat(struct ipc_namespace *ns, int shmid, 913 + int cmd, struct shmid64_ds *tbuf) 914 + { 915 + struct shmid_kernel *shp; 916 + int result; 917 + int err; 945 918 946 - err = -EACCES; 947 - if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) 919 + rcu_read_lock(); 920 + if (cmd == SHM_STAT) { 921 + shp = shm_obtain_object(ns, shmid); 922 + if (IS_ERR(shp)) { 923 + err = PTR_ERR(shp); 948 924 goto out_unlock; 949 - 950 - err = security_shm_shmctl(shp, cmd); 951 - if (err) 925 + } 926 + result = shp->shm_perm.id; 927 + } else { 928 + shp = shm_obtain_object_check(ns, shmid); 929 + if (IS_ERR(shp)) { 930 + err = PTR_ERR(shp); 952 931 goto out_unlock; 953 - 954 - memset(&tbuf, 0, sizeof(tbuf)); 955 - kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); 956 - tbuf.shm_segsz = shp->shm_segsz; 957 - tbuf.shm_atime = shp->shm_atim; 958 - tbuf.shm_dtime = shp->shm_dtim; 959 - tbuf.shm_ctime = shp->shm_ctim; 960 - tbuf.shm_cpid = shp->shm_cprid; 961 - tbuf.shm_lpid = shp->shm_lprid; 962 - tbuf.shm_nattch = shp->shm_nattch; 963 - rcu_read_unlock(); 964 - 965 - if (copy_shmid_to_user(buf, &tbuf, version)) 966 - err = -EFAULT; 967 - else 968 - err = result; 969 - goto out; 932 + } 933 + result = 0; 970 934 } 971 - default: 972 - return -EINVAL; 973 - } 935 + 936 + err = -EACCES; 937 + if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) 938 + goto out_unlock; 939 + 940 + err = security_shm_shmctl(shp, cmd); 941 + if (err) 942 + goto out_unlock; 943 + 944 + memset(tbuf, 0, sizeof(*tbuf)); 945 + kernel_to_ipc64_perm(&shp->shm_perm, &tbuf->shm_perm); 946 + tbuf->shm_segsz = shp->shm_segsz; 947 + tbuf->shm_atime = shp->shm_atim; 948 + tbuf->shm_dtime = shp->shm_dtim; 949 + tbuf->shm_ctime = shp->shm_ctim; 950 + tbuf->shm_cpid = shp->shm_cprid; 951 + tbuf->shm_lpid = shp->shm_lprid; 952 + tbuf->shm_nattch = shp->shm_nattch; 953 + rcu_read_unlock(); 954 + return result; 974 955 975 956 out_unlock: 976 957 rcu_read_unlock(); 977 - out: 958 + return err; 959 + } 960 + 961 + static int shmctl_do_lock(struct ipc_namespace *ns, int shmid, int cmd) 962 + { 963 + struct shmid_kernel *shp; 964 + struct file *shm_file; 965 + int err; 966 + 967 + rcu_read_lock(); 968 + shp = shm_obtain_object_check(ns, shmid); 969 + if (IS_ERR(shp)) { 970 + err = PTR_ERR(shp); 971 + goto out_unlock1; 972 + } 973 + 974 + audit_ipc_obj(&(shp->shm_perm)); 975 + err = security_shm_shmctl(shp, cmd); 976 + if (err) 977 + goto out_unlock1; 978 + 979 + ipc_lock_object(&shp->shm_perm); 980 + 981 + /* check if shm_destroy() is tearing down shp */ 982 + if (!ipc_valid_object(&shp->shm_perm)) { 983 + err = -EIDRM; 984 + goto out_unlock0; 985 + } 986 + 987 + if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { 988 + kuid_t euid = current_euid(); 989 + 990 + if (!uid_eq(euid, shp->shm_perm.uid) && 991 + !uid_eq(euid, shp->shm_perm.cuid)) { 992 + err = -EPERM; 993 + goto out_unlock0; 994 + } 995 + if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) { 996 + err = -EPERM; 997 + goto out_unlock0; 998 + } 999 + } 1000 + 1001 + shm_file = shp->shm_file; 1002 + if (is_file_hugepages(shm_file)) 1003 + goto out_unlock0; 1004 + 1005 + if (cmd == SHM_LOCK) { 1006 + struct user_struct *user = current_user(); 1007 + 1008 + err = shmem_lock(shm_file, 1, user); 1009 + if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) { 1010 + shp->shm_perm.mode |= SHM_LOCKED; 1011 + shp->mlock_user = user; 1012 + } 1013 + goto out_unlock0; 1014 + } 1015 + 1016 + /* SHM_UNLOCK */ 1017 + if (!(shp->shm_perm.mode & SHM_LOCKED)) 1018 + goto out_unlock0; 1019 + shmem_lock(shm_file, 0, shp->mlock_user); 1020 + shp->shm_perm.mode &= ~SHM_LOCKED; 1021 + shp->mlock_user = NULL; 1022 + get_file(shm_file); 1023 + ipc_unlock_object(&shp->shm_perm); 1024 + rcu_read_unlock(); 1025 + shmem_unlock_mapping(shm_file->f_mapping); 1026 + 1027 + fput(shm_file); 1028 + return err; 1029 + 1030 + out_unlock0: 1031 + ipc_unlock_object(&shp->shm_perm); 1032 + out_unlock1: 1033 + rcu_read_unlock(); 978 1034 return err; 979 1035 } 980 1036 981 1037 SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) 982 1038 { 983 - struct shmid_kernel *shp; 984 1039 int err, version; 985 1040 struct ipc_namespace *ns; 1041 + struct shmid64_ds sem64; 986 1042 987 1043 if (cmd < 0 || shmid < 0) 988 1044 return -EINVAL; ··· 1041 997 ns = current->nsproxy->ipc_ns; 1042 998 1043 999 switch (cmd) { 1044 - case IPC_INFO: 1045 - case SHM_INFO: 1046 - case SHM_STAT: 1047 - case IPC_STAT: 1048 - return shmctl_nolock(ns, shmid, cmd, version, buf); 1049 - case IPC_RMID: 1050 - case IPC_SET: 1051 - return shmctl_down(ns, shmid, cmd, buf, version); 1052 - case SHM_LOCK: 1053 - case SHM_UNLOCK: 1054 - { 1055 - struct file *shm_file; 1056 - 1057 - rcu_read_lock(); 1058 - shp = shm_obtain_object_check(ns, shmid); 1059 - if (IS_ERR(shp)) { 1060 - err = PTR_ERR(shp); 1061 - goto out_unlock1; 1062 - } 1063 - 1064 - audit_ipc_obj(&(shp->shm_perm)); 1065 - err = security_shm_shmctl(shp, cmd); 1066 - if (err) 1067 - goto out_unlock1; 1068 - 1069 - ipc_lock_object(&shp->shm_perm); 1070 - 1071 - /* check if shm_destroy() is tearing down shp */ 1072 - if (!ipc_valid_object(&shp->shm_perm)) { 1073 - err = -EIDRM; 1074 - goto out_unlock0; 1075 - } 1076 - 1077 - if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { 1078 - kuid_t euid = current_euid(); 1079 - 1080 - if (!uid_eq(euid, shp->shm_perm.uid) && 1081 - !uid_eq(euid, shp->shm_perm.cuid)) { 1082 - err = -EPERM; 1083 - goto out_unlock0; 1084 - } 1085 - if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) { 1086 - err = -EPERM; 1087 - goto out_unlock0; 1088 - } 1089 - } 1090 - 1091 - shm_file = shp->shm_file; 1092 - if (is_file_hugepages(shm_file)) 1093 - goto out_unlock0; 1094 - 1095 - if (cmd == SHM_LOCK) { 1096 - struct user_struct *user = current_user(); 1097 - 1098 - err = shmem_lock(shm_file, 1, user); 1099 - if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) { 1100 - shp->shm_perm.mode |= SHM_LOCKED; 1101 - shp->mlock_user = user; 1102 - } 1103 - goto out_unlock0; 1104 - } 1105 - 1106 - /* SHM_UNLOCK */ 1107 - if (!(shp->shm_perm.mode & SHM_LOCKED)) 1108 - goto out_unlock0; 1109 - shmem_lock(shm_file, 0, shp->mlock_user); 1110 - shp->shm_perm.mode &= ~SHM_LOCKED; 1111 - shp->mlock_user = NULL; 1112 - get_file(shm_file); 1113 - ipc_unlock_object(&shp->shm_perm); 1114 - rcu_read_unlock(); 1115 - shmem_unlock_mapping(shm_file->f_mapping); 1116 - 1117 - fput(shm_file); 1000 + case IPC_INFO: { 1001 + struct shminfo64 shminfo; 1002 + err = shmctl_ipc_info(ns, &shminfo); 1003 + if (err < 0) 1004 + return err; 1005 + if (copy_shminfo_to_user(buf, &shminfo, version)) 1006 + err = -EFAULT; 1118 1007 return err; 1119 1008 } 1009 + case SHM_INFO: { 1010 + struct shm_info shm_info; 1011 + err = shmctl_shm_info(ns, &shm_info); 1012 + if (err < 0) 1013 + return err; 1014 + if (copy_to_user(buf, &shm_info, sizeof(shm_info))) 1015 + err = -EFAULT; 1016 + return err; 1017 + } 1018 + case SHM_STAT: 1019 + case IPC_STAT: { 1020 + err = shmctl_stat(ns, shmid, cmd, &sem64); 1021 + if (err < 0) 1022 + return err; 1023 + if (copy_shmid_to_user(buf, &sem64, version)) 1024 + err = -EFAULT; 1025 + return err; 1026 + } 1027 + case IPC_SET: 1028 + if (copy_shmid_from_user(&sem64, buf, version)) 1029 + return -EFAULT; 1030 + /* fallthru */ 1031 + case IPC_RMID: 1032 + return shmctl_down(ns, shmid, cmd, &sem64); 1033 + case SHM_LOCK: 1034 + case SHM_UNLOCK: 1035 + return shmctl_do_lock(ns, shmid, cmd); 1120 1036 default: 1121 1037 return -EINVAL; 1122 1038 } 1039 + } 1123 1040 1124 - out_unlock0: 1125 - ipc_unlock_object(&shp->shm_perm); 1126 - out_unlock1: 1127 - rcu_read_unlock(); 1041 + #ifdef CONFIG_COMPAT 1042 + 1043 + struct compat_shmid_ds { 1044 + struct compat_ipc_perm shm_perm; 1045 + int shm_segsz; 1046 + compat_time_t shm_atime; 1047 + compat_time_t shm_dtime; 1048 + compat_time_t shm_ctime; 1049 + compat_ipc_pid_t shm_cpid; 1050 + compat_ipc_pid_t shm_lpid; 1051 + unsigned short shm_nattch; 1052 + unsigned short shm_unused; 1053 + compat_uptr_t shm_unused2; 1054 + compat_uptr_t shm_unused3; 1055 + }; 1056 + 1057 + struct compat_shminfo64 { 1058 + compat_ulong_t shmmax; 1059 + compat_ulong_t shmmin; 1060 + compat_ulong_t shmmni; 1061 + compat_ulong_t shmseg; 1062 + compat_ulong_t shmall; 1063 + compat_ulong_t __unused1; 1064 + compat_ulong_t __unused2; 1065 + compat_ulong_t __unused3; 1066 + compat_ulong_t __unused4; 1067 + }; 1068 + 1069 + struct compat_shm_info { 1070 + compat_int_t used_ids; 1071 + compat_ulong_t shm_tot, shm_rss, shm_swp; 1072 + compat_ulong_t swap_attempts, swap_successes; 1073 + }; 1074 + 1075 + static int copy_compat_shminfo_to_user(void __user *buf, struct shminfo64 *in, 1076 + int version) 1077 + { 1078 + if (in->shmmax > INT_MAX) 1079 + in->shmmax = INT_MAX; 1080 + if (version == IPC_64) { 1081 + struct compat_shminfo64 info; 1082 + memset(&info, 0, sizeof(info)); 1083 + info.shmmax = in->shmmax; 1084 + info.shmmin = in->shmmin; 1085 + info.shmmni = in->shmmni; 1086 + info.shmseg = in->shmseg; 1087 + info.shmall = in->shmall; 1088 + return copy_to_user(buf, &info, sizeof(info)); 1089 + } else { 1090 + struct shminfo info; 1091 + memset(&info, 0, sizeof(info)); 1092 + info.shmmax = in->shmmax; 1093 + info.shmmin = in->shmmin; 1094 + info.shmmni = in->shmmni; 1095 + info.shmseg = in->shmseg; 1096 + info.shmall = in->shmall; 1097 + return copy_to_user(buf, &info, sizeof(info)); 1098 + } 1099 + } 1100 + 1101 + static int put_compat_shm_info(struct shm_info *ip, 1102 + struct compat_shm_info __user *uip) 1103 + { 1104 + struct compat_shm_info info; 1105 + 1106 + memset(&info, 0, sizeof(info)); 1107 + info.used_ids = ip->used_ids; 1108 + info.shm_tot = ip->shm_tot; 1109 + info.shm_rss = ip->shm_rss; 1110 + info.shm_swp = ip->shm_swp; 1111 + info.swap_attempts = ip->swap_attempts; 1112 + info.swap_successes = ip->swap_successes; 1113 + return copy_to_user(up, &info, sizeof(info)); 1114 + } 1115 + 1116 + static int copy_compat_shmid_to_user(void __user *buf, struct shmid64_ds *in, 1117 + int version) 1118 + { 1119 + if (version == IPC_64) { 1120 + struct compat_shmid64_ds v; 1121 + memset(&v, 0, sizeof(v)); 1122 + to_compat_ipc64_perm(&v.shm_perm, &in->shm_perm); 1123 + v.shm_atime = in->shm_atime; 1124 + v.shm_dtime = in->shm_dtime; 1125 + v.shm_ctime = in->shm_ctime; 1126 + v.shm_segsz = in->shm_segsz; 1127 + v.shm_nattch = in->shm_nattch; 1128 + v.shm_cpid = in->shm_cpid; 1129 + v.shm_lpid = in->shm_lpid; 1130 + return copy_to_user(buf, &v, sizeof(v)); 1131 + } else { 1132 + struct compat_shmid_ds v; 1133 + memset(&v, 0, sizeof(v)); 1134 + to_compat_ipc_perm(&v.shm_perm, &in->shm_perm); 1135 + v.shm_perm.key = in->shm_perm.key; 1136 + v.shm_atime = in->shm_atime; 1137 + v.shm_dtime = in->shm_dtime; 1138 + v.shm_ctime = in->shm_ctime; 1139 + v.shm_segsz = in->shm_segsz; 1140 + v.shm_nattch = in->shm_nattch; 1141 + v.shm_cpid = in->shm_cpid; 1142 + v.shm_lpid = in->shm_lpid; 1143 + return copy_to_user(buf, &v, sizeof(v)); 1144 + } 1145 + } 1146 + 1147 + static int copy_compat_shmid_from_user(struct shmid64_ds *out, void __user *buf, 1148 + int version) 1149 + { 1150 + memset(out, 0, sizeof(*out)); 1151 + if (version == IPC_64) { 1152 + struct compat_shmid64_ds *p = buf; 1153 + return get_compat_ipc64_perm(&out->shm_perm, &p->shm_perm); 1154 + } else { 1155 + struct compat_shmid_ds *p = buf; 1156 + return get_compat_ipc_perm(&out->shm_perm, &p->shm_perm); 1157 + } 1158 + } 1159 + 1160 + COMPAT_SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, void __user *, uptr) 1161 + { 1162 + struct ipc_namespace *ns; 1163 + struct shmid64_ds sem64; 1164 + int version = compat_ipc_parse_version(&cmd); 1165 + int err; 1166 + 1167 + ns = current->nsproxy->ipc_ns; 1168 + 1169 + if (cmd < 0 || shmid < 0) 1170 + return -EINVAL; 1171 + 1172 + switch (cmd) { 1173 + case IPC_INFO: { 1174 + struct shminfo64 shminfo; 1175 + err = shmctl_ipc_info(ns, &shminfo); 1176 + if (err < 0) 1177 + return err; 1178 + if (copy_compat_shminfo_to_user(uptr, &shminfo, version)) 1179 + err = -EFAULT; 1180 + return err; 1181 + } 1182 + case SHM_INFO: { 1183 + struct shm_info shm_info; 1184 + err = shmctl_shm_info(ns, &shm_info); 1185 + if (err < 0) 1186 + return err; 1187 + if (put_compat_shm_info(&shm_info, uptr)) 1188 + err = -EFAULT; 1189 + return err; 1190 + } 1191 + case IPC_STAT: 1192 + case SHM_STAT: 1193 + err = shmctl_stat(ns, shmid, cmd, &sem64); 1194 + if (err < 0) 1195 + return err; 1196 + if (copy_compat_shmid_to_user(&sem64, uptr, version)) 1197 + err = -EFAULT; 1198 + return err; 1199 + 1200 + case IPC_SET: 1201 + if (copy_compat_shmid_from_user(&sem64, uptr, version)) 1202 + return -EFAULT; 1203 + /* fallthru */ 1204 + case IPC_RMID: 1205 + return shmctl_down(ns, shmid, cmd, &sem64); 1206 + case SHM_LOCK: 1207 + case SHM_UNLOCK: 1208 + return shmctl_do_lock(ns, shmid, cmd); 1209 + break; 1210 + default: 1211 + return -EINVAL; 1212 + } 1128 1213 return err; 1129 1214 } 1215 + #endif 1130 1216 1131 1217 /* 1132 1218 * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists. ··· 1441 1267 return (long)ret; 1442 1268 } 1443 1269 1270 + #ifdef CONFIG_COMPAT 1271 + 1272 + #ifndef COMPAT_SHMLBA 1273 + #define COMPAT_SHMLBA SHMLBA 1274 + #endif 1275 + 1276 + COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg) 1277 + { 1278 + unsigned long ret; 1279 + long err; 1280 + 1281 + err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA); 1282 + if (err) 1283 + return err; 1284 + force_successful_syscall_return(); 1285 + return (long)ret; 1286 + } 1287 + #endif 1288 + 1444 1289 /* 1445 1290 * detach and kill segment if marked destroyed. 1446 1291 * The work is done in shm_close. ··· 1590 1397 1591 1398 seq_printf(s, 1592 1399 "%10d %10d %4o " SIZE_SPEC " %5u %5u " 1593 - "%5lu %5u %5u %5u %5u %10lu %10lu %10lu " 1400 + "%5lu %5u %5u %5u %5u %10llu %10llu %10llu " 1594 1401 SIZE_SPEC " " SIZE_SPEC "\n", 1595 1402 shp->shm_perm.key, 1596 1403 shp->shm_perm.id,
+89 -1
ipc/syscall.c
··· 5 5 * the individual syscalls instead. 6 6 */ 7 7 #include <linux/unistd.h> 8 + #include <linux/syscalls.h> 8 9 9 10 #ifdef __ARCH_WANT_SYS_IPC 10 11 #include <linux/errno.h> 11 12 #include <linux/ipc.h> 12 13 #include <linux/shm.h> 13 - #include <linux/syscalls.h> 14 14 #include <linux/uaccess.h> 15 15 16 16 SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, ··· 96 96 return -ENOSYS; 97 97 } 98 98 } 99 + #endif 100 + 101 + #ifdef CONFIG_COMPAT 102 + #include <linux/compat.h> 103 + 104 + #ifndef COMPAT_SHMLBA 105 + #define COMPAT_SHMLBA SHMLBA 106 + #endif 107 + 108 + struct compat_ipc_kludge { 109 + compat_uptr_t msgp; 110 + compat_long_t msgtyp; 111 + }; 112 + 113 + #ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC 114 + COMPAT_SYSCALL_DEFINE6(ipc, u32, call, int, first, int, second, 115 + u32, third, compat_uptr_t, ptr, u32, fifth) 116 + { 117 + int version; 118 + u32 pad; 119 + 120 + version = call >> 16; /* hack for backward compatibility */ 121 + call &= 0xffff; 122 + 123 + switch (call) { 124 + case SEMOP: 125 + /* struct sembuf is the same on 32 and 64bit :)) */ 126 + return sys_semtimedop(first, compat_ptr(ptr), second, NULL); 127 + case SEMTIMEDOP: 128 + return compat_sys_semtimedop(first, compat_ptr(ptr), second, 129 + compat_ptr(fifth)); 130 + case SEMGET: 131 + return sys_semget(first, second, third); 132 + case SEMCTL: 133 + if (!ptr) 134 + return -EINVAL; 135 + if (get_user(pad, (u32 __user *) compat_ptr(ptr))) 136 + return -EFAULT; 137 + return compat_sys_semctl(first, second, third, pad); 138 + 139 + case MSGSND: 140 + return compat_sys_msgsnd(first, ptr, second, third); 141 + 142 + case MSGRCV: { 143 + void __user *uptr = compat_ptr(ptr); 144 + 145 + if (first < 0 || second < 0) 146 + return -EINVAL; 147 + 148 + if (!version) { 149 + struct compat_ipc_kludge ipck; 150 + if (!uptr) 151 + return -EINVAL; 152 + if (copy_from_user(&ipck, uptr, sizeof(ipck))) 153 + return -EFAULT; 154 + return compat_sys_msgrcv(first, ipck.msgp, second, 155 + ipck.msgtyp, third); 156 + } 157 + return compat_sys_msgrcv(first, ptr, second, fifth, third); 158 + } 159 + case MSGGET: 160 + return sys_msgget(first, second); 161 + case MSGCTL: 162 + return compat_sys_msgctl(first, second, compat_ptr(ptr)); 163 + 164 + case SHMAT: { 165 + int err; 166 + unsigned long raddr; 167 + 168 + if (version == 1) 169 + return -EINVAL; 170 + err = do_shmat(first, compat_ptr(ptr), second, &raddr, 171 + COMPAT_SHMLBA); 172 + if (err < 0) 173 + return err; 174 + return put_user(raddr, (compat_ulong_t *)compat_ptr(third)); 175 + } 176 + case SHMDT: 177 + return sys_shmdt(compat_ptr(ptr)); 178 + case SHMGET: 179 + return sys_shmget(first, (unsigned)second, third); 180 + case SHMCTL: 181 + return compat_sys_shmctl(first, second, compat_ptr(ptr)); 182 + } 183 + 184 + return -ENOSYS; 185 + } 186 + #endif 99 187 #endif
+30
ipc/util.h
··· 194 194 const struct ipc_ops *ops, struct ipc_params *params); 195 195 void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, 196 196 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)); 197 + 198 + #ifdef CONFIG_COMPAT 199 + #include <linux/compat.h> 200 + struct compat_ipc_perm { 201 + key_t key; 202 + __compat_uid_t uid; 203 + __compat_gid_t gid; 204 + __compat_uid_t cuid; 205 + __compat_gid_t cgid; 206 + compat_mode_t mode; 207 + unsigned short seq; 208 + }; 209 + 210 + void to_compat_ipc_perm(struct compat_ipc_perm *, struct ipc64_perm *); 211 + void to_compat_ipc64_perm(struct compat_ipc64_perm *, struct ipc64_perm *); 212 + int get_compat_ipc_perm(struct ipc64_perm *, struct compat_ipc_perm __user *); 213 + int get_compat_ipc64_perm(struct ipc64_perm *, 214 + struct compat_ipc64_perm __user *); 215 + 216 + static inline int compat_ipc_parse_version(int *cmd) 217 + { 218 + #ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION 219 + int version = *cmd & IPC_64; 220 + *cmd &= ~IPC_64; 221 + return version; 222 + #else 223 + return IPC_64; 224 + #endif 225 + } 226 + #endif 197 227 #endif
+1 -1
kernel/audit.h
··· 182 182 mqd_t mqdes; 183 183 size_t msg_len; 184 184 unsigned int msg_prio; 185 - struct timespec abs_timeout; 185 + struct timespec64 abs_timeout; 186 186 } mq_sendrecv; 187 187 struct { 188 188 int oflag;
+6 -6
kernel/auditsc.c
··· 1235 1235 case AUDIT_MQ_SENDRECV: 1236 1236 audit_log_format(ab, 1237 1237 "mqdes=%d msg_len=%zd msg_prio=%u " 1238 - "abs_timeout_sec=%ld abs_timeout_nsec=%ld", 1238 + "abs_timeout_sec=%lld abs_timeout_nsec=%ld", 1239 1239 context->mq_sendrecv.mqdes, 1240 1240 context->mq_sendrecv.msg_len, 1241 1241 context->mq_sendrecv.msg_prio, 1242 - context->mq_sendrecv.abs_timeout.tv_sec, 1242 + (long long) context->mq_sendrecv.abs_timeout.tv_sec, 1243 1243 context->mq_sendrecv.abs_timeout.tv_nsec); 1244 1244 break; 1245 1245 case AUDIT_MQ_NOTIFY: ··· 2083 2083 * 2084 2084 */ 2085 2085 void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, 2086 - const struct timespec *abs_timeout) 2086 + const struct timespec64 *abs_timeout) 2087 2087 { 2088 2088 struct audit_context *context = current->audit_context; 2089 - struct timespec *p = &context->mq_sendrecv.abs_timeout; 2089 + struct timespec64 *p = &context->mq_sendrecv.abs_timeout; 2090 2090 2091 2091 if (abs_timeout) 2092 - memcpy(p, abs_timeout, sizeof(struct timespec)); 2092 + memcpy(p, abs_timeout, sizeof(*p)); 2093 2093 else 2094 - memset(p, 0, sizeof(struct timespec)); 2094 + memset(p, 0, sizeof(*p)); 2095 2095 2096 2096 context->mq_sendrecv.mqdes = mqdes; 2097 2097 context->mq_sendrecv.msg_len = msg_len;
-23
kernel/compat.c
··· 200 200 } 201 201 EXPORT_SYMBOL_GPL(compat_put_timespec); 202 202 203 - int compat_convert_timespec(struct timespec __user **kts, 204 - const void __user *cts) 205 - { 206 - struct timespec ts; 207 - struct timespec __user *uts; 208 - 209 - if (!cts || COMPAT_USE_64BIT_TIME) { 210 - *kts = (struct timespec __user *)cts; 211 - return 0; 212 - } 213 - 214 - uts = compat_alloc_user_space(sizeof(ts)); 215 - if (!uts) 216 - return -EFAULT; 217 - if (compat_get_timespec(&ts, cts)) 218 - return -EFAULT; 219 - if (copy_to_user(uts, &ts, sizeof(ts))) 220 - return -EFAULT; 221 - 222 - *kts = uts; 223 - return 0; 224 - } 225 - 226 203 int get_compat_itimerval(struct itimerval *o, const struct compat_itimerval __user *i) 227 204 { 228 205 struct compat_itimerval v32;