aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-07-09 08:31:16 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2017-07-15 20:46:43 -0400
commit4693916846269d633a3664586650dbfac2c5562f (patch)
treee7dd196843fc6af4a67b20588403dd696e5262e9 /ipc
parent156d9ed1260ee566f2be09c13254b58247edfb29 (diff)
msgctl(): move compat to native
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/compat.c132
-rw-r--r--ipc/msg.c133
2 files changed, 133 insertions, 132 deletions
diff --git a/ipc/compat.c b/ipc/compat.c
index fbfd6fb0a68d..c83099a3b265 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -50,22 +50,6 @@ struct compat_semid_ds {
50 unsigned short sem_nsems; 50 unsigned short sem_nsems;
51}; 51};
52 52
53struct compat_msqid_ds {
54 struct compat_ipc_perm msg_perm;
55 compat_uptr_t msg_first;
56 compat_uptr_t msg_last;
57 compat_time_t msg_stime;
58 compat_time_t msg_rtime;
59 compat_time_t msg_ctime;
60 compat_ulong_t msg_lcbytes;
61 compat_ulong_t msg_lqbytes;
62 unsigned short msg_cbytes;
63 unsigned short msg_qnum;
64 unsigned short msg_qbytes;
65 compat_ipc_pid_t msg_lspid;
66 compat_ipc_pid_t msg_lrpid;
67};
68
69struct compat_ipc_kludge { 53struct compat_ipc_kludge {
70 compat_uptr_t msgp; 54 compat_uptr_t msgp;
71 compat_long_t msgtyp; 55 compat_long_t msgtyp;
@@ -391,122 +375,6 @@ COMPAT_SYSCALL_DEFINE5(msgrcv, int, msqid, compat_uptr_t, msgp,
391 msgflg, compat_do_msg_fill); 375 msgflg, compat_do_msg_fill);
392} 376}
393 377
394static inline int get_compat_msqid64(struct msqid64_ds *m64,
395 struct compat_msqid64_ds __user *up64)
396{
397 int err;
398
399 if (!access_ok(VERIFY_READ, up64, sizeof(*up64)))
400 return -EFAULT;
401 err = __get_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
402 err |= __get_user(m64->msg_qbytes, &up64->msg_qbytes);
403 return err;
404}
405
406static inline int get_compat_msqid(struct msqid64_ds *m,
407 struct compat_msqid_ds __user *up)
408{
409 int err;
410
411 if (!access_ok(VERIFY_READ, up, sizeof(*up)))
412 return -EFAULT;
413 err = __get_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
414 err |= __get_user(m->msg_qbytes, &up->msg_qbytes);
415 return err;
416}
417
418static inline int put_compat_msqid64_ds(struct msqid64_ds *m64,
419 struct compat_msqid64_ds __user *up64)
420{
421 int err;
422
423 if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64)))
424 return -EFAULT;
425 err = __put_compat_ipc64_perm(&m64->msg_perm, &up64->msg_perm);
426 err |= __put_user(m64->msg_stime, &up64->msg_stime);
427 err |= __put_user(m64->msg_rtime, &up64->msg_rtime);
428 err |= __put_user(m64->msg_ctime, &up64->msg_ctime);
429 err |= __put_user(m64->msg_cbytes, &up64->msg_cbytes);
430 err |= __put_user(m64->msg_qnum, &up64->msg_qnum);
431 err |= __put_user(m64->msg_qbytes, &up64->msg_qbytes);
432 err |= __put_user(m64->msg_lspid, &up64->msg_lspid);
433 err |= __put_user(m64->msg_lrpid, &up64->msg_lrpid);
434 return err;
435}
436
437static inline int put_compat_msqid_ds(struct msqid64_ds *m,
438 struct compat_msqid_ds __user *up)
439{
440 int err;
441
442 if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
443 return -EFAULT;
444 err = __put_compat_ipc_perm(&m->msg_perm, &up->msg_perm);
445 err |= __put_user(m->msg_stime, &up->msg_stime);
446 err |= __put_user(m->msg_rtime, &up->msg_rtime);
447 err |= __put_user(m->msg_ctime, &up->msg_ctime);
448 err |= __put_user(m->msg_cbytes, &up->msg_cbytes);
449 err |= __put_user(m->msg_qnum, &up->msg_qnum);
450 err |= __put_user(m->msg_qbytes, &up->msg_qbytes);
451 err |= __put_user(m->msg_lspid, &up->msg_lspid);
452 err |= __put_user(m->msg_lrpid, &up->msg_lrpid);
453 return err;
454}
455
456COMPAT_SYSCALL_DEFINE3(msgctl, int, first, int, second, void __user *, uptr)
457{
458 int err, err2;
459 struct msqid64_ds m64;
460 int version = __compat_ipc_parse_version(&second);
461 void __user *p;
462
463 memset(&m64, 0, sizeof(m64));
464
465 switch (second & (~IPC_64)) {
466 case IPC_INFO:
467 case IPC_RMID:
468 case MSG_INFO:
469 err = sys_msgctl(first, second, uptr);
470 break;
471
472 case IPC_SET:
473 if (version == IPC_64)
474 err = get_compat_msqid64(&m64, uptr);
475 else
476 err = get_compat_msqid(&m64, uptr);
477
478 if (err)
479 break;
480 p = compat_alloc_user_space(sizeof(m64));
481 if (copy_to_user(p, &m64, sizeof(m64)))
482 err = -EFAULT;
483 else
484 err = sys_msgctl(first, second, p);
485 break;
486
487 case IPC_STAT:
488 case MSG_STAT:
489 p = compat_alloc_user_space(sizeof(m64));
490 err = sys_msgctl(first, second, p);
491 if (err < 0)
492 break;
493 if (copy_from_user(&m64, p, sizeof(m64)))
494 err2 = -EFAULT;
495 else if (version == IPC_64)
496 err2 = put_compat_msqid64_ds(&m64, uptr);
497 else
498 err2 = put_compat_msqid_ds(&m64, uptr);
499 if (err2)
500 err = -EFAULT;
501 break;
502
503 default:
504 err = -EINVAL;
505 break;
506 }
507 return err;
508}
509
510COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg) 378COMPAT_SYSCALL_DEFINE3(shmat, int, shmid, compat_uptr_t, shmaddr, int, shmflg)
511{ 379{
512 unsigned long ret; 380 unsigned long ret;
diff --git a/ipc/msg.c b/ipc/msg.c
index 322e7bf8b8d1..3400012e1ce8 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -567,6 +567,139 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
567 } 567 }
568} 568}
569 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 struct compat_ipc64_perm v;
595 if (copy_from_user(&v, &p->msg_perm, sizeof(v)))
596 return -EFAULT;
597 out->msg_perm.uid = v.uid;
598 out->msg_perm.gid = v.gid;
599 out->msg_perm.mode = v.mode;
600 if (get_user(out->msg_qbytes, &p->msg_qbytes))
601 return -EFAULT;
602 } else {
603 struct compat_msqid_ds *p = buf;
604 struct compat_ipc_perm v;
605 if (copy_from_user(&v, &p->msg_perm, sizeof(v)))
606 return -EFAULT;
607 out->msg_perm.uid = v.uid;
608 out->msg_perm.gid = v.gid;
609 out->msg_perm.mode = v.mode;
610 if (get_user(out->msg_qbytes, &p->msg_qbytes))
611 return -EFAULT;
612 }
613 return 0;
614}
615
616static int copy_compat_msqid_to_user(void __user *buf, struct msqid64_ds *in,
617 int version)
618{
619 if (version == IPC_64) {
620 struct compat_msqid64_ds v;
621 memset(&v, 0, sizeof(v));
622 v.msg_perm.key = in->msg_perm.key;
623 v.msg_perm.uid = in->msg_perm.uid;
624 v.msg_perm.gid = in->msg_perm.gid;
625 v.msg_perm.cuid = in->msg_perm.cuid;
626 v.msg_perm.cgid = in->msg_perm.cgid;
627 v.msg_perm.mode = in->msg_perm.mode;
628 v.msg_perm.seq = in->msg_perm.seq;
629 v.msg_stime = in->msg_stime;
630 v.msg_rtime = in->msg_rtime;
631 v.msg_ctime = in->msg_ctime;
632 v.msg_cbytes = in->msg_cbytes;
633 v.msg_qnum = in->msg_qnum;
634 v.msg_qbytes = in->msg_qbytes;
635 v.msg_lspid = in->msg_lspid;
636 v.msg_lrpid = in->msg_lrpid;
637 return copy_to_user(buf, &v, sizeof(v));
638 } else {
639 struct compat_msqid_ds v;
640 memset(&v, 0, sizeof(v));
641 v.msg_perm.key = in->msg_perm.key;
642 SET_UID(v.msg_perm.uid, in->msg_perm.uid);
643 SET_GID(v.msg_perm.gid, in->msg_perm.gid);
644 SET_UID(v.msg_perm.cuid, in->msg_perm.cuid);
645 SET_GID(v.msg_perm.cgid, in->msg_perm.cgid);
646 v.msg_perm.mode = in->msg_perm.mode;
647 v.msg_perm.seq = in->msg_perm.seq;
648 v.msg_stime = in->msg_stime;
649 v.msg_rtime = in->msg_rtime;
650 v.msg_ctime = in->msg_ctime;
651 v.msg_cbytes = in->msg_cbytes;
652 v.msg_qnum = in->msg_qnum;
653 v.msg_qbytes = in->msg_qbytes;
654 v.msg_lspid = in->msg_lspid;
655 v.msg_lrpid = in->msg_lrpid;
656 return copy_to_user(buf, &v, sizeof(v));
657 }
658}
659
660COMPAT_SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, void __user *, uptr)
661{
662 struct ipc_namespace *ns;
663 int err;
664 struct msqid64_ds msqid64;
665 int version = compat_ipc_parse_version(&cmd);
666
667 ns = current->nsproxy->ipc_ns;
668
669 if (msqid < 0 || cmd < 0)
670 return -EINVAL;
671
672 switch (cmd & (~IPC_64)) {
673 case IPC_INFO:
674 case MSG_INFO: {
675 struct msginfo msginfo;
676 err = msgctl_info(ns, msqid, cmd, &msginfo);
677 if (err < 0)
678 return err;
679 if (copy_to_user(uptr, &msginfo, sizeof(struct msginfo)))
680 err = -EFAULT;
681 return err;
682 }
683 case IPC_STAT:
684 case MSG_STAT:
685 err = msgctl_stat(ns, msqid, cmd, &msqid64);
686 if (err < 0)
687 return err;
688 if (copy_compat_msqid_to_user(uptr, &msqid64, version))
689 err = -EFAULT;
690 return err;
691 case IPC_SET:
692 if (copy_compat_msqid_from_user(&msqid64, uptr, version))
693 return -EFAULT;
694 /* fallthru */
695 case IPC_RMID:
696 return msgctl_down(ns, msqid, cmd, &msqid64);
697 default:
698 return -EINVAL;
699 }
700}
701#endif
702
570static int testmsg(struct msg_msg *msg, long type, int mode) 703static int testmsg(struct msg_msg *msg, long type, int mode)
571{ 704{
572 switch (mode) { 705 switch (mode) {