aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-09-14 20:37:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-14 20:37:26 -0400
commitcc73fee0bae2d66594d1fa2df92bbd783aa98e04 (patch)
treed1e7fe7f76cae4cbc941fc3bb43a46d237a9df77 /ipc
parente7cdb60fd28b252f1c15a0e50f79a01906124915 (diff)
parentaaed2dd8a31359e5767ee099ecbb078d55be4d29 (diff)
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
Diffstat (limited to 'ipc')
-rw-r--r--ipc/compat.c740
-rw-r--r--ipc/mqueue.c28
-rw-r--r--ipc/msg.c366
-rw-r--r--ipc/sem.c344
-rw-r--r--ipc/shm.c533
-rw-r--r--ipc/syscall.c90
-rw-r--r--ipc/util.h30
7 files changed, 1011 insertions, 1120 deletions
diff --git a/ipc/compat.c b/ipc/compat.c
index 9b3c85f8a538..b17bf93d7b49 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -34,724 +34,48 @@
34 34
35#include "util.h" 35#include "util.h"
36 36
37struct compat_msgbuf { 37int get_compat_ipc64_perm(struct ipc64_perm *to,
38 compat_long_t mtype; 38 struct compat_ipc64_perm __user *from)
39 char mtext[1];
40};
41
42struct 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
52struct 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
63struct 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
79struct 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
93struct compat_ipc_kludge {
94 compat_uptr_t msgp;
95 compat_long_t msgtyp;
96};
97
98struct 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
110struct 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
116static inline int compat_ipc_parse_version(int *cmd)
117{
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
136static 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
147static 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
158static inline int __put_compat_ipc64_perm(struct ipc64_perm *p64,
159 struct compat_ipc64_perm __user *up64)
160{ 39{
161 int err; 40 struct compat_ipc64_perm v;
162 41 if (copy_from_user(&v, from, sizeof(v)))
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
173static 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
194static 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)))
198 return -EFAULT;
199 return __get_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm);
200}
201
202static inline int get_compat_semid_ds(struct semid64_ds *s,
203 struct compat_semid_ds __user *up)
204{
205 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
206 return -EFAULT; 42 return -EFAULT;
207 return __get_compat_ipc_perm(&s->sem_perm, &up->sem_perm); 43 to->uid = v.uid;
44 to->gid = v.gid;
45 to->mode = v.mode;
46 return 0;
208} 47}
209 48
210static inline int put_compat_semid64_ds(struct semid64_ds *sem64, 49int get_compat_ipc_perm(struct ipc64_perm *to,
211 struct compat_semid64_ds __user *up64) 50 struct compat_ipc_perm __user *from)
212{ 51{
213 int err; 52 struct compat_ipc_perm v;
214 53 if (copy_from_user(&v, from, sizeof(v)))
215 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
216 return -EFAULT; 54 return -EFAULT;
217 err = __put_compat_ipc64_perm(&sem64->sem_perm, &up64->sem_perm); 55 to->uid = v.uid;
218 err |= __put_user(sem64->sem_otime, &up64->sem_otime); 56 to->gid = v.gid;
219 err |= __put_user(sem64->sem_ctime, &up64->sem_ctime); 57 to->mode = v.mode;
220 err |= __put_user(sem64->sem_nsems, &up64->sem_nsems); 58 return 0;
221 return err;
222} 59}
223 60
224static inline int put_compat_semid_ds(struct semid64_ds *s, 61void to_compat_ipc64_perm(struct compat_ipc64_perm *to, struct ipc64_perm *from)
225 struct compat_semid_ds __user *up)
226{ 62{
227 int err; 63 to->key = from->key;
228 64 to->uid = from->uid;
229 if (!access_ok(VERIFY_WRITE, up, sizeof(*up))) 65 to->gid = from->gid;
230 return -EFAULT; 66 to->cuid = from->cuid;
231 err = __put_compat_ipc_perm(&s->sem_perm, &up->sem_perm); 67 to->cgid = from->cgid;
232 err |= __put_user(s->sem_otime, &up->sem_otime); 68 to->mode = from->mode;
233 err |= __put_user(s->sem_ctime, &up->sem_ctime); 69 to->seq = from->seq;
234 err |= __put_user(s->sem_nsems, &up->sem_nsems);
235 return err;
236} 70}
237 71
238static long do_compat_semctl(int first, int second, int third, u32 pad) 72void to_compat_ipc_perm(struct compat_ipc_perm *to, struct ipc64_perm *from)
239{ 73{
240 unsigned long fourth; 74 to->key = from->key;
241 int err, err2; 75 SET_UID(to->uid, from->uid);
242 struct semid64_ds sem64; 76 SET_GID(to->gid, from->gid);
243 struct semid64_ds __user *up64; 77 SET_UID(to->cuid, from->cuid);
244 int version = compat_ipc_parse_version(&third); 78 SET_GID(to->cgid, from->cgid);
245 79 to->mode = from->mode;
246 memset(&sem64, 0, sizeof(sem64)); 80 to->seq = from->seq;
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
310static 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
329COMPAT_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
413COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
414{
415 return do_compat_semctl(semid, semnum, cmd, arg);
416}
417
418COMPAT_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
429COMPAT_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
436static 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
448static 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
460static 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
479static 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
498COMPAT_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
552COMPAT_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
564static 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
572static 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
580static 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
598static 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
616static 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
633static 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
650static 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
668COMPAT_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
749COMPAT_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);
757} 81}
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index eb1391b52c6f..d24025626310 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -668,11 +668,11 @@ static void __do_notify(struct mqueue_inode_info *info)
668} 668}
669 669
670static int prepare_timeout(const struct timespec __user *u_abs_timeout, 670static 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 return -EFAULT; 674 return -EFAULT;
675 if (!timespec_valid(ts)) 675 if (!timespec64_valid(ts))
676 return -EINVAL; 676 return -EINVAL;
677 return 0; 677 return 0;
678} 678}
@@ -962,7 +962,7 @@ static inline void pipelined_receive(struct wake_q_head *wake_q,
962 962
963static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, 963static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
964 size_t msg_len, unsigned int msg_prio, 964 size_t msg_len, unsigned int msg_prio,
965 struct timespec *ts) 965 struct timespec64 *ts)
966{ 966{
967 struct fd f; 967 struct fd f;
968 struct inode *inode; 968 struct inode *inode;
@@ -979,7 +979,7 @@ static int do_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
979 return -EINVAL; 979 return -EINVAL;
980 980
981 if (ts) { 981 if (ts) {
982 expires = timespec_to_ktime(*ts); 982 expires = timespec64_to_ktime(*ts);
983 timeout = &expires; 983 timeout = &expires;
984 } 984 }
985 985
@@ -1080,7 +1080,7 @@ out:
1080 1080
1081static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, 1081static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
1082 size_t msg_len, unsigned int __user *u_msg_prio, 1082 size_t msg_len, unsigned int __user *u_msg_prio,
1083 struct timespec *ts) 1083 struct timespec64 *ts)
1084{ 1084{
1085 ssize_t ret; 1085 ssize_t ret;
1086 struct msg_msg *msg_ptr; 1086 struct msg_msg *msg_ptr;
@@ -1092,7 +1092,7 @@ static int do_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
1092 struct posix_msg_tree_node *new_leaf = NULL; 1092 struct posix_msg_tree_node *new_leaf = NULL;
1093 1093
1094 if (ts) { 1094 if (ts) {
1095 expires = timespec_to_ktime(*ts); 1095 expires = timespec64_to_ktime(*ts);
1096 timeout = &expires; 1096 timeout = &expires;
1097 } 1097 }
1098 1098
@@ -1184,7 +1184,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
1184 size_t, msg_len, unsigned int, msg_prio, 1184 size_t, msg_len, unsigned int, msg_prio,
1185 const struct timespec __user *, u_abs_timeout) 1185 const struct timespec __user *, u_abs_timeout)
1186{ 1186{
1187 struct timespec ts, *p = NULL; 1187 struct timespec64 ts, *p = NULL;
1188 if (u_abs_timeout) { 1188 if (u_abs_timeout) {
1189 int res = prepare_timeout(u_abs_timeout, &ts); 1189 int res = prepare_timeout(u_abs_timeout, &ts);
1190 if (res) 1190 if (res)
@@ -1198,7 +1198,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
1198 size_t, msg_len, unsigned int __user *, u_msg_prio, 1198 size_t, msg_len, unsigned int __user *, u_msg_prio,
1199 const struct timespec __user *, u_abs_timeout) 1199 const struct timespec __user *, u_abs_timeout)
1200{ 1200{
1201 struct timespec ts, *p = NULL; 1201 struct timespec64 ts, *p = NULL;
1202 if (u_abs_timeout) { 1202 if (u_abs_timeout) {
1203 int res = prepare_timeout(u_abs_timeout, &ts); 1203 int res = prepare_timeout(u_abs_timeout, &ts);
1204 if (res) 1204 if (res)
@@ -1475,11 +1475,11 @@ COMPAT_SYSCALL_DEFINE4(mq_open, const char __user *, u_name,
1475} 1475}
1476 1476
1477static int compat_prepare_timeout(const struct compat_timespec __user *p, 1477static 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 return -EFAULT; 1481 return -EFAULT;
1482 if (!timespec_valid(ts)) 1482 if (!timespec64_valid(ts))
1483 return -EINVAL; 1483 return -EINVAL;
1484 return 0; 1484 return 0;
1485} 1485}
@@ -1489,7 +1489,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes,
1489 compat_size_t, msg_len, unsigned int, msg_prio, 1489 compat_size_t, msg_len, unsigned int, msg_prio,
1490 const struct compat_timespec __user *, u_abs_timeout) 1490 const struct compat_timespec __user *, u_abs_timeout)
1491{ 1491{
1492 struct timespec ts, *p = NULL; 1492 struct timespec64 ts, *p = NULL;
1493 if (u_abs_timeout) { 1493 if (u_abs_timeout) {
1494 int res = compat_prepare_timeout(u_abs_timeout, &ts); 1494 int res = compat_prepare_timeout(u_abs_timeout, &ts);
1495 if (res) 1495 if (res)
@@ -1504,7 +1504,7 @@ COMPAT_SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes,
1504 compat_size_t, msg_len, unsigned int __user *, u_msg_prio, 1504 compat_size_t, msg_len, unsigned int __user *, u_msg_prio,
1505 const struct compat_timespec __user *, u_abs_timeout) 1505 const struct compat_timespec __user *, u_abs_timeout)
1506{ 1506{
1507 struct timespec ts, *p = NULL; 1507 struct timespec64 ts, *p = NULL;
1508 if (u_abs_timeout) { 1508 if (u_abs_timeout) {
1509 int res = compat_prepare_timeout(u_abs_timeout, &ts); 1509 int res = compat_prepare_timeout(u_abs_timeout, &ts);
1510 if (res) 1510 if (res)
diff --git a/ipc/msg.c b/ipc/msg.c
index df82bc9a5531..06be5a9adfa4 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -133,7 +133,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
133 } 133 }
134 134
135 msq->q_stime = msq->q_rtime = 0; 135 msq->q_stime = msq->q_rtime = 0;
136 msq->q_ctime = get_seconds(); 136 msq->q_ctime = ktime_get_real_seconds();
137 msq->q_cbytes = msq->q_qnum = 0; 137 msq->q_cbytes = msq->q_qnum = 0;
138 msq->q_qbytes = ns->msg_ctlmnb; 138 msq->q_qbytes = ns->msg_ctlmnb;
139 msq->q_lspid = msq->q_lrpid = 0; 139 msq->q_lspid = msq->q_lrpid = 0;
@@ -361,23 +361,17 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
361 * NOTE: no locks must be held, the rwsem is taken inside this function. 361 * NOTE: no locks must be held, the rwsem is taken inside this function.
362 */ 362 */
363static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd, 363static 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 struct kern_ipc_perm *ipcp; 366 struct kern_ipc_perm *ipcp;
367 struct msqid64_ds uninitialized_var(msqid64);
368 struct msg_queue *msq; 367 struct msg_queue *msq;
369 int err; 368 int err;
370 369
371 if (cmd == IPC_SET) {
372 if (copy_msqid_from_user(&msqid64, buf, version))
373 return -EFAULT;
374 }
375
376 down_write(&msg_ids(ns).rwsem); 370 down_write(&msg_ids(ns).rwsem);
377 rcu_read_lock(); 371 rcu_read_lock();
378 372
379 ipcp = ipcctl_pre_down_nolock(ns, &msg_ids(ns), msqid, cmd, 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 if (IS_ERR(ipcp)) { 375 if (IS_ERR(ipcp)) {
382 err = PTR_ERR(ipcp); 376 err = PTR_ERR(ipcp);
383 goto out_unlock1; 377 goto out_unlock1;
@@ -399,20 +393,20 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
399 { 393 {
400 DEFINE_WAKE_Q(wake_q); 394 DEFINE_WAKE_Q(wake_q);
401 395
402 if (msqid64.msg_qbytes > ns->msg_ctlmnb && 396 if (msqid64->msg_qbytes > ns->msg_ctlmnb &&
403 !capable(CAP_SYS_RESOURCE)) { 397 !capable(CAP_SYS_RESOURCE)) {
404 err = -EPERM; 398 err = -EPERM;
405 goto out_unlock1; 399 goto out_unlock1;
406 } 400 }
407 401
408 ipc_lock_object(&msq->q_perm); 402 ipc_lock_object(&msq->q_perm);
409 err = ipc_update_perm(&msqid64.msg_perm, ipcp); 403 err = ipc_update_perm(&msqid64->msg_perm, ipcp);
410 if (err) 404 if (err)
411 goto out_unlock0; 405 goto out_unlock0;
412 406
413 msq->q_qbytes = msqid64.msg_qbytes; 407 msq->q_qbytes = msqid64->msg_qbytes;
414 408
415 msq->q_ctime = get_seconds(); 409 msq->q_ctime = ktime_get_real_seconds();
416 /* 410 /*
417 * Sleeping receivers might be excluded by 411 * Sleeping receivers might be excluded by
418 * stricter permissions. 412 * stricter permissions.
@@ -442,111 +436,89 @@ out_up:
442 return err; 436 return err;
443} 437}
444 438
445static int msgctl_nolock(struct ipc_namespace *ns, int msqid, 439static int msgctl_info(struct ipc_namespace *ns, int msqid,
446 int cmd, int version, void __user *buf) 440 int cmd, struct msginfo *msginfo)
447{ 441{
448 int err; 442 int err;
449 struct msg_queue *msq; 443 int max_id;
450
451 switch (cmd) {
452 case IPC_INFO:
453 case MSG_INFO:
454 {
455 struct msginfo msginfo;
456 int max_id;
457
458 if (!buf)
459 return -EFAULT;
460
461 /*
462 * We must not return kernel stack data.
463 * due to padding, it's not enough
464 * to set all member fields.
465 */
466 err = security_msg_queue_msgctl(NULL, cmd);
467 if (err)
468 return err;
469 444
470 memset(&msginfo, 0, sizeof(msginfo)); 445 /*
471 msginfo.msgmni = ns->msg_ctlmni; 446 * We must not return kernel stack data.
472 msginfo.msgmax = ns->msg_ctlmax; 447 * due to padding, it's not enough
473 msginfo.msgmnb = ns->msg_ctlmnb; 448 * to set all member fields.
474 msginfo.msgssz = MSGSSZ; 449 */
475 msginfo.msgseg = MSGSEG; 450 err = security_msg_queue_msgctl(NULL, cmd);
476 down_read(&msg_ids(ns).rwsem); 451 if (err)
477 if (cmd == MSG_INFO) { 452 return err;
478 msginfo.msgpool = msg_ids(ns).in_use; 453
479 msginfo.msgmap = atomic_read(&ns->msg_hdrs); 454 memset(msginfo, 0, sizeof(*msginfo));
480 msginfo.msgtql = atomic_read(&ns->msg_bytes); 455 msginfo->msgmni = ns->msg_ctlmni;
481 } else { 456 msginfo->msgmax = ns->msg_ctlmax;
482 msginfo.msgmap = MSGMAP; 457 msginfo->msgmnb = ns->msg_ctlmnb;
483 msginfo.msgpool = MSGPOOL; 458 msginfo->msgssz = MSGSSZ;
484 msginfo.msgtql = MSGTQL; 459 msginfo->msgseg = MSGSEG;
485 } 460 down_read(&msg_ids(ns).rwsem);
486 max_id = ipc_get_maxid(&msg_ids(ns)); 461 if (cmd == MSG_INFO) {
487 up_read(&msg_ids(ns).rwsem); 462 msginfo->msgpool = msg_ids(ns).in_use;
488 if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) 463 msginfo->msgmap = atomic_read(&ns->msg_hdrs);
489 return -EFAULT; 464 msginfo->msgtql = atomic_read(&ns->msg_bytes);
490 return (max_id < 0) ? 0 : max_id; 465 } else {
466 msginfo->msgmap = MSGMAP;
467 msginfo->msgpool = MSGPOOL;
468 msginfo->msgtql = MSGTQL;
491 } 469 }
470 max_id = ipc_get_maxid(&msg_ids(ns));
471 up_read(&msg_ids(ns).rwsem);
472 return (max_id < 0) ? 0 : max_id;
473}
492 474
493 case MSG_STAT: 475static int msgctl_stat(struct ipc_namespace *ns, int msqid,
494 case IPC_STAT: 476 int cmd, struct msqid64_ds *p)
495 { 477{
496 struct msqid64_ds tbuf; 478 int err;
497 int success_return; 479 struct msg_queue *msq;
498 480 int success_return;
499 if (!buf)
500 return -EFAULT;
501
502 memset(&tbuf, 0, sizeof(tbuf));
503 481
504 rcu_read_lock(); 482 memset(p, 0, sizeof(*p));
505 if (cmd == MSG_STAT) {
506 msq = msq_obtain_object(ns, msqid);
507 if (IS_ERR(msq)) {
508 err = PTR_ERR(msq);
509 goto out_unlock;
510 }
511 success_return = msq->q_perm.id;
512 } else {
513 msq = msq_obtain_object_check(ns, msqid);
514 if (IS_ERR(msq)) {
515 err = PTR_ERR(msq);
516 goto out_unlock;
517 }
518 success_return = 0;
519 }
520 483
521 err = -EACCES; 484 rcu_read_lock();
522 if (ipcperms(ns, &msq->q_perm, S_IRUGO)) 485 if (cmd == MSG_STAT) {
486 msq = msq_obtain_object(ns, msqid);
487 if (IS_ERR(msq)) {
488 err = PTR_ERR(msq);
523 goto out_unlock; 489 goto out_unlock;
524 490 }
525 err = security_msg_queue_msgctl(msq, cmd); 491 success_return = msq->q_perm.id;
526 if (err) 492 } else {
493 msq = msq_obtain_object_check(ns, msqid);
494 if (IS_ERR(msq)) {
495 err = PTR_ERR(msq);
527 goto out_unlock; 496 goto out_unlock;
497 }
498 success_return = 0;
499 }
528 500
529 kernel_to_ipc64_perm(&msq->q_perm, &tbuf.msg_perm); 501 err = -EACCES;
530 tbuf.msg_stime = msq->q_stime; 502 if (ipcperms(ns, &msq->q_perm, S_IRUGO))
531 tbuf.msg_rtime = msq->q_rtime; 503 goto out_unlock;
532 tbuf.msg_ctime = msq->q_ctime;
533 tbuf.msg_cbytes = msq->q_cbytes;
534 tbuf.msg_qnum = msq->q_qnum;
535 tbuf.msg_qbytes = msq->q_qbytes;
536 tbuf.msg_lspid = msq->q_lspid;
537 tbuf.msg_lrpid = msq->q_lrpid;
538 rcu_read_unlock();
539 504
540 if (copy_msqid_to_user(buf, &tbuf, version)) 505 err = security_msg_queue_msgctl(msq, cmd);
541 return -EFAULT; 506 if (err)
542 return success_return; 507 goto out_unlock;
543 } 508
509 kernel_to_ipc64_perm(&msq->q_perm, &p->msg_perm);
510 p->msg_stime = msq->q_stime;
511 p->msg_rtime = msq->q_rtime;
512 p->msg_ctime = msq->q_ctime;
513 p->msg_cbytes = msq->q_cbytes;
514 p->msg_qnum = msq->q_qnum;
515 p->msg_qbytes = msq->q_qbytes;
516 p->msg_lspid = msq->q_lspid;
517 p->msg_lrpid = msq->q_lrpid;
518 rcu_read_unlock();
544 519
545 default: 520 return success_return;
546 return -EINVAL;
547 }
548 521
549 return err;
550out_unlock: 522out_unlock:
551 rcu_read_unlock(); 523 rcu_read_unlock();
552 return err; 524 return err;
@@ -556,6 +528,8 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
556{ 528{
557 int version; 529 int version;
558 struct ipc_namespace *ns; 530 struct ipc_namespace *ns;
531 struct msqid64_ds msqid64;
532 int err;
559 533
560 if (msqid < 0 || cmd < 0) 534 if (msqid < 0 || cmd < 0)
561 return -EINVAL; 535 return -EINVAL;
@@ -565,18 +539,147 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
565 539
566 switch (cmd) { 540 switch (cmd) {
567 case IPC_INFO: 541 case IPC_INFO:
568 case MSG_INFO: 542 case MSG_INFO: {
543 struct msginfo msginfo;
544 err = msgctl_info(ns, msqid, cmd, &msginfo);
545 if (err < 0)
546 return err;
547 if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
548 err = -EFAULT;
549 return err;
550 }
569 case MSG_STAT: /* msqid is an index rather than a msg queue id */ 551 case MSG_STAT: /* msqid is an index rather than a msg queue id */
570 case IPC_STAT: 552 case IPC_STAT:
571 return msgctl_nolock(ns, msqid, cmd, version, buf); 553 err = msgctl_stat(ns, msqid, cmd, &msqid64);
554 if (err < 0)
555 return err;
556 if (copy_msqid_to_user(buf, &msqid64, version))
557 err = -EFAULT;
558 return err;
572 case IPC_SET: 559 case IPC_SET:
560 if (copy_msqid_from_user(&msqid64, buf, version))
561 return -EFAULT;
562 /* fallthru */
573 case IPC_RMID: 563 case IPC_RMID:
574 return msgctl_down(ns, msqid, cmd, buf, version); 564 return msgctl_down(ns, msqid, cmd, &msqid64);
575 default: 565 default:
576 return -EINVAL; 566 return -EINVAL;
577 } 567 }
578} 568}
579 569
570#ifdef CONFIG_COMPAT
571
572struct compat_msqid_ds {
573 struct compat_ipc_perm msg_perm;
574 compat_uptr_t msg_first;
575 compat_uptr_t msg_last;
576 compat_time_t msg_stime;
577 compat_time_t msg_rtime;
578 compat_time_t msg_ctime;
579 compat_ulong_t msg_lcbytes;
580 compat_ulong_t msg_lqbytes;
581 unsigned short msg_cbytes;
582 unsigned short msg_qnum;
583 unsigned short msg_qbytes;
584 compat_ipc_pid_t msg_lspid;
585 compat_ipc_pid_t msg_lrpid;
586};
587
588static int copy_compat_msqid_from_user(struct msqid64_ds *out, void __user *buf,
589 int version)
590{
591 memset(out, 0, sizeof(*out));
592 if (version == IPC_64) {
593 struct compat_msqid64_ds *p = buf;
594 if (get_compat_ipc64_perm(&out->msg_perm, &p->msg_perm))
595 return -EFAULT;
596 if (get_user(out->msg_qbytes, &p->msg_qbytes))
597 return -EFAULT;
598 } else {
599 struct compat_msqid_ds *p = buf;
600 if (get_compat_ipc_perm(&out->msg_perm, &p->msg_perm))
601 return -EFAULT;
602 if (get_user(out->msg_qbytes, &p->msg_qbytes))
603 return -EFAULT;
604 }
605 return 0;
606}
607
608static int copy_compat_msqid_to_user(void __user *buf, struct msqid64_ds *in,
609 int version)
610{
611 if (version == IPC_64) {
612 struct compat_msqid64_ds v;
613 memset(&v, 0, sizeof(v));
614 to_compat_ipc64_perm(&v.msg_perm, &in->msg_perm);
615 v.msg_stime = in->msg_stime;
616 v.msg_rtime = in->msg_rtime;
617 v.msg_ctime = in->msg_ctime;
618 v.msg_cbytes = in->msg_cbytes;
619 v.msg_qnum = in->msg_qnum;
620 v.msg_qbytes = in->msg_qbytes;
621 v.msg_lspid = in->msg_lspid;
622 v.msg_lrpid = in->msg_lrpid;
623 return copy_to_user(buf, &v, sizeof(v));
624 } else {
625 struct compat_msqid_ds v;
626 memset(&v, 0, sizeof(v));
627 to_compat_ipc_perm(&v.msg_perm, &in->msg_perm);
628 v.msg_stime = in->msg_stime;
629 v.msg_rtime = in->msg_rtime;
630 v.msg_ctime = in->msg_ctime;
631 v.msg_cbytes = in->msg_cbytes;
632 v.msg_qnum = in->msg_qnum;
633 v.msg_qbytes = in->msg_qbytes;
634 v.msg_lspid = in->msg_lspid;
635 v.msg_lrpid = in->msg_lrpid;
636 return copy_to_user(buf, &v, sizeof(v));
637 }
638}
639
640COMPAT_SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, void __user *, uptr)
641{
642 struct ipc_namespace *ns;
643 int err;
644 struct msqid64_ds msqid64;
645 int version = compat_ipc_parse_version(&cmd);
646
647 ns = current->nsproxy->ipc_ns;
648
649 if (msqid < 0 || cmd < 0)
650 return -EINVAL;
651
652 switch (cmd & (~IPC_64)) {
653 case IPC_INFO:
654 case MSG_INFO: {
655 struct msginfo msginfo;
656 err = msgctl_info(ns, msqid, cmd, &msginfo);
657 if (err < 0)
658 return err;
659 if (copy_to_user(uptr, &msginfo, sizeof(struct msginfo)))
660 err = -EFAULT;
661 return err;
662 }
663 case IPC_STAT:
664 case MSG_STAT:
665 err = msgctl_stat(ns, msqid, cmd, &msqid64);
666 if (err < 0)
667 return err;
668 if (copy_compat_msqid_to_user(uptr, &msqid64, version))
669 err = -EFAULT;
670 return err;
671 case IPC_SET:
672 if (copy_compat_msqid_from_user(&msqid64, uptr, version))
673 return -EFAULT;
674 /* fallthru */
675 case IPC_RMID:
676 return msgctl_down(ns, msqid, cmd, &msqid64);
677 default:
678 return -EINVAL;
679 }
680}
681#endif
682
580static int testmsg(struct msg_msg *msg, long type, int mode) 683static int testmsg(struct msg_msg *msg, long type, int mode)
581{ 684{
582 switch (mode) { 685 switch (mode) {
@@ -627,7 +730,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg,
627 return 0; 730 return 0;
628} 731}
629 732
630long do_msgsnd(int msqid, long mtype, void __user *mtext, 733static long do_msgsnd(int msqid, long mtype, void __user *mtext,
631 size_t msgsz, int msgflg) 734 size_t msgsz, int msgflg)
632{ 735{
633 struct msg_queue *msq; 736 struct msg_queue *msq;
@@ -750,6 +853,25 @@ SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
750 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg); 853 return do_msgsnd(msqid, mtype, msgp->mtext, msgsz, msgflg);
751} 854}
752 855
856#ifdef CONFIG_COMPAT
857
858struct compat_msgbuf {
859 compat_long_t mtype;
860 char mtext[1];
861};
862
863COMPAT_SYSCALL_DEFINE4(msgsnd, int, msqid, compat_uptr_t, msgp,
864 compat_ssize_t, msgsz, int, msgflg)
865{
866 struct compat_msgbuf __user *up = compat_ptr(msgp);
867 compat_long_t mtype;
868
869 if (get_user(mtype, &up->mtype))
870 return -EFAULT;
871 return do_msgsnd(msqid, mtype, up->mtext, (ssize_t)msgsz, msgflg);
872}
873#endif
874
753static inline int convert_mode(long *msgtyp, int msgflg) 875static inline int convert_mode(long *msgtyp, int msgflg)
754{ 876{
755 if (msgflg & MSG_COPY) 877 if (msgflg & MSG_COPY)
@@ -846,7 +968,7 @@ static struct msg_msg *find_msg(struct msg_queue *msq, long *msgtyp, int mode)
846 return found ?: ERR_PTR(-EAGAIN); 968 return found ?: ERR_PTR(-EAGAIN);
847} 969}
848 970
849long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg, 971static long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgflg,
850 long (*msg_handler)(void __user *, struct msg_msg *, size_t)) 972 long (*msg_handler)(void __user *, struct msg_msg *, size_t))
851{ 973{
852 int mode; 974 int mode;
@@ -1010,6 +1132,28 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
1010 return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); 1132 return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
1011} 1133}
1012 1134
1135#ifdef CONFIG_COMPAT
1136static long compat_do_msg_fill(void __user *dest, struct msg_msg *msg, size_t bufsz)
1137{
1138 struct compat_msgbuf __user *msgp = dest;
1139 size_t msgsz;
1140
1141 if (put_user(msg->m_type, &msgp->mtype))
1142 return -EFAULT;
1143
1144 msgsz = (bufsz > msg->m_ts) ? msg->m_ts : bufsz;
1145 if (store_msg(msgp->mtext, msg, msgsz))
1146 return -EFAULT;
1147 return msgsz;
1148}
1149
1150COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
1151 compat_ssize_t, msgsz, compat_long_t, msgtyp, int, msgflg)
1152{
1153 return do_msgrcv(msqid, compat_ptr(msgp), (ssize_t)msgsz, (long)msgtyp,
1154 msgflg, compat_do_msg_fill);
1155}
1156#endif
1013 1157
1014int msg_init_ns(struct ipc_namespace *ns) 1158int msg_init_ns(struct ipc_namespace *ns)
1015{ 1159{
@@ -1039,7 +1183,7 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
1039 struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); 1183 struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
1040 1184
1041 seq_printf(s, 1185 seq_printf(s,
1042 "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", 1186 "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10llu %10llu %10llu\n",
1043 msq->q_perm.key, 1187 msq->q_perm.key,
1044 msq->q_perm.id, 1188 msq->q_perm.id,
1045 msq->q_perm.mode, 1189 msq->q_perm.mode,
diff --git a/ipc/sem.c b/ipc/sem.c
index 013c7981f3c7..f7385bce5fd3 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -512,7 +512,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
512 INIT_LIST_HEAD(&sma->pending_const); 512 INIT_LIST_HEAD(&sma->pending_const);
513 INIT_LIST_HEAD(&sma->list_id); 513 INIT_LIST_HEAD(&sma->list_id);
514 sma->sem_nsems = nsems; 514 sma->sem_nsems = nsems;
515 sma->sem_ctime = get_seconds(); 515 sma->sem_ctime = ktime_get_real_seconds();
516 516
517 retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni); 517 retval = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
518 if (retval < 0) { 518 if (retval < 0) {
@@ -1163,14 +1163,14 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
1163 } 1163 }
1164} 1164}
1165 1165
1166static time_t get_semotime(struct sem_array *sma) 1166static time64_t get_semotime(struct sem_array *sma)
1167{ 1167{
1168 int i; 1168 int i;
1169 time_t res; 1169 time64_t res;
1170 1170
1171 res = sma->sems[0].sem_otime; 1171 res = sma->sems[0].sem_otime;
1172 for (i = 1; i < sma->sem_nsems; i++) { 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 if (to > res) 1175 if (to > res)
1176 res = to; 1176 res = to;
@@ -1178,112 +1178,95 @@ static time_t get_semotime(struct sem_array *sma)
1178 return res; 1178 return res;
1179} 1179}
1180 1180
1181static int semctl_nolock(struct ipc_namespace *ns, int semid, 1181static int semctl_stat(struct ipc_namespace *ns, int semid,
1182 int cmd, int version, void __user *p) 1182 int cmd, struct semid64_ds *semid64)
1183{ 1183{
1184 int err;
1185 struct sem_array *sma; 1184 struct sem_array *sma;
1185 int id = 0;
1186 int err;
1186 1187
1187 switch (cmd) { 1188 memset(semid64, 0, sizeof(*semid64));
1188 case IPC_INFO:
1189 case SEM_INFO:
1190 {
1191 struct seminfo seminfo;
1192 int max_id;
1193
1194 err = security_sem_semctl(NULL, cmd);
1195 if (err)
1196 return err;
1197 1189
1198 memset(&seminfo, 0, sizeof(seminfo)); 1190 rcu_read_lock();
1199 seminfo.semmni = ns->sc_semmni; 1191 if (cmd == SEM_STAT) {
1200 seminfo.semmns = ns->sc_semmns; 1192 sma = sem_obtain_object(ns, semid);
1201 seminfo.semmsl = ns->sc_semmsl; 1193 if (IS_ERR(sma)) {
1202 seminfo.semopm = ns->sc_semopm; 1194 err = PTR_ERR(sma);
1203 seminfo.semvmx = SEMVMX; 1195 goto out_unlock;
1204 seminfo.semmnu = SEMMNU; 1196 }
1205 seminfo.semmap = SEMMAP; 1197 id = sma->sem_perm.id;
1206 seminfo.semume = SEMUME; 1198 } else {
1207 down_read(&sem_ids(ns).rwsem); 1199 sma = sem_obtain_object_check(ns, semid);
1208 if (cmd == SEM_INFO) { 1200 if (IS_ERR(sma)) {
1209 seminfo.semusz = sem_ids(ns).in_use; 1201 err = PTR_ERR(sma);
1210 seminfo.semaem = ns->used_sems; 1202 goto out_unlock;
1211 } else {
1212 seminfo.semusz = SEMUSZ;
1213 seminfo.semaem = SEMAEM;
1214 } 1203 }
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 } 1204 }
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 1205
1229 rcu_read_lock(); 1206 err = -EACCES;
1230 if (cmd == SEM_STAT) { 1207 if (ipcperms(ns, &sma->sem_perm, S_IRUGO))
1231 sma = sem_obtain_object(ns, semid); 1208 goto out_unlock;
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 1209
1245 err = -EACCES; 1210 err = security_sem_semctl(sma, cmd);
1246 if (ipcperms(ns, &sma->sem_perm, S_IRUGO)) 1211 if (err)
1247 goto out_unlock; 1212 goto out_unlock;
1248 1213
1249 err = security_sem_semctl(sma, cmd); 1214 kernel_to_ipc64_perm(&sma->sem_perm, &semid64->sem_perm);
1250 if (err) 1215 semid64->sem_otime = get_semotime(sma);
1251 goto out_unlock; 1216 semid64->sem_ctime = sma->sem_ctime;
1217 semid64->sem_nsems = sma->sem_nsems;
1218 rcu_read_unlock();
1219 return id;
1252 1220
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 }
1265out_unlock: 1221out_unlock:
1266 rcu_read_unlock(); 1222 rcu_read_unlock();
1267 return err; 1223 return err;
1268} 1224}
1269 1225
1226static 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
1270static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum, 1261static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
1271 unsigned long arg) 1262 int val)
1272{ 1263{
1273 struct sem_undo *un; 1264 struct sem_undo *un;
1274 struct sem_array *sma; 1265 struct sem_array *sma;
1275 struct sem *curr; 1266 struct sem *curr;
1276 int err, val; 1267 int err;
1277 DEFINE_WAKE_Q(wake_q); 1268 DEFINE_WAKE_Q(wake_q);
1278 1269
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
1287 if (val > SEMVMX || val < 0) 1270 if (val > SEMVMX || val < 0)
1288 return -ERANGE; 1271 return -ERANGE;
1289 1272
@@ -1327,7 +1310,7 @@ static int semctl_setval(struct ipc_namespace *ns, int semid, int semnum,
1327 1310
1328 curr->semval = val; 1311 curr->semval = val;
1329 curr->sempid = task_tgid_vnr(current); 1312 curr->sempid = task_tgid_vnr(current);
1330 sma->sem_ctime = get_seconds(); 1313 sma->sem_ctime = ktime_get_real_seconds();
1331 /* maybe some queued-up processes were waiting for this */ 1314 /* maybe some queued-up processes were waiting for this */
1332 do_smart_update(sma, NULL, 0, 0, &wake_q); 1315 do_smart_update(sma, NULL, 0, 0, &wake_q);
1333 sem_unlock(sma, -1); 1316 sem_unlock(sma, -1);
@@ -1455,7 +1438,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
1455 for (i = 0; i < nsems; i++) 1438 for (i = 0; i < nsems; i++)
1456 un->semadj[i] = 0; 1439 un->semadj[i] = 0;
1457 } 1440 }
1458 sma->sem_ctime = get_seconds(); 1441 sma->sem_ctime = ktime_get_real_seconds();
1459 /* maybe some queued-up processes were waiting for this */ 1442 /* maybe some queued-up processes were waiting for this */
1460 do_smart_update(sma, NULL, 0, 0, &wake_q); 1443 do_smart_update(sma, NULL, 0, 0, &wake_q);
1461 err = 0; 1444 err = 0;
@@ -1532,23 +1515,17 @@ copy_semid_from_user(struct semid64_ds *out, void __user *buf, int version)
1532 * NOTE: no locks must be held, the rwsem is taken inside this function. 1515 * NOTE: no locks must be held, the rwsem is taken inside this function.
1533 */ 1516 */
1534static int semctl_down(struct ipc_namespace *ns, int semid, 1517static int semctl_down(struct ipc_namespace *ns, int semid,
1535 int cmd, int version, void __user *p) 1518 int cmd, struct semid64_ds *semid64)
1536{ 1519{
1537 struct sem_array *sma; 1520 struct sem_array *sma;
1538 int err; 1521 int err;
1539 struct semid64_ds semid64;
1540 struct kern_ipc_perm *ipcp; 1522 struct kern_ipc_perm *ipcp;
1541 1523
1542 if (cmd == IPC_SET) {
1543 if (copy_semid_from_user(&semid64, p, version))
1544 return -EFAULT;
1545 }
1546
1547 down_write(&sem_ids(ns).rwsem); 1524 down_write(&sem_ids(ns).rwsem);
1548 rcu_read_lock(); 1525 rcu_read_lock();
1549 1526
1550 ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd, 1527 ipcp = ipcctl_pre_down_nolock(ns, &sem_ids(ns), semid, cmd,
1551 &semid64.sem_perm, 0); 1528 &semid64->sem_perm, 0);
1552 if (IS_ERR(ipcp)) { 1529 if (IS_ERR(ipcp)) {
1553 err = PTR_ERR(ipcp); 1530 err = PTR_ERR(ipcp);
1554 goto out_unlock1; 1531 goto out_unlock1;
@@ -1568,10 +1545,10 @@ static int semctl_down(struct ipc_namespace *ns, int semid,
1568 goto out_up; 1545 goto out_up;
1569 case IPC_SET: 1546 case IPC_SET:
1570 sem_lock(sma, NULL, -1); 1547 sem_lock(sma, NULL, -1);
1571 err = ipc_update_perm(&semid64.sem_perm, ipcp); 1548 err = ipc_update_perm(&semid64->sem_perm, ipcp);
1572 if (err) 1549 if (err)
1573 goto out_unlock0; 1550 goto out_unlock0;
1574 sma->sem_ctime = get_seconds(); 1551 sma->sem_ctime = ktime_get_real_seconds();
1575 break; 1552 break;
1576 default: 1553 default:
1577 err = -EINVAL; 1554 err = -EINVAL;
@@ -1592,6 +1569,8 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
1592 int version; 1569 int version;
1593 struct ipc_namespace *ns; 1570 struct ipc_namespace *ns;
1594 void __user *p = (void __user *)arg; 1571 void __user *p = (void __user *)arg;
1572 struct semid64_ds semid64;
1573 int err;
1595 1574
1596 if (semid < 0) 1575 if (semid < 0)
1597 return -EINVAL; 1576 return -EINVAL;
@@ -1602,9 +1581,15 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
1602 switch (cmd) { 1581 switch (cmd) {
1603 case IPC_INFO: 1582 case IPC_INFO:
1604 case SEM_INFO: 1583 case SEM_INFO:
1584 return semctl_info(ns, semid, cmd, p);
1605 case IPC_STAT: 1585 case IPC_STAT:
1606 case SEM_STAT: 1586 case SEM_STAT:
1607 return semctl_nolock(ns, semid, cmd, version, p); 1587 err = semctl_stat(ns, semid, cmd, &semid64);
1588 if (err < 0)
1589 return err;
1590 if (copy_semid_to_user(p, &semid64, version))
1591 err = -EFAULT;
1592 return err;
1608 case GETALL: 1593 case GETALL:
1609 case GETVAL: 1594 case GETVAL:
1610 case GETPID: 1595 case GETPID:
@@ -1612,15 +1597,120 @@ SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, unsigned long, arg)
1612 case GETZCNT: 1597 case GETZCNT:
1613 case SETALL: 1598 case SETALL:
1614 return semctl_main(ns, semid, semnum, cmd, p); 1599 return semctl_main(ns, semid, semnum, cmd, p);
1600 case SETVAL: {
1601 int val;
1602#if defined(CONFIG_64BIT) && defined(__BIG_ENDIAN)
1603 /* big-endian 64bit */
1604 val = arg >> 32;
1605#else
1606 /* 32bit or little-endian 64bit */
1607 val = arg;
1608#endif
1609 return semctl_setval(ns, semid, semnum, val);
1610 }
1611 case IPC_SET:
1612 if (copy_semid_from_user(&semid64, p, version))
1613 return -EFAULT;
1614 case IPC_RMID:
1615 return semctl_down(ns, semid, cmd, &semid64);
1616 default:
1617 return -EINVAL;
1618 }
1619}
1620
1621#ifdef CONFIG_COMPAT
1622
1623struct compat_semid_ds {
1624 struct compat_ipc_perm sem_perm;
1625 compat_time_t sem_otime;
1626 compat_time_t sem_ctime;
1627 compat_uptr_t sem_base;
1628 compat_uptr_t sem_pending;
1629 compat_uptr_t sem_pending_last;
1630 compat_uptr_t undo;
1631 unsigned short sem_nsems;
1632};
1633
1634static int copy_compat_semid_from_user(struct semid64_ds *out, void __user *buf,
1635 int version)
1636{
1637 memset(out, 0, sizeof(*out));
1638 if (version == IPC_64) {
1639 struct compat_semid64_ds *p = buf;
1640 return get_compat_ipc64_perm(&out->sem_perm, &p->sem_perm);
1641 } else {
1642 struct compat_semid_ds *p = buf;
1643 return get_compat_ipc_perm(&out->sem_perm, &p->sem_perm);
1644 }
1645}
1646
1647static int copy_compat_semid_to_user(void __user *buf, struct semid64_ds *in,
1648 int version)
1649{
1650 if (version == IPC_64) {
1651 struct compat_semid64_ds v;
1652 memset(&v, 0, sizeof(v));
1653 to_compat_ipc64_perm(&v.sem_perm, &in->sem_perm);
1654 v.sem_otime = in->sem_otime;
1655 v.sem_ctime = in->sem_ctime;
1656 v.sem_nsems = in->sem_nsems;
1657 return copy_to_user(buf, &v, sizeof(v));
1658 } else {
1659 struct compat_semid_ds v;
1660 memset(&v, 0, sizeof(v));
1661 to_compat_ipc_perm(&v.sem_perm, &in->sem_perm);
1662 v.sem_otime = in->sem_otime;
1663 v.sem_ctime = in->sem_ctime;
1664 v.sem_nsems = in->sem_nsems;
1665 return copy_to_user(buf, &v, sizeof(v));
1666 }
1667}
1668
1669COMPAT_SYSCALL_DEFINE4(semctl, int, semid, int, semnum, int, cmd, int, arg)
1670{
1671 void __user *p = compat_ptr(arg);
1672 struct ipc_namespace *ns;
1673 struct semid64_ds semid64;
1674 int version = compat_ipc_parse_version(&cmd);
1675 int err;
1676
1677 ns = current->nsproxy->ipc_ns;
1678
1679 if (semid < 0)
1680 return -EINVAL;
1681
1682 switch (cmd & (~IPC_64)) {
1683 case IPC_INFO:
1684 case SEM_INFO:
1685 return semctl_info(ns, semid, cmd, p);
1686 case IPC_STAT:
1687 case SEM_STAT:
1688 err = semctl_stat(ns, semid, cmd, &semid64);
1689 if (err < 0)
1690 return err;
1691 if (copy_compat_semid_to_user(p, &semid64, version))
1692 err = -EFAULT;
1693 return err;
1694 case GETVAL:
1695 case GETPID:
1696 case GETNCNT:
1697 case GETZCNT:
1698 case GETALL:
1699 case SETALL:
1700 return semctl_main(ns, semid, semnum, cmd, p);
1615 case SETVAL: 1701 case SETVAL:
1616 return semctl_setval(ns, semid, semnum, arg); 1702 return semctl_setval(ns, semid, semnum, arg);
1617 case IPC_RMID:
1618 case IPC_SET: 1703 case IPC_SET:
1619 return semctl_down(ns, semid, cmd, version, p); 1704 if (copy_compat_semid_from_user(&semid64, p, version))
1705 return -EFAULT;
1706 /* fallthru */
1707 case IPC_RMID:
1708 return semctl_down(ns, semid, cmd, &semid64);
1620 default: 1709 default:
1621 return -EINVAL; 1710 return -EINVAL;
1622 } 1711 }
1623} 1712}
1713#endif
1624 1714
1625/* If the task doesn't already have a undo_list, then allocate one 1715/* If the task doesn't already have a undo_list, then allocate one
1626 * here. We guarantee there is only one thread using this undo list, 1716 * here. We guarantee there is only one thread using this undo list,
@@ -1766,8 +1856,8 @@ out:
1766 return un; 1856 return un;
1767} 1857}
1768 1858
1769SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, 1859static long do_semtimedop(int semid, struct sembuf __user *tsops,
1770 unsigned, nsops, const struct timespec __user *, timeout) 1860 unsigned nsops, const struct timespec64 *timeout)
1771{ 1861{
1772 int error = -EINVAL; 1862 int error = -EINVAL;
1773 struct sem_array *sma; 1863 struct sem_array *sma;
@@ -1798,17 +1888,12 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1798 } 1888 }
1799 1889
1800 if (timeout) { 1890 if (timeout) {
1801 struct timespec _timeout; 1891 if (timeout->tv_sec < 0 || timeout->tv_nsec < 0 ||
1802 if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) { 1892 timeout->tv_nsec >= 1000000000L) {
1803 error = -EFAULT;
1804 goto out_free;
1805 }
1806 if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
1807 _timeout.tv_nsec >= 1000000000L) {
1808 error = -EINVAL; 1893 error = -EINVAL;
1809 goto out_free; 1894 goto out_free;
1810 } 1895 }
1811 jiffies_left = timespec_to_jiffies(&_timeout); 1896 jiffies_left = timespec64_to_jiffies(timeout);
1812 } 1897 }
1813 1898
1814 max = 0; 1899 max = 0;
@@ -2023,10 +2108,37 @@ out_free:
2023 return error; 2108 return error;
2024} 2109}
2025 2110
2111SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
2112 unsigned, nsops, const struct timespec __user *, timeout)
2113{
2114 if (timeout) {
2115 struct timespec64 ts;
2116 if (get_timespec64(&ts, timeout))
2117 return -EFAULT;
2118 return do_semtimedop(semid, tsops, nsops, &ts);
2119 }
2120 return do_semtimedop(semid, tsops, nsops, NULL);
2121}
2122
2123#ifdef CONFIG_COMPAT
2124COMPAT_SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsems,
2125 unsigned, nsops,
2126 const struct compat_timespec __user *, timeout)
2127{
2128 if (timeout) {
2129 struct timespec64 ts;
2130 if (compat_get_timespec64(&ts, timeout))
2131 return -EFAULT;
2132 return do_semtimedop(semid, tsems, nsops, &ts);
2133 }
2134 return do_semtimedop(semid, tsems, nsops, NULL);
2135}
2136#endif
2137
2026SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops, 2138SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops,
2027 unsigned, nsops) 2139 unsigned, nsops)
2028{ 2140{
2029 return sys_semtimedop(semid, tsops, nsops, NULL); 2141 return do_semtimedop(semid, tsops, nsops, NULL);
2030} 2142}
2031 2143
2032/* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between 2144/* If CLONE_SYSVSEM is set, establish sharing of SEM_UNDO state between
@@ -2183,7 +2295,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
2183 struct user_namespace *user_ns = seq_user_ns(s); 2295 struct user_namespace *user_ns = seq_user_ns(s);
2184 struct kern_ipc_perm *ipcp = it; 2296 struct kern_ipc_perm *ipcp = it;
2185 struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm); 2297 struct sem_array *sma = container_of(ipcp, struct sem_array, sem_perm);
2186 time_t sem_otime; 2298 time64_t sem_otime;
2187 2299
2188 /* 2300 /*
2189 * The proc interface isn't aware of sem_lock(), it calls 2301 * The proc interface isn't aware of sem_lock(), it calls
@@ -2196,7 +2308,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
2196 sem_otime = get_semotime(sma); 2308 sem_otime = get_semotime(sma);
2197 2309
2198 seq_printf(s, 2310 seq_printf(s,
2199 "%10d %10d %4o %10u %5u %5u %5u %5u %10lu %10lu\n", 2311 "%10d %10d %4o %10u %5u %5u %5u %5u %10llu %10llu\n",
2200 sma->sem_perm.key, 2312 sma->sem_perm.key,
2201 sma->sem_perm.id, 2313 sma->sem_perm.id,
2202 sma->sem_perm.mode, 2314 sma->sem_perm.mode,
diff --git a/ipc/shm.c b/ipc/shm.c
index 8fc97beb5234..1b3adfe3c60e 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -202,7 +202,7 @@ static int __shm_open(struct vm_area_struct *vma)
202 if (IS_ERR(shp)) 202 if (IS_ERR(shp))
203 return PTR_ERR(shp); 203 return PTR_ERR(shp);
204 204
205 shp->shm_atim = get_seconds(); 205 shp->shm_atim = ktime_get_real_seconds();
206 shp->shm_lprid = task_tgid_vnr(current); 206 shp->shm_lprid = task_tgid_vnr(current);
207 shp->shm_nattch++; 207 shp->shm_nattch++;
208 shm_unlock(shp); 208 shm_unlock(shp);
@@ -289,7 +289,7 @@ static void shm_close(struct vm_area_struct *vma)
289 goto done; /* no-op */ 289 goto done; /* no-op */
290 290
291 shp->shm_lprid = task_tgid_vnr(current); 291 shp->shm_lprid = task_tgid_vnr(current);
292 shp->shm_dtim = get_seconds(); 292 shp->shm_dtim = ktime_get_real_seconds();
293 shp->shm_nattch--; 293 shp->shm_nattch--;
294 if (shm_may_destroy(ns, shp)) 294 if (shm_may_destroy(ns, shp))
295 shm_destroy(ns, shp); 295 shm_destroy(ns, shp);
@@ -594,7 +594,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
594 shp->shm_cprid = task_tgid_vnr(current); 594 shp->shm_cprid = task_tgid_vnr(current);
595 shp->shm_lprid = 0; 595 shp->shm_lprid = 0;
596 shp->shm_atim = shp->shm_dtim = 0; 596 shp->shm_atim = shp->shm_dtim = 0;
597 shp->shm_ctim = get_seconds(); 597 shp->shm_ctim = ktime_get_real_seconds();
598 shp->shm_segsz = size; 598 shp->shm_segsz = size;
599 shp->shm_nattch = 0; 599 shp->shm_nattch = 0;
600 shp->shm_file = file; 600 shp->shm_file = file;
@@ -815,23 +815,17 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
815 * NOTE: no locks must be held, the rwsem is taken inside this function. 815 * NOTE: no locks must be held, the rwsem is taken inside this function.
816 */ 816 */
817static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd, 817static 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 struct kern_ipc_perm *ipcp; 820 struct kern_ipc_perm *ipcp;
821 struct shmid64_ds shmid64;
822 struct shmid_kernel *shp; 821 struct shmid_kernel *shp;
823 int err; 822 int err;
824 823
825 if (cmd == IPC_SET) {
826 if (copy_shmid_from_user(&shmid64, buf, version))
827 return -EFAULT;
828 }
829
830 down_write(&shm_ids(ns).rwsem); 824 down_write(&shm_ids(ns).rwsem);
831 rcu_read_lock(); 825 rcu_read_lock();
832 826
833 ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd, 827 ipcp = ipcctl_pre_down_nolock(ns, &shm_ids(ns), shmid, cmd,
834 &shmid64.shm_perm, 0); 828 &shmid64->shm_perm, 0);
835 if (IS_ERR(ipcp)) { 829 if (IS_ERR(ipcp)) {
836 err = PTR_ERR(ipcp); 830 err = PTR_ERR(ipcp);
837 goto out_unlock1; 831 goto out_unlock1;
@@ -851,10 +845,10 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,
851 goto out_up; 845 goto out_up;
852 case IPC_SET: 846 case IPC_SET:
853 ipc_lock_object(&shp->shm_perm); 847 ipc_lock_object(&shp->shm_perm);
854 err = ipc_update_perm(&shmid64.shm_perm, ipcp); 848 err = ipc_update_perm(&shmid64->shm_perm, ipcp);
855 if (err) 849 if (err)
856 goto out_unlock0; 850 goto out_unlock0;
857 shp->shm_ctim = get_seconds(); 851 shp->shm_ctim = ktime_get_real_seconds();
858 break; 852 break;
859 default: 853 default:
860 err = -EINVAL; 854 err = -EINVAL;
@@ -870,125 +864,175 @@ out_up:
870 return err; 864 return err;
871} 865}
872 866
873static int shmctl_nolock(struct ipc_namespace *ns, int shmid, 867static int shmctl_ipc_info(struct ipc_namespace *ns,
874 int cmd, int version, void __user *buf) 868 struct shminfo64 *shminfo)
875{ 869{
876 int err; 870 int err = security_shm_shmctl(NULL, IPC_INFO);
877 struct shmid_kernel *shp; 871 if (!err) {
878 872 memset(shminfo, 0, sizeof(*shminfo));
879 /* preliminary security checks for *_INFO */ 873 shminfo->shmmni = shminfo->shmseg = ns->shm_ctlmni;
880 if (cmd == IPC_INFO || cmd == SHM_INFO) { 874 shminfo->shmmax = ns->shm_ctlmax;
881 err = security_shm_shmctl(NULL, cmd); 875 shminfo->shmall = ns->shm_ctlall;
882 if (err) 876 shminfo->shmmin = SHMMIN;
883 return err;
884 }
885
886 switch (cmd) {
887 case IPC_INFO:
888 {
889 struct shminfo64 shminfo;
890
891 memset(&shminfo, 0, sizeof(shminfo));
892 shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni;
893 shminfo.shmmax = ns->shm_ctlmax;
894 shminfo.shmall = ns->shm_ctlall;
895
896 shminfo.shmmin = SHMMIN;
897 if (copy_shminfo_to_user(buf, &shminfo, version))
898 return -EFAULT;
899
900 down_read(&shm_ids(ns).rwsem); 877 down_read(&shm_ids(ns).rwsem);
901 err = ipc_get_maxid(&shm_ids(ns)); 878 err = ipc_get_maxid(&shm_ids(ns));
902 up_read(&shm_ids(ns).rwsem); 879 up_read(&shm_ids(ns).rwsem);
903
904 if (err < 0) 880 if (err < 0)
905 err = 0; 881 err = 0;
906 goto out;
907 } 882 }
908 case SHM_INFO: 883 return err;
909 { 884}
910 struct shm_info shm_info;
911 885
912 memset(&shm_info, 0, sizeof(shm_info)); 886static int shmctl_shm_info(struct ipc_namespace *ns,
887 struct shm_info *shm_info)
888{
889 int err = security_shm_shmctl(NULL, SHM_INFO);
890 if (!err) {
891 memset(shm_info, 0, sizeof(*shm_info));
913 down_read(&shm_ids(ns).rwsem); 892 down_read(&shm_ids(ns).rwsem);
914 shm_info.used_ids = shm_ids(ns).in_use; 893 shm_info->used_ids = shm_ids(ns).in_use;
915 shm_get_stat(ns, &shm_info.shm_rss, &shm_info.shm_swp); 894 shm_get_stat(ns, &shm_info->shm_rss, &shm_info->shm_swp);
916 shm_info.shm_tot = ns->shm_tot; 895 shm_info->shm_tot = ns->shm_tot;
917 shm_info.swap_attempts = 0; 896 shm_info->swap_attempts = 0;
918 shm_info.swap_successes = 0; 897 shm_info->swap_successes = 0;
919 err = ipc_get_maxid(&shm_ids(ns)); 898 err = ipc_get_maxid(&shm_ids(ns));
920 up_read(&shm_ids(ns).rwsem); 899 up_read(&shm_ids(ns).rwsem);
921 if (copy_to_user(buf, &shm_info, sizeof(shm_info))) { 900 if (err < 0)
922 err = -EFAULT; 901 err = 0;
923 goto out; 902 }
903 return err;
904}
905
906static int shmctl_stat(struct ipc_namespace *ns, int shmid,
907 int cmd, struct shmid64_ds *tbuf)
908{
909 struct shmid_kernel *shp;
910 int result;
911 int err;
912
913 rcu_read_lock();
914 if (cmd == SHM_STAT) {
915 shp = shm_obtain_object(ns, shmid);
916 if (IS_ERR(shp)) {
917 err = PTR_ERR(shp);
918 goto out_unlock;
919 }
920 result = shp->shm_perm.id;
921 } else {
922 shp = shm_obtain_object_check(ns, shmid);
923 if (IS_ERR(shp)) {
924 err = PTR_ERR(shp);
925 goto out_unlock;
924 } 926 }
927 result = 0;
928 }
925 929
926 err = err < 0 ? 0 : err; 930 err = -EACCES;
927 goto out; 931 if (ipcperms(ns, &shp->shm_perm, S_IRUGO))
932 goto out_unlock;
933
934 err = security_shm_shmctl(shp, cmd);
935 if (err)
936 goto out_unlock;
937
938 memset(tbuf, 0, sizeof(*tbuf));
939 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf->shm_perm);
940 tbuf->shm_segsz = shp->shm_segsz;
941 tbuf->shm_atime = shp->shm_atim;
942 tbuf->shm_dtime = shp->shm_dtim;
943 tbuf->shm_ctime = shp->shm_ctim;
944 tbuf->shm_cpid = shp->shm_cprid;
945 tbuf->shm_lpid = shp->shm_lprid;
946 tbuf->shm_nattch = shp->shm_nattch;
947 rcu_read_unlock();
948 return result;
949
950out_unlock:
951 rcu_read_unlock();
952 return err;
953}
954
955static int shmctl_do_lock(struct ipc_namespace *ns, int shmid, int cmd)
956{
957 struct shmid_kernel *shp;
958 struct file *shm_file;
959 int err;
960
961 rcu_read_lock();
962 shp = shm_obtain_object_check(ns, shmid);
963 if (IS_ERR(shp)) {
964 err = PTR_ERR(shp);
965 goto out_unlock1;
928 } 966 }
929 case SHM_STAT:
930 case IPC_STAT:
931 {
932 struct shmid64_ds tbuf;
933 int result;
934
935 rcu_read_lock();
936 if (cmd == SHM_STAT) {
937 shp = shm_obtain_object(ns, shmid);
938 if (IS_ERR(shp)) {
939 err = PTR_ERR(shp);
940 goto out_unlock;
941 }
942 result = shp->shm_perm.id;
943 } else {
944 shp = shm_obtain_object_check(ns, shmid);
945 if (IS_ERR(shp)) {
946 err = PTR_ERR(shp);
947 goto out_unlock;
948 }
949 result = 0;
950 }
951 967
952 err = -EACCES; 968 audit_ipc_obj(&(shp->shm_perm));
953 if (ipcperms(ns, &shp->shm_perm, S_IRUGO)) 969 err = security_shm_shmctl(shp, cmd);
954 goto out_unlock; 970 if (err)
971 goto out_unlock1;
955 972
956 err = security_shm_shmctl(shp, cmd); 973 ipc_lock_object(&shp->shm_perm);
957 if (err)
958 goto out_unlock;
959 974
960 memset(&tbuf, 0, sizeof(tbuf)); 975 /* check if shm_destroy() is tearing down shp */
961 kernel_to_ipc64_perm(&shp->shm_perm, &tbuf.shm_perm); 976 if (!ipc_valid_object(&shp->shm_perm)) {
962 tbuf.shm_segsz = shp->shm_segsz; 977 err = -EIDRM;
963 tbuf.shm_atime = shp->shm_atim; 978 goto out_unlock0;
964 tbuf.shm_dtime = shp->shm_dtim;
965 tbuf.shm_ctime = shp->shm_ctim;
966 tbuf.shm_cpid = shp->shm_cprid;
967 tbuf.shm_lpid = shp->shm_lprid;
968 tbuf.shm_nattch = shp->shm_nattch;
969 rcu_read_unlock();
970
971 if (copy_shmid_to_user(buf, &tbuf, version))
972 err = -EFAULT;
973 else
974 err = result;
975 goto out;
976 } 979 }
977 default: 980
978 return -EINVAL; 981 if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {
982 kuid_t euid = current_euid();
983
984 if (!uid_eq(euid, shp->shm_perm.uid) &&
985 !uid_eq(euid, shp->shm_perm.cuid)) {
986 err = -EPERM;
987 goto out_unlock0;
988 }
989 if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) {
990 err = -EPERM;
991 goto out_unlock0;
992 }
979 } 993 }
980 994
981out_unlock: 995 shm_file = shp->shm_file;
996 if (is_file_hugepages(shm_file))
997 goto out_unlock0;
998
999 if (cmd == SHM_LOCK) {
1000 struct user_struct *user = current_user();
1001
1002 err = shmem_lock(shm_file, 1, user);
1003 if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) {
1004 shp->shm_perm.mode |= SHM_LOCKED;
1005 shp->mlock_user = user;
1006 }
1007 goto out_unlock0;
1008 }
1009
1010 /* SHM_UNLOCK */
1011 if (!(shp->shm_perm.mode & SHM_LOCKED))
1012 goto out_unlock0;
1013 shmem_lock(shm_file, 0, shp->mlock_user);
1014 shp->shm_perm.mode &= ~SHM_LOCKED;
1015 shp->mlock_user = NULL;
1016 get_file(shm_file);
1017 ipc_unlock_object(&shp->shm_perm);
1018 rcu_read_unlock();
1019 shmem_unlock_mapping(shm_file->f_mapping);
1020
1021 fput(shm_file);
1022 return err;
1023
1024out_unlock0:
1025 ipc_unlock_object(&shp->shm_perm);
1026out_unlock1:
982 rcu_read_unlock(); 1027 rcu_read_unlock();
983out:
984 return err; 1028 return err;
985} 1029}
986 1030
987SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) 1031SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
988{ 1032{
989 struct shmid_kernel *shp;
990 int err, version; 1033 int err, version;
991 struct ipc_namespace *ns; 1034 struct ipc_namespace *ns;
1035 struct shmid64_ds sem64;
992 1036
993 if (cmd < 0 || shmid < 0) 1037 if (cmd < 0 || shmid < 0)
994 return -EINVAL; 1038 return -EINVAL;
@@ -997,92 +1041,222 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
997 ns = current->nsproxy->ipc_ns; 1041 ns = current->nsproxy->ipc_ns;
998 1042
999 switch (cmd) { 1043 switch (cmd) {
1000 case IPC_INFO: 1044 case IPC_INFO: {
1001 case SHM_INFO: 1045 struct shminfo64 shminfo;
1046 err = shmctl_ipc_info(ns, &shminfo);
1047 if (err < 0)
1048 return err;
1049 if (copy_shminfo_to_user(buf, &shminfo, version))
1050 err = -EFAULT;
1051 return err;
1052 }
1053 case SHM_INFO: {
1054 struct shm_info shm_info;
1055 err = shmctl_shm_info(ns, &shm_info);
1056 if (err < 0)
1057 return err;
1058 if (copy_to_user(buf, &shm_info, sizeof(shm_info)))
1059 err = -EFAULT;
1060 return err;
1061 }
1002 case SHM_STAT: 1062 case SHM_STAT:
1003 case IPC_STAT: 1063 case IPC_STAT: {
1004 return shmctl_nolock(ns, shmid, cmd, version, buf); 1064 err = shmctl_stat(ns, shmid, cmd, &sem64);
1005 case IPC_RMID: 1065 if (err < 0)
1066 return err;
1067 if (copy_shmid_to_user(buf, &sem64, version))
1068 err = -EFAULT;
1069 return err;
1070 }
1006 case IPC_SET: 1071 case IPC_SET:
1007 return shmctl_down(ns, shmid, cmd, buf, version); 1072 if (copy_shmid_from_user(&sem64, buf, version))
1073 return -EFAULT;
1074 /* fallthru */
1075 case IPC_RMID:
1076 return shmctl_down(ns, shmid, cmd, &sem64);
1008 case SHM_LOCK: 1077 case SHM_LOCK:
1009 case SHM_UNLOCK: 1078 case SHM_UNLOCK:
1010 { 1079 return shmctl_do_lock(ns, shmid, cmd);
1011 struct file *shm_file; 1080 default:
1081 return -EINVAL;
1082 }
1083}
1012 1084
1013 rcu_read_lock(); 1085#ifdef CONFIG_COMPAT
1014 shp = shm_obtain_object_check(ns, shmid); 1086
1015 if (IS_ERR(shp)) { 1087struct compat_shmid_ds {
1016 err = PTR_ERR(shp); 1088 struct compat_ipc_perm shm_perm;
1017 goto out_unlock1; 1089 int shm_segsz;
1018 } 1090 compat_time_t shm_atime;
1091 compat_time_t shm_dtime;
1092 compat_time_t shm_ctime;
1093 compat_ipc_pid_t shm_cpid;
1094 compat_ipc_pid_t shm_lpid;
1095 unsigned short shm_nattch;
1096 unsigned short shm_unused;
1097 compat_uptr_t shm_unused2;
1098 compat_uptr_t shm_unused3;
1099};
1019 1100
1020 audit_ipc_obj(&(shp->shm_perm)); 1101struct compat_shminfo64 {
1021 err = security_shm_shmctl(shp, cmd); 1102 compat_ulong_t shmmax;
1022 if (err) 1103 compat_ulong_t shmmin;
1023 goto out_unlock1; 1104 compat_ulong_t shmmni;
1105 compat_ulong_t shmseg;
1106 compat_ulong_t shmall;
1107 compat_ulong_t __unused1;
1108 compat_ulong_t __unused2;
1109 compat_ulong_t __unused3;
1110 compat_ulong_t __unused4;
1111};
1024 1112
1025 ipc_lock_object(&shp->shm_perm); 1113struct compat_shm_info {
1114 compat_int_t used_ids;
1115 compat_ulong_t shm_tot, shm_rss, shm_swp;
1116 compat_ulong_t swap_attempts, swap_successes;
1117};
1026 1118
1027 /* check if shm_destroy() is tearing down shp */ 1119static int copy_compat_shminfo_to_user(void __user *buf, struct shminfo64 *in,
1028 if (!ipc_valid_object(&shp->shm_perm)) { 1120 int version)
1029 err = -EIDRM; 1121{
1030 goto out_unlock0; 1122 if (in->shmmax > INT_MAX)
1031 } 1123 in->shmmax = INT_MAX;
1124 if (version == IPC_64) {
1125 struct compat_shminfo64 info;
1126 memset(&info, 0, sizeof(info));
1127 info.shmmax = in->shmmax;
1128 info.shmmin = in->shmmin;
1129 info.shmmni = in->shmmni;
1130 info.shmseg = in->shmseg;
1131 info.shmall = in->shmall;
1132 return copy_to_user(buf, &info, sizeof(info));
1133 } else {
1134 struct shminfo info;
1135 memset(&info, 0, sizeof(info));
1136 info.shmmax = in->shmmax;
1137 info.shmmin = in->shmmin;
1138 info.shmmni = in->shmmni;
1139 info.shmseg = in->shmseg;
1140 info.shmall = in->shmall;
1141 return copy_to_user(buf, &info, sizeof(info));
1142 }
1143}
1032 1144
1033 if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) { 1145static int put_compat_shm_info(struct shm_info *ip,
1034 kuid_t euid = current_euid(); 1146 struct compat_shm_info __user *uip)
1035 1147{
1036 if (!uid_eq(euid, shp->shm_perm.uid) && 1148 struct compat_shm_info info;
1037 !uid_eq(euid, shp->shm_perm.cuid)) { 1149
1038 err = -EPERM; 1150 memset(&info, 0, sizeof(info));
1039 goto out_unlock0; 1151 info.used_ids = ip->used_ids;
1040 } 1152 info.shm_tot = ip->shm_tot;
1041 if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK)) { 1153 info.shm_rss = ip->shm_rss;
1042 err = -EPERM; 1154 info.shm_swp = ip->shm_swp;
1043 goto out_unlock0; 1155 info.swap_attempts = ip->swap_attempts;
1044 } 1156 info.swap_successes = ip->swap_successes;
1045 } 1157 return copy_to_user(up, &info, sizeof(info));
1158}
1046 1159
1047 shm_file = shp->shm_file; 1160static int copy_compat_shmid_to_user(void __user *buf, struct shmid64_ds *in,
1048 if (is_file_hugepages(shm_file)) 1161 int version)
1049 goto out_unlock0; 1162{
1163 if (version == IPC_64) {
1164 struct compat_shmid64_ds v;
1165 memset(&v, 0, sizeof(v));
1166 to_compat_ipc64_perm(&v.shm_perm, &in->shm_perm);
1167 v.shm_atime = in->shm_atime;
1168 v.shm_dtime = in->shm_dtime;
1169 v.shm_ctime = in->shm_ctime;
1170 v.shm_segsz = in->shm_segsz;
1171 v.shm_nattch = in->shm_nattch;
1172 v.shm_cpid = in->shm_cpid;
1173 v.shm_lpid = in->shm_lpid;
1174 return copy_to_user(buf, &v, sizeof(v));
1175 } else {
1176 struct compat_shmid_ds v;
1177 memset(&v, 0, sizeof(v));
1178 to_compat_ipc_perm(&v.shm_perm, &in->shm_perm);
1179 v.shm_perm.key = in->shm_perm.key;
1180 v.shm_atime = in->shm_atime;
1181 v.shm_dtime = in->shm_dtime;
1182 v.shm_ctime = in->shm_ctime;
1183 v.shm_segsz = in->shm_segsz;
1184 v.shm_nattch = in->shm_nattch;
1185 v.shm_cpid = in->shm_cpid;
1186 v.shm_lpid = in->shm_lpid;
1187 return copy_to_user(buf, &v, sizeof(v));
1188 }
1189}
1050 1190
1051 if (cmd == SHM_LOCK) { 1191static int copy_compat_shmid_from_user(struct shmid64_ds *out, void __user *buf,
1052 struct user_struct *user = current_user(); 1192 int version)
1193{
1194 memset(out, 0, sizeof(*out));
1195 if (version == IPC_64) {
1196 struct compat_shmid64_ds *p = buf;
1197 return get_compat_ipc64_perm(&out->shm_perm, &p->shm_perm);
1198 } else {
1199 struct compat_shmid_ds *p = buf;
1200 return get_compat_ipc_perm(&out->shm_perm, &p->shm_perm);
1201 }
1202}
1053 1203
1054 err = shmem_lock(shm_file, 1, user); 1204COMPAT_SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, void __user *, uptr)
1055 if (!err && !(shp->shm_perm.mode & SHM_LOCKED)) { 1205{
1056 shp->shm_perm.mode |= SHM_LOCKED; 1206 struct ipc_namespace *ns;
1057 shp->mlock_user = user; 1207 struct shmid64_ds sem64;
1058 } 1208 int version = compat_ipc_parse_version(&cmd);
1059 goto out_unlock0; 1209 int err;
1060 }
1061 1210
1062 /* SHM_UNLOCK */ 1211 ns = current->nsproxy->ipc_ns;
1063 if (!(shp->shm_perm.mode & SHM_LOCKED)) 1212
1064 goto out_unlock0; 1213 if (cmd < 0 || shmid < 0)
1065 shmem_lock(shm_file, 0, shp->mlock_user); 1214 return -EINVAL;
1066 shp->shm_perm.mode &= ~SHM_LOCKED;
1067 shp->mlock_user = NULL;
1068 get_file(shm_file);
1069 ipc_unlock_object(&shp->shm_perm);
1070 rcu_read_unlock();
1071 shmem_unlock_mapping(shm_file->f_mapping);
1072 1215
1073 fput(shm_file); 1216 switch (cmd) {
1217 case IPC_INFO: {
1218 struct shminfo64 shminfo;
1219 err = shmctl_ipc_info(ns, &shminfo);
1220 if (err < 0)
1221 return err;
1222 if (copy_compat_shminfo_to_user(uptr, &shminfo, version))
1223 err = -EFAULT;
1224 return err;
1225 }
1226 case SHM_INFO: {
1227 struct shm_info shm_info;
1228 err = shmctl_shm_info(ns, &shm_info);
1229 if (err < 0)
1230 return err;
1231 if (put_compat_shm_info(&shm_info, uptr))
1232 err = -EFAULT;
1074 return err; 1233 return err;
1075 } 1234 }
1235 case IPC_STAT:
1236 case SHM_STAT:
1237 err = shmctl_stat(ns, shmid, cmd, &sem64);
1238 if (err < 0)
1239 return err;
1240 if (copy_compat_shmid_to_user(&sem64, uptr, version))
1241 err = -EFAULT;
1242 return err;
1243
1244 case IPC_SET:
1245 if (copy_compat_shmid_from_user(&sem64, uptr, version))
1246 return -EFAULT;
1247 /* fallthru */
1248 case IPC_RMID:
1249 return shmctl_down(ns, shmid, cmd, &sem64);
1250 case SHM_LOCK:
1251 case SHM_UNLOCK:
1252 return shmctl_do_lock(ns, shmid, cmd);
1253 break;
1076 default: 1254 default:
1077 return -EINVAL; 1255 return -EINVAL;
1078 } 1256 }
1079
1080out_unlock0:
1081 ipc_unlock_object(&shp->shm_perm);
1082out_unlock1:
1083 rcu_read_unlock();
1084 return err; 1257 return err;
1085} 1258}
1259#endif
1086 1260
1087/* 1261/*
1088 * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists. 1262 * Fix shmaddr, allocate descriptor, map shm, add attach descriptor to lists.
@@ -1267,6 +1441,25 @@ SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
1267 return (long)ret; 1441 return (long)ret;
1268} 1442}
1269 1443
1444#ifdef CONFIG_COMPAT
1445
1446#ifndef COMPAT_SHMLBA
1447#define COMPAT_SHMLBA SHMLBA
1448#endif
1449
1450COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
1451{
1452 unsigned long ret;
1453 long err;
1454
1455 err = do_shmat(shmid, compat_ptr(shmaddr), shmflg, &ret, COMPAT_SHMLBA);
1456 if (err)
1457 return err;
1458 force_successful_syscall_return();
1459 return (long)ret;
1460}
1461#endif
1462
1270/* 1463/*
1271 * detach and kill segment if marked destroyed. 1464 * detach and kill segment if marked destroyed.
1272 * The work is done in shm_close. 1465 * The work is done in shm_close.
@@ -1397,7 +1590,7 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
1397 1590
1398 seq_printf(s, 1591 seq_printf(s,
1399 "%10d %10d %4o " SIZE_SPEC " %5u %5u " 1592 "%10d %10d %4o " SIZE_SPEC " %5u %5u "
1400 "%5lu %5u %5u %5u %5u %10lu %10lu %10lu " 1593 "%5lu %5u %5u %5u %5u %10llu %10llu %10llu "
1401 SIZE_SPEC " " SIZE_SPEC "\n", 1594 SIZE_SPEC " " SIZE_SPEC "\n",
1402 shp->shm_perm.key, 1595 shp->shm_perm.key,
1403 shp->shm_perm.id, 1596 shp->shm_perm.id,
diff --git a/ipc/syscall.c b/ipc/syscall.c
index 52429489cde0..667022746ca5 100644
--- a/ipc/syscall.c
+++ b/ipc/syscall.c
@@ -5,12 +5,12 @@
5 * the individual syscalls instead. 5 * the individual syscalls instead.
6 */ 6 */
7#include <linux/unistd.h> 7#include <linux/unistd.h>
8#include <linux/syscalls.h>
8 9
9#ifdef __ARCH_WANT_SYS_IPC 10#ifdef __ARCH_WANT_SYS_IPC
10#include <linux/errno.h> 11#include <linux/errno.h>
11#include <linux/ipc.h> 12#include <linux/ipc.h>
12#include <linux/shm.h> 13#include <linux/shm.h>
13#include <linux/syscalls.h>
14#include <linux/uaccess.h> 14#include <linux/uaccess.h>
15 15
16SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second, 16SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
@@ -97,3 +97,91 @@ SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
97 } 97 }
98} 98}
99#endif 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
108struct compat_ipc_kludge {
109 compat_uptr_t msgp;
110 compat_long_t msgtyp;
111};
112
113#ifdef CONFIG_ARCH_WANT_OLD_COMPAT_IPC
114COMPAT_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
187#endif
diff --git a/ipc/util.h b/ipc/util.h
index 80c9f51c3f07..b21297bc11eb 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -194,4 +194,34 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
194 const struct ipc_ops *ops, struct ipc_params *params); 194 const struct ipc_ops *ops, struct ipc_params *params);
195void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, 195void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
196 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)); 196 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *));
197
198#ifdef CONFIG_COMPAT
199#include <linux/compat.h>
200struct 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
210void to_compat_ipc_perm(struct compat_ipc_perm *, struct ipc64_perm *);
211void to_compat_ipc64_perm(struct compat_ipc64_perm *, struct ipc64_perm *);
212int get_compat_ipc_perm(struct ipc64_perm *, struct compat_ipc_perm __user *);
213int get_compat_ipc64_perm(struct ipc64_perm *,
214 struct compat_ipc64_perm __user *);
215
216static 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#endif 227#endif