diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/mqueue.c | 97 | ||||
-rw-r--r-- | ipc/sem.c | 2 | ||||
-rw-r--r-- | ipc/shm.c | 4 | ||||
-rw-r--r-- | ipc/util.c | 18 |
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 | ||
526 | static long prepare_timeout(const struct timespec __user *u_arg) | 526 | static 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 | */ |
593 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, | 589 | static 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(¬ification, u_notification, | 1011 | if (copy_from_user(¬ification, 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 ? ¬ification : 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 |
@@ -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 | * |
@@ -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) | |||
624 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) | 624 | int 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; |
823 | out_unlock: | ||
824 | ipc_unlock(ipcp); | 816 | ipc_unlock(ipcp); |
825 | out_up: | 817 | out_up: |
826 | up_write(&ids->rw_mutex); | 818 | up_write(&ids->rw_mutex); |