aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/mqueue.c97
-rw-r--r--ipc/sem.c2
-rw-r--r--ipc/shm.c4
-rw-r--r--ipc/util.c18
4 files changed, 56 insertions, 65 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 41b72f02fa70..eddb6247a553 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -523,31 +523,27 @@ static void __do_notify(struct mqueue_inode_info *info)
523 wake_up(&info->wait_q); 523 wake_up(&info->wait_q);
524} 524}
525 525
526static long prepare_timeout(const struct timespec __user *u_arg) 526static long prepare_timeout(struct timespec *p)
527{ 527{
528 struct timespec ts, nowts; 528 struct timespec nowts;
529 long timeout; 529 long timeout;
530 530
531 if (u_arg) { 531 if (p) {
532 if (unlikely(copy_from_user(&ts, u_arg, 532 if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0
533 sizeof(struct timespec)))) 533 || p->tv_nsec >= NSEC_PER_SEC))
534 return -EFAULT;
535
536 if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0
537 || ts.tv_nsec >= NSEC_PER_SEC))
538 return -EINVAL; 534 return -EINVAL;
539 nowts = CURRENT_TIME; 535 nowts = CURRENT_TIME;
540 /* first subtract as jiffies can't be too big */ 536 /* first subtract as jiffies can't be too big */
541 ts.tv_sec -= nowts.tv_sec; 537 p->tv_sec -= nowts.tv_sec;
542 if (ts.tv_nsec < nowts.tv_nsec) { 538 if (p->tv_nsec < nowts.tv_nsec) {
543 ts.tv_nsec += NSEC_PER_SEC; 539 p->tv_nsec += NSEC_PER_SEC;
544 ts.tv_sec--; 540 p->tv_sec--;
545 } 541 }
546 ts.tv_nsec -= nowts.tv_nsec; 542 p->tv_nsec -= nowts.tv_nsec;
547 if (ts.tv_sec < 0) 543 if (p->tv_sec < 0)
548 return 0; 544 return 0;
549 545
550 timeout = timespec_to_jiffies(&ts) + 1; 546 timeout = timespec_to_jiffies(p) + 1;
551 } else 547 } else
552 return MAX_SCHEDULE_TIMEOUT; 548 return MAX_SCHEDULE_TIMEOUT;
553 549
@@ -591,22 +587,18 @@ static int mq_attr_ok(struct mq_attr *attr)
591 * Invoked when creating a new queue via sys_mq_open 587 * Invoked when creating a new queue via sys_mq_open
592 */ 588 */
593static struct file *do_create(struct dentry *dir, struct dentry *dentry, 589static struct file *do_create(struct dentry *dir, struct dentry *dentry,
594 int oflag, mode_t mode, struct mq_attr __user *u_attr) 590 int oflag, mode_t mode, struct mq_attr *attr)
595{ 591{
596 const struct cred *cred = current_cred(); 592 const struct cred *cred = current_cred();
597 struct mq_attr attr;
598 struct file *result; 593 struct file *result;
599 int ret; 594 int ret;
600 595
601 if (u_attr) { 596 if (attr) {
602 ret = -EFAULT;
603 if (copy_from_user(&attr, u_attr, sizeof(attr)))
604 goto out;
605 ret = -EINVAL; 597 ret = -EINVAL;
606 if (!mq_attr_ok(&attr)) 598 if (!mq_attr_ok(attr))
607 goto out; 599 goto out;
608 /* store for use during create */ 600 /* store for use during create */
609 dentry->d_fsdata = &attr; 601 dentry->d_fsdata = attr;
610 } 602 }
611 603
612 mode &= ~current->fs->umask; 604 mode &= ~current->fs->umask;
@@ -663,11 +655,13 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
663 struct dentry *dentry; 655 struct dentry *dentry;
664 struct file *filp; 656 struct file *filp;
665 char *name; 657 char *name;
658 struct mq_attr attr;
666 int fd, error; 659 int fd, error;
667 660
668 error = audit_mq_open(oflag, mode, u_attr); 661 if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
669 if (error != 0) 662 return -EFAULT;
670 return error; 663
664 audit_mq_open(oflag, mode, u_attr ? &attr : NULL);
671 665
672 if (IS_ERR(name = getname(u_name))) 666 if (IS_ERR(name = getname(u_name)))
673 return PTR_ERR(name); 667 return PTR_ERR(name);
@@ -693,7 +687,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
693 filp = do_open(dentry, oflag); 687 filp = do_open(dentry, oflag);
694 } else { 688 } else {
695 filp = do_create(mqueue_mnt->mnt_root, dentry, 689 filp = do_create(mqueue_mnt->mnt_root, dentry,
696 oflag, mode, u_attr); 690 oflag, mode,
691 u_attr ? &attr : NULL);
697 } 692 }
698 } else { 693 } else {
699 error = -ENOENT; 694 error = -ENOENT;
@@ -828,17 +823,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
828 struct ext_wait_queue *receiver; 823 struct ext_wait_queue *receiver;
829 struct msg_msg *msg_ptr; 824 struct msg_msg *msg_ptr;
830 struct mqueue_inode_info *info; 825 struct mqueue_inode_info *info;
826 struct timespec ts, *p = NULL;
831 long timeout; 827 long timeout;
832 int ret; 828 int ret;
833 829
834 ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); 830 if (u_abs_timeout) {
835 if (ret != 0) 831 if (copy_from_user(&ts, u_abs_timeout,
836 return ret; 832 sizeof(struct timespec)))
833 return -EFAULT;
834 p = &ts;
835 }
837 836
838 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) 837 if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
839 return -EINVAL; 838 return -EINVAL;
840 839
841 timeout = prepare_timeout(u_abs_timeout); 840 audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
841 timeout = prepare_timeout(p);
842 842
843 ret = -EBADF; 843 ret = -EBADF;
844 filp = fget(mqdes); 844 filp = fget(mqdes);
@@ -917,12 +917,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
917 struct inode *inode; 917 struct inode *inode;
918 struct mqueue_inode_info *info; 918 struct mqueue_inode_info *info;
919 struct ext_wait_queue wait; 919 struct ext_wait_queue wait;
920 struct timespec ts, *p = NULL;
920 921
921 ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); 922 if (u_abs_timeout) {
922 if (ret != 0) 923 if (copy_from_user(&ts, u_abs_timeout,
923 return ret; 924 sizeof(struct timespec)))
925 return -EFAULT;
926 p = &ts;
927 }
924 928
925 timeout = prepare_timeout(u_abs_timeout); 929 audit_mq_sendrecv(mqdes, msg_len, 0, p);
930 timeout = prepare_timeout(p);
926 931
927 ret = -EBADF; 932 ret = -EBADF;
928 filp = fget(mqdes); 933 filp = fget(mqdes);
@@ -1002,17 +1007,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes,
1002 struct mqueue_inode_info *info; 1007 struct mqueue_inode_info *info;
1003 struct sk_buff *nc; 1008 struct sk_buff *nc;
1004 1009
1005 ret = audit_mq_notify(mqdes, u_notification); 1010 if (u_notification) {
1006 if (ret != 0)
1007 return ret;
1008
1009 nc = NULL;
1010 sock = NULL;
1011 if (u_notification != NULL) {
1012 if (copy_from_user(&notification, u_notification, 1011 if (copy_from_user(&notification, u_notification,
1013 sizeof(struct sigevent))) 1012 sizeof(struct sigevent)))
1014 return -EFAULT; 1013 return -EFAULT;
1014 }
1015 1015
1016 audit_mq_notify(mqdes, u_notification ? &notification : NULL);
1017
1018 nc = NULL;
1019 sock = NULL;
1020 if (u_notification != NULL) {
1016 if (unlikely(notification.sigev_notify != SIGEV_NONE && 1021 if (unlikely(notification.sigev_notify != SIGEV_NONE &&
1017 notification.sigev_notify != SIGEV_SIGNAL && 1022 notification.sigev_notify != SIGEV_SIGNAL &&
1018 notification.sigev_notify != SIGEV_THREAD)) 1023 notification.sigev_notify != SIGEV_THREAD))
@@ -1149,11 +1154,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
1149 omqstat = info->attr; 1154 omqstat = info->attr;
1150 omqstat.mq_flags = filp->f_flags & O_NONBLOCK; 1155 omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
1151 if (u_mqstat) { 1156 if (u_mqstat) {
1152 ret = audit_mq_getsetattr(mqdes, &mqstat); 1157 audit_mq_getsetattr(mqdes, &mqstat);
1153 if (ret != 0) {
1154 spin_unlock(&info->lock);
1155 goto out_fput;
1156 }
1157 if (mqstat.mq_flags & O_NONBLOCK) 1158 if (mqstat.mq_flags & O_NONBLOCK)
1158 filp->f_flags |= O_NONBLOCK; 1159 filp->f_flags |= O_NONBLOCK;
1159 else 1160 else
diff --git a/ipc/sem.c b/ipc/sem.c
index 082122469b17..fea0ad3aed7b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -58,7 +58,7 @@
58 * SMP-threaded, sysctl's added 58 * SMP-threaded, sysctl's added
59 * (c) 1999 Manfred Spraul <manfred@colorfullife.com> 59 * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
60 * Enforced range limit on SEM_UNDO 60 * Enforced range limit on SEM_UNDO
61 * (c) 2001 Red Hat Inc <alan@redhat.com> 61 * (c) 2001 Red Hat Inc
62 * Lockless wakeup 62 * Lockless wakeup
63 * (c) 2003 Manfred Spraul <manfred@colorfullife.com> 63 * (c) 2003 Manfred Spraul <manfred@colorfullife.com>
64 * 64 *
diff --git a/ipc/shm.c b/ipc/shm.c
index 38a055758a9b..57dd50046cef 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -747,9 +747,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf)
747 goto out; 747 goto out;
748 } 748 }
749 749
750 err = audit_ipc_obj(&(shp->shm_perm)); 750 audit_ipc_obj(&(shp->shm_perm));
751 if (err)
752 goto out_unlock;
753 751
754 if (!capable(CAP_IPC_LOCK)) { 752 if (!capable(CAP_IPC_LOCK)) {
755 uid_t euid = current_euid(); 753 uid_t euid = current_euid();
diff --git a/ipc/util.c b/ipc/util.c
index 5a1808c774a2..7585a72e259b 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -624,10 +624,9 @@ void ipc_rcu_putref(void *ptr)
624int ipcperms (struct kern_ipc_perm *ipcp, short flag) 624int ipcperms (struct kern_ipc_perm *ipcp, short flag)
625{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ 625{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
626 uid_t euid = current_euid(); 626 uid_t euid = current_euid();
627 int requested_mode, granted_mode, err; 627 int requested_mode, granted_mode;
628 628
629 if (unlikely((err = audit_ipc_obj(ipcp)))) 629 audit_ipc_obj(ipcp);
630 return err;
631 requested_mode = (flag >> 6) | (flag >> 3) | flag; 630 requested_mode = (flag >> 6) | (flag >> 3) | flag;
632 granted_mode = ipcp->mode; 631 granted_mode = ipcp->mode;
633 if (euid == ipcp->cuid || 632 if (euid == ipcp->cuid ||
@@ -803,16 +802,10 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
803 goto out_up; 802 goto out_up;
804 } 803 }
805 804
806 err = audit_ipc_obj(ipcp); 805 audit_ipc_obj(ipcp);
807 if (err) 806 if (cmd == IPC_SET)
808 goto out_unlock; 807 audit_ipc_set_perm(extra_perm, perm->uid,
809
810 if (cmd == IPC_SET) {
811 err = audit_ipc_set_perm(extra_perm, perm->uid,
812 perm->gid, perm->mode); 808 perm->gid, perm->mode);
813 if (err)
814 goto out_unlock;
815 }
816 809
817 euid = current_euid(); 810 euid = current_euid();
818 if (euid == ipcp->cuid || 811 if (euid == ipcp->cuid ||
@@ -820,7 +813,6 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,
820 return ipcp; 813 return ipcp;
821 814
822 err = -EPERM; 815 err = -EPERM;
823out_unlock:
824 ipc_unlock(ipcp); 816 ipc_unlock(ipcp);
825out_up: 817out_up:
826 up_write(&ids->rw_mutex); 818 up_write(&ids->rw_mutex);