diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2017-07-09 08:31:16 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-07-15 20:46:43 -0400 |
commit | 4693916846269d633a3664586650dbfac2c5562f (patch) | |
tree | e7dd196843fc6af4a67b20588403dd696e5262e9 /ipc/msg.c | |
parent | 156d9ed1260ee566f2be09c13254b58247edfb29 (diff) |
msgctl(): move compat to native
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'ipc/msg.c')
-rw-r--r-- | ipc/msg.c | 133 |
1 files changed, 133 insertions, 0 deletions
@@ -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 | |||
572 | struct 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 | |||
588 | static 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 | |||
616 | static 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 | |||
660 | COMPAT_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 | |||
570 | static int testmsg(struct msg_msg *msg, long type, int mode) | 703 | static int testmsg(struct msg_msg *msg, long type, int mode) |
571 | { | 704 | { |
572 | switch (mode) { | 705 | switch (mode) { |