diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/ipc_sysctl.c | 46 | ||||
-rw-r--r-- | ipc/mqueue.c | 148 | ||||
-rw-r--r-- | ipc/msg.c | 12 | ||||
-rw-r--r-- | ipc/sem.c | 21 | ||||
-rw-r--r-- | ipc/shm.c | 48 | ||||
-rw-r--r-- | ipc/util.c | 36 |
6 files changed, 164 insertions, 147 deletions
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 0dfebc509426..4a7a12c95abe 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c | |||
@@ -26,29 +26,6 @@ static void *get_ipc(ctl_table *table) | |||
26 | return which; | 26 | return which; |
27 | } | 27 | } |
28 | 28 | ||
29 | /* | ||
30 | * Routine that is called when the file "auto_msgmni" has successfully been | ||
31 | * written. | ||
32 | * Two values are allowed: | ||
33 | * 0: unregister msgmni's callback routine from the ipc namespace notifier | ||
34 | * chain. This means that msgmni won't be recomputed anymore upon memory | ||
35 | * add/remove or ipc namespace creation/removal. | ||
36 | * 1: register back the callback routine. | ||
37 | */ | ||
38 | static void ipc_auto_callback(int val) | ||
39 | { | ||
40 | if (!val) | ||
41 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); | ||
42 | else { | ||
43 | /* | ||
44 | * Re-enable automatic recomputing only if not already | ||
45 | * enabled. | ||
46 | */ | ||
47 | recompute_msgmni(current->nsproxy->ipc_ns); | ||
48 | cond_register_ipcns_notifier(current->nsproxy->ipc_ns); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | #ifdef CONFIG_PROC_FS | 29 | #ifdef CONFIG_PROC_FS |
53 | static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, | 30 | static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, |
54 | void __user *buffer, size_t *lenp, loff_t *ppos) | 31 | void __user *buffer, size_t *lenp, loff_t *ppos) |
@@ -94,6 +71,29 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, | |||
94 | lenp, ppos); | 71 | lenp, ppos); |
95 | } | 72 | } |
96 | 73 | ||
74 | /* | ||
75 | * Routine that is called when the file "auto_msgmni" has successfully been | ||
76 | * written. | ||
77 | * Two values are allowed: | ||
78 | * 0: unregister msgmni's callback routine from the ipc namespace notifier | ||
79 | * chain. This means that msgmni won't be recomputed anymore upon memory | ||
80 | * add/remove or ipc namespace creation/removal. | ||
81 | * 1: register back the callback routine. | ||
82 | */ | ||
83 | static void ipc_auto_callback(int val) | ||
84 | { | ||
85 | if (!val) | ||
86 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); | ||
87 | else { | ||
88 | /* | ||
89 | * Re-enable automatic recomputing only if not already | ||
90 | * enabled. | ||
91 | */ | ||
92 | recompute_msgmni(current->nsproxy->ipc_ns); | ||
93 | cond_register_ipcns_notifier(current->nsproxy->ipc_ns); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, | 97 | static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, |
98 | struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) | 98 | struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) |
99 | { | 99 | { |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 68eb857cfdea..54b4077fed79 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -112,21 +112,20 @@ static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode) | |||
112 | static struct inode *mqueue_get_inode(struct super_block *sb, int mode, | 112 | static struct inode *mqueue_get_inode(struct super_block *sb, int mode, |
113 | struct mq_attr *attr) | 113 | struct mq_attr *attr) |
114 | { | 114 | { |
115 | struct user_struct *u = current_user(); | ||
115 | struct inode *inode; | 116 | struct inode *inode; |
116 | 117 | ||
117 | inode = new_inode(sb); | 118 | inode = new_inode(sb); |
118 | if (inode) { | 119 | if (inode) { |
119 | inode->i_mode = mode; | 120 | inode->i_mode = mode; |
120 | inode->i_uid = current->fsuid; | 121 | inode->i_uid = current_fsuid(); |
121 | inode->i_gid = current->fsgid; | 122 | inode->i_gid = current_fsgid(); |
122 | inode->i_blocks = 0; | ||
123 | inode->i_mtime = inode->i_ctime = inode->i_atime = | 123 | inode->i_mtime = inode->i_ctime = inode->i_atime = |
124 | CURRENT_TIME; | 124 | CURRENT_TIME; |
125 | 125 | ||
126 | if (S_ISREG(mode)) { | 126 | if (S_ISREG(mode)) { |
127 | struct mqueue_inode_info *info; | 127 | struct mqueue_inode_info *info; |
128 | struct task_struct *p = current; | 128 | struct task_struct *p = current; |
129 | struct user_struct *u = p->user; | ||
130 | unsigned long mq_bytes, mq_msg_tblsz; | 129 | unsigned long mq_bytes, mq_msg_tblsz; |
131 | 130 | ||
132 | inode->i_fop = &mqueue_file_operations; | 131 | inode->i_fop = &mqueue_file_operations; |
@@ -506,8 +505,9 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
506 | sig_i.si_errno = 0; | 505 | sig_i.si_errno = 0; |
507 | sig_i.si_code = SI_MESGQ; | 506 | sig_i.si_code = SI_MESGQ; |
508 | sig_i.si_value = info->notify.sigev_value; | 507 | sig_i.si_value = info->notify.sigev_value; |
509 | sig_i.si_pid = task_tgid_vnr(current); | 508 | sig_i.si_pid = task_tgid_nr_ns(current, |
510 | sig_i.si_uid = current->uid; | 509 | ns_of_pid(info->notify_owner)); |
510 | sig_i.si_uid = current_uid(); | ||
511 | 511 | ||
512 | kill_pid_info(info->notify.sigev_signo, | 512 | kill_pid_info(info->notify.sigev_signo, |
513 | &sig_i, info->notify_owner); | 513 | &sig_i, info->notify_owner); |
@@ -524,31 +524,27 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
524 | wake_up(&info->wait_q); | 524 | wake_up(&info->wait_q); |
525 | } | 525 | } |
526 | 526 | ||
527 | static long prepare_timeout(const struct timespec __user *u_arg) | 527 | static long prepare_timeout(struct timespec *p) |
528 | { | 528 | { |
529 | struct timespec ts, nowts; | 529 | struct timespec nowts; |
530 | long timeout; | 530 | long timeout; |
531 | 531 | ||
532 | if (u_arg) { | 532 | if (p) { |
533 | if (unlikely(copy_from_user(&ts, u_arg, | 533 | if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0 |
534 | sizeof(struct timespec)))) | 534 | || p->tv_nsec >= NSEC_PER_SEC)) |
535 | return -EFAULT; | ||
536 | |||
537 | if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0 | ||
538 | || ts.tv_nsec >= NSEC_PER_SEC)) | ||
539 | return -EINVAL; | 535 | return -EINVAL; |
540 | nowts = CURRENT_TIME; | 536 | nowts = CURRENT_TIME; |
541 | /* first subtract as jiffies can't be too big */ | 537 | /* first subtract as jiffies can't be too big */ |
542 | ts.tv_sec -= nowts.tv_sec; | 538 | p->tv_sec -= nowts.tv_sec; |
543 | if (ts.tv_nsec < nowts.tv_nsec) { | 539 | if (p->tv_nsec < nowts.tv_nsec) { |
544 | ts.tv_nsec += NSEC_PER_SEC; | 540 | p->tv_nsec += NSEC_PER_SEC; |
545 | ts.tv_sec--; | 541 | p->tv_sec--; |
546 | } | 542 | } |
547 | ts.tv_nsec -= nowts.tv_nsec; | 543 | p->tv_nsec -= nowts.tv_nsec; |
548 | if (ts.tv_sec < 0) | 544 | if (p->tv_sec < 0) |
549 | return 0; | 545 | return 0; |
550 | 546 | ||
551 | timeout = timespec_to_jiffies(&ts) + 1; | 547 | timeout = timespec_to_jiffies(p) + 1; |
552 | } else | 548 | } else |
553 | return MAX_SCHEDULE_TIMEOUT; | 549 | return MAX_SCHEDULE_TIMEOUT; |
554 | 550 | ||
@@ -592,21 +588,18 @@ static int mq_attr_ok(struct mq_attr *attr) | |||
592 | * Invoked when creating a new queue via sys_mq_open | 588 | * Invoked when creating a new queue via sys_mq_open |
593 | */ | 589 | */ |
594 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, | 590 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, |
595 | int oflag, mode_t mode, struct mq_attr __user *u_attr) | 591 | int oflag, mode_t mode, struct mq_attr *attr) |
596 | { | 592 | { |
597 | struct mq_attr attr; | 593 | const struct cred *cred = current_cred(); |
598 | struct file *result; | 594 | struct file *result; |
599 | int ret; | 595 | int ret; |
600 | 596 | ||
601 | if (u_attr) { | 597 | if (attr) { |
602 | ret = -EFAULT; | ||
603 | if (copy_from_user(&attr, u_attr, sizeof(attr))) | ||
604 | goto out; | ||
605 | ret = -EINVAL; | 598 | ret = -EINVAL; |
606 | if (!mq_attr_ok(&attr)) | 599 | if (!mq_attr_ok(attr)) |
607 | goto out; | 600 | goto out; |
608 | /* store for use during create */ | 601 | /* store for use during create */ |
609 | dentry->d_fsdata = &attr; | 602 | dentry->d_fsdata = attr; |
610 | } | 603 | } |
611 | 604 | ||
612 | mode &= ~current->fs->umask; | 605 | mode &= ~current->fs->umask; |
@@ -618,7 +611,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, | |||
618 | if (ret) | 611 | if (ret) |
619 | goto out_drop_write; | 612 | goto out_drop_write; |
620 | 613 | ||
621 | result = dentry_open(dentry, mqueue_mnt, oflag); | 614 | result = dentry_open(dentry, mqueue_mnt, oflag, cred); |
622 | /* | 615 | /* |
623 | * dentry_open() took a persistent mnt_want_write(), | 616 | * dentry_open() took a persistent mnt_want_write(), |
624 | * so we can now drop this one. | 617 | * so we can now drop this one. |
@@ -637,8 +630,10 @@ out: | |||
637 | /* Opens existing queue */ | 630 | /* Opens existing queue */ |
638 | static struct file *do_open(struct dentry *dentry, int oflag) | 631 | static struct file *do_open(struct dentry *dentry, int oflag) |
639 | { | 632 | { |
640 | static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | 633 | const struct cred *cred = current_cred(); |
641 | MAY_READ | MAY_WRITE }; | 634 | |
635 | static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | ||
636 | MAY_READ | MAY_WRITE }; | ||
642 | 637 | ||
643 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { | 638 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { |
644 | dput(dentry); | 639 | dput(dentry); |
@@ -652,20 +647,22 @@ static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | |||
652 | return ERR_PTR(-EACCES); | 647 | return ERR_PTR(-EACCES); |
653 | } | 648 | } |
654 | 649 | ||
655 | return dentry_open(dentry, mqueue_mnt, oflag); | 650 | return dentry_open(dentry, mqueue_mnt, oflag, cred); |
656 | } | 651 | } |
657 | 652 | ||
658 | asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | 653 | SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, |
659 | struct mq_attr __user *u_attr) | 654 | struct mq_attr __user *, u_attr) |
660 | { | 655 | { |
661 | struct dentry *dentry; | 656 | struct dentry *dentry; |
662 | struct file *filp; | 657 | struct file *filp; |
663 | char *name; | 658 | char *name; |
659 | struct mq_attr attr; | ||
664 | int fd, error; | 660 | int fd, error; |
665 | 661 | ||
666 | error = audit_mq_open(oflag, mode, u_attr); | 662 | if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) |
667 | if (error != 0) | 663 | return -EFAULT; |
668 | return error; | 664 | |
665 | audit_mq_open(oflag, mode, u_attr ? &attr : NULL); | ||
669 | 666 | ||
670 | if (IS_ERR(name = getname(u_name))) | 667 | if (IS_ERR(name = getname(u_name))) |
671 | return PTR_ERR(name); | 668 | return PTR_ERR(name); |
@@ -691,7 +688,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | |||
691 | filp = do_open(dentry, oflag); | 688 | filp = do_open(dentry, oflag); |
692 | } else { | 689 | } else { |
693 | filp = do_create(mqueue_mnt->mnt_root, dentry, | 690 | filp = do_create(mqueue_mnt->mnt_root, dentry, |
694 | oflag, mode, u_attr); | 691 | oflag, mode, |
692 | u_attr ? &attr : NULL); | ||
695 | } | 693 | } |
696 | } else { | 694 | } else { |
697 | error = -ENOENT; | 695 | error = -ENOENT; |
@@ -723,7 +721,7 @@ out_putname: | |||
723 | return fd; | 721 | return fd; |
724 | } | 722 | } |
725 | 723 | ||
726 | asmlinkage long sys_mq_unlink(const char __user *u_name) | 724 | SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) |
727 | { | 725 | { |
728 | int err; | 726 | int err; |
729 | char *name; | 727 | char *name; |
@@ -816,9 +814,9 @@ static inline void pipelined_receive(struct mqueue_inode_info *info) | |||
816 | sender->state = STATE_READY; | 814 | sender->state = STATE_READY; |
817 | } | 815 | } |
818 | 816 | ||
819 | asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, | 817 | SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, |
820 | size_t msg_len, unsigned int msg_prio, | 818 | size_t, msg_len, unsigned int, msg_prio, |
821 | const struct timespec __user *u_abs_timeout) | 819 | const struct timespec __user *, u_abs_timeout) |
822 | { | 820 | { |
823 | struct file *filp; | 821 | struct file *filp; |
824 | struct inode *inode; | 822 | struct inode *inode; |
@@ -826,17 +824,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, | |||
826 | struct ext_wait_queue *receiver; | 824 | struct ext_wait_queue *receiver; |
827 | struct msg_msg *msg_ptr; | 825 | struct msg_msg *msg_ptr; |
828 | struct mqueue_inode_info *info; | 826 | struct mqueue_inode_info *info; |
827 | struct timespec ts, *p = NULL; | ||
829 | long timeout; | 828 | long timeout; |
830 | int ret; | 829 | int ret; |
831 | 830 | ||
832 | ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); | 831 | if (u_abs_timeout) { |
833 | if (ret != 0) | 832 | if (copy_from_user(&ts, u_abs_timeout, |
834 | return ret; | 833 | sizeof(struct timespec))) |
834 | return -EFAULT; | ||
835 | p = &ts; | ||
836 | } | ||
835 | 837 | ||
836 | if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) | 838 | if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) |
837 | return -EINVAL; | 839 | return -EINVAL; |
838 | 840 | ||
839 | timeout = prepare_timeout(u_abs_timeout); | 841 | audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); |
842 | timeout = prepare_timeout(p); | ||
840 | 843 | ||
841 | ret = -EBADF; | 844 | ret = -EBADF; |
842 | filp = fget(mqdes); | 845 | filp = fget(mqdes); |
@@ -904,9 +907,9 @@ out: | |||
904 | return ret; | 907 | return ret; |
905 | } | 908 | } |
906 | 909 | ||
907 | asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, | 910 | SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, |
908 | size_t msg_len, unsigned int __user *u_msg_prio, | 911 | size_t, msg_len, unsigned int __user *, u_msg_prio, |
909 | const struct timespec __user *u_abs_timeout) | 912 | const struct timespec __user *, u_abs_timeout) |
910 | { | 913 | { |
911 | long timeout; | 914 | long timeout; |
912 | ssize_t ret; | 915 | ssize_t ret; |
@@ -915,12 +918,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, | |||
915 | struct inode *inode; | 918 | struct inode *inode; |
916 | struct mqueue_inode_info *info; | 919 | struct mqueue_inode_info *info; |
917 | struct ext_wait_queue wait; | 920 | struct ext_wait_queue wait; |
921 | struct timespec ts, *p = NULL; | ||
918 | 922 | ||
919 | ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); | 923 | if (u_abs_timeout) { |
920 | if (ret != 0) | 924 | if (copy_from_user(&ts, u_abs_timeout, |
921 | return ret; | 925 | sizeof(struct timespec))) |
926 | return -EFAULT; | ||
927 | p = &ts; | ||
928 | } | ||
922 | 929 | ||
923 | timeout = prepare_timeout(u_abs_timeout); | 930 | audit_mq_sendrecv(mqdes, msg_len, 0, p); |
931 | timeout = prepare_timeout(p); | ||
924 | 932 | ||
925 | ret = -EBADF; | 933 | ret = -EBADF; |
926 | filp = fget(mqdes); | 934 | filp = fget(mqdes); |
@@ -989,8 +997,8 @@ out: | |||
989 | * and he isn't currently owner of notification, will be silently discarded. | 997 | * and he isn't currently owner of notification, will be silently discarded. |
990 | * It isn't explicitly defined in the POSIX. | 998 | * It isn't explicitly defined in the POSIX. |
991 | */ | 999 | */ |
992 | asmlinkage long sys_mq_notify(mqd_t mqdes, | 1000 | SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes, |
993 | const struct sigevent __user *u_notification) | 1001 | const struct sigevent __user *, u_notification) |
994 | { | 1002 | { |
995 | int ret; | 1003 | int ret; |
996 | struct file *filp; | 1004 | struct file *filp; |
@@ -1000,17 +1008,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes, | |||
1000 | struct mqueue_inode_info *info; | 1008 | struct mqueue_inode_info *info; |
1001 | struct sk_buff *nc; | 1009 | struct sk_buff *nc; |
1002 | 1010 | ||
1003 | ret = audit_mq_notify(mqdes, u_notification); | 1011 | if (u_notification) { |
1004 | if (ret != 0) | ||
1005 | return ret; | ||
1006 | |||
1007 | nc = NULL; | ||
1008 | sock = NULL; | ||
1009 | if (u_notification != NULL) { | ||
1010 | if (copy_from_user(¬ification, u_notification, | 1012 | if (copy_from_user(¬ification, u_notification, |
1011 | sizeof(struct sigevent))) | 1013 | sizeof(struct sigevent))) |
1012 | return -EFAULT; | 1014 | return -EFAULT; |
1015 | } | ||
1013 | 1016 | ||
1017 | audit_mq_notify(mqdes, u_notification ? ¬ification : NULL); | ||
1018 | |||
1019 | nc = NULL; | ||
1020 | sock = NULL; | ||
1021 | if (u_notification != NULL) { | ||
1014 | if (unlikely(notification.sigev_notify != SIGEV_NONE && | 1022 | if (unlikely(notification.sigev_notify != SIGEV_NONE && |
1015 | notification.sigev_notify != SIGEV_SIGNAL && | 1023 | notification.sigev_notify != SIGEV_SIGNAL && |
1016 | notification.sigev_notify != SIGEV_THREAD)) | 1024 | notification.sigev_notify != SIGEV_THREAD)) |
@@ -1115,9 +1123,9 @@ out: | |||
1115 | return ret; | 1123 | return ret; |
1116 | } | 1124 | } |
1117 | 1125 | ||
1118 | asmlinkage long sys_mq_getsetattr(mqd_t mqdes, | 1126 | SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes, |
1119 | const struct mq_attr __user *u_mqstat, | 1127 | const struct mq_attr __user *, u_mqstat, |
1120 | struct mq_attr __user *u_omqstat) | 1128 | struct mq_attr __user *, u_omqstat) |
1121 | { | 1129 | { |
1122 | int ret; | 1130 | int ret; |
1123 | struct mq_attr mqstat, omqstat; | 1131 | struct mq_attr mqstat, omqstat; |
@@ -1147,11 +1155,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, | |||
1147 | omqstat = info->attr; | 1155 | omqstat = info->attr; |
1148 | omqstat.mq_flags = filp->f_flags & O_NONBLOCK; | 1156 | omqstat.mq_flags = filp->f_flags & O_NONBLOCK; |
1149 | if (u_mqstat) { | 1157 | if (u_mqstat) { |
1150 | ret = audit_mq_getsetattr(mqdes, &mqstat); | 1158 | audit_mq_getsetattr(mqdes, &mqstat); |
1151 | if (ret != 0) { | ||
1152 | spin_unlock(&info->lock); | ||
1153 | goto out_fput; | ||
1154 | } | ||
1155 | if (mqstat.mq_flags & O_NONBLOCK) | 1159 | if (mqstat.mq_flags & O_NONBLOCK) |
1156 | filp->f_flags |= O_NONBLOCK; | 1160 | filp->f_flags |= O_NONBLOCK; |
1157 | else | 1161 | else |
@@ -309,7 +309,7 @@ static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg) | |||
309 | return security_msg_queue_associate(msq, msgflg); | 309 | return security_msg_queue_associate(msq, msgflg); |
310 | } | 310 | } |
311 | 311 | ||
312 | asmlinkage long sys_msgget(key_t key, int msgflg) | 312 | SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg) |
313 | { | 313 | { |
314 | struct ipc_namespace *ns; | 314 | struct ipc_namespace *ns; |
315 | struct ipc_ops msg_ops; | 315 | struct ipc_ops msg_ops; |
@@ -466,7 +466,7 @@ out_up: | |||
466 | return err; | 466 | return err; |
467 | } | 467 | } |
468 | 468 | ||
469 | asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) | 469 | SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf) |
470 | { | 470 | { |
471 | struct msg_queue *msq; | 471 | struct msg_queue *msq; |
472 | int err, version; | 472 | int err, version; |
@@ -723,8 +723,8 @@ out_free: | |||
723 | return err; | 723 | return err; |
724 | } | 724 | } |
725 | 725 | ||
726 | asmlinkage long | 726 | SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, |
727 | sys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, int msgflg) | 727 | int, msgflg) |
728 | { | 728 | { |
729 | long mtype; | 729 | long mtype; |
730 | 730 | ||
@@ -904,8 +904,8 @@ out_unlock: | |||
904 | return msgsz; | 904 | return msgsz; |
905 | } | 905 | } |
906 | 906 | ||
907 | asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, | 907 | SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, |
908 | long msgtyp, int msgflg) | 908 | long, msgtyp, int, msgflg) |
909 | { | 909 | { |
910 | long err, mtype; | 910 | long err, mtype; |
911 | 911 | ||
@@ -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 | * |
@@ -308,7 +308,7 @@ static inline int sem_more_checks(struct kern_ipc_perm *ipcp, | |||
308 | return 0; | 308 | return 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | asmlinkage long sys_semget(key_t key, int nsems, int semflg) | 311 | SYSCALL_DEFINE3(semget, key_t, key, int, nsems, int, semflg) |
312 | { | 312 | { |
313 | struct ipc_namespace *ns; | 313 | struct ipc_namespace *ns; |
314 | struct ipc_ops sem_ops; | 314 | struct ipc_ops sem_ops; |
@@ -887,7 +887,7 @@ out_up: | |||
887 | return err; | 887 | return err; |
888 | } | 888 | } |
889 | 889 | ||
890 | asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) | 890 | SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg) |
891 | { | 891 | { |
892 | int err = -EINVAL; | 892 | int err = -EINVAL; |
893 | int version; | 893 | int version; |
@@ -923,6 +923,13 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) | |||
923 | return -EINVAL; | 923 | return -EINVAL; |
924 | } | 924 | } |
925 | } | 925 | } |
926 | #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS | ||
927 | asmlinkage long SyS_semctl(int semid, int semnum, int cmd, union semun arg) | ||
928 | { | ||
929 | return SYSC_semctl((int) semid, (int) semnum, (int) cmd, arg); | ||
930 | } | ||
931 | SYSCALL_ALIAS(sys_semctl, SyS_semctl); | ||
932 | #endif | ||
926 | 933 | ||
927 | /* If the task doesn't already have a undo_list, then allocate one | 934 | /* If the task doesn't already have a undo_list, then allocate one |
928 | * here. We guarantee there is only one thread using this undo list, | 935 | * here. We guarantee there is only one thread using this undo list, |
@@ -1048,8 +1055,8 @@ out: | |||
1048 | return un; | 1055 | return un; |
1049 | } | 1056 | } |
1050 | 1057 | ||
1051 | asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops, | 1058 | SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, |
1052 | unsigned nsops, const struct timespec __user *timeout) | 1059 | unsigned, nsops, const struct timespec __user *, timeout) |
1053 | { | 1060 | { |
1054 | int error = -EINVAL; | 1061 | int error = -EINVAL; |
1055 | struct sem_array *sma; | 1062 | struct sem_array *sma; |
@@ -1216,7 +1223,6 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops, | |||
1216 | if (timeout && jiffies_left == 0) | 1223 | if (timeout && jiffies_left == 0) |
1217 | error = -EAGAIN; | 1224 | error = -EAGAIN; |
1218 | list_del(&queue.list); | 1225 | list_del(&queue.list); |
1219 | goto out_unlock_free; | ||
1220 | 1226 | ||
1221 | out_unlock_free: | 1227 | out_unlock_free: |
1222 | sem_unlock(sma); | 1228 | sem_unlock(sma); |
@@ -1226,7 +1232,8 @@ out_free: | |||
1226 | return error; | 1232 | return error; |
1227 | } | 1233 | } |
1228 | 1234 | ||
1229 | asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsops) | 1235 | SYSCALL_DEFINE3(semop, int, semid, struct sembuf __user *, tsops, |
1236 | unsigned, nsops) | ||
1230 | { | 1237 | { |
1231 | return sys_semtimedop(semid, tsops, nsops, NULL); | 1238 | return sys_semtimedop(semid, tsops, nsops, NULL); |
1232 | } | 1239 | } |
@@ -75,7 +75,7 @@ void shm_init_ns(struct ipc_namespace *ns) | |||
75 | ns->shm_ctlall = SHMALL; | 75 | ns->shm_ctlall = SHMALL; |
76 | ns->shm_ctlmni = SHMMNI; | 76 | ns->shm_ctlmni = SHMMNI; |
77 | ns->shm_tot = 0; | 77 | ns->shm_tot = 0; |
78 | ipc_init_ids(&ns->ids[IPC_SHM_IDS]); | 78 | ipc_init_ids(&shm_ids(ns)); |
79 | } | 79 | } |
80 | 80 | ||
81 | /* | 81 | /* |
@@ -366,7 +366,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
366 | if (shmflg & SHM_HUGETLB) { | 366 | if (shmflg & SHM_HUGETLB) { |
367 | /* hugetlb_file_setup takes care of mlock user accounting */ | 367 | /* hugetlb_file_setup takes care of mlock user accounting */ |
368 | file = hugetlb_file_setup(name, size); | 368 | file = hugetlb_file_setup(name, size); |
369 | shp->mlock_user = current->user; | 369 | shp->mlock_user = current_user(); |
370 | } else { | 370 | } else { |
371 | int acctflag = VM_ACCOUNT; | 371 | int acctflag = VM_ACCOUNT; |
372 | /* | 372 | /* |
@@ -440,7 +440,7 @@ static inline int shm_more_checks(struct kern_ipc_perm *ipcp, | |||
440 | return 0; | 440 | return 0; |
441 | } | 441 | } |
442 | 442 | ||
443 | asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) | 443 | SYSCALL_DEFINE3(shmget, key_t, key, size_t, size, int, shmflg) |
444 | { | 444 | { |
445 | struct ipc_namespace *ns; | 445 | struct ipc_namespace *ns; |
446 | struct ipc_ops shm_ops; | 446 | struct ipc_ops shm_ops; |
@@ -621,7 +621,7 @@ out_up: | |||
621 | return err; | 621 | return err; |
622 | } | 622 | } |
623 | 623 | ||
624 | asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | 624 | SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf) |
625 | { | 625 | { |
626 | struct shmid_kernel *shp; | 626 | struct shmid_kernel *shp; |
627 | int err, version; | 627 | int err, version; |
@@ -644,7 +644,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
644 | if (err) | 644 | if (err) |
645 | return err; | 645 | return err; |
646 | 646 | ||
647 | memset(&shminfo,0,sizeof(shminfo)); | 647 | memset(&shminfo, 0, sizeof(shminfo)); |
648 | shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; | 648 | shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; |
649 | shminfo.shmmax = ns->shm_ctlmax; | 649 | shminfo.shmmax = ns->shm_ctlmax; |
650 | shminfo.shmall = ns->shm_ctlall; | 650 | shminfo.shmall = ns->shm_ctlall; |
@@ -669,7 +669,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
669 | if (err) | 669 | if (err) |
670 | return err; | 670 | return err; |
671 | 671 | ||
672 | memset(&shm_info,0,sizeof(shm_info)); | 672 | memset(&shm_info, 0, sizeof(shm_info)); |
673 | down_read(&shm_ids(ns).rw_mutex); | 673 | down_read(&shm_ids(ns).rw_mutex); |
674 | shm_info.used_ids = shm_ids(ns).in_use; | 674 | shm_info.used_ids = shm_ids(ns).in_use; |
675 | shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp); | 675 | shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp); |
@@ -678,7 +678,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
678 | shm_info.swap_successes = 0; | 678 | shm_info.swap_successes = 0; |
679 | err = ipc_get_maxid(&shm_ids(ns)); | 679 | err = ipc_get_maxid(&shm_ids(ns)); |
680 | up_read(&shm_ids(ns).rw_mutex); | 680 | up_read(&shm_ids(ns).rw_mutex); |
681 | if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { | 681 | if (copy_to_user(buf, &shm_info, sizeof(shm_info))) { |
682 | err = -EFAULT; | 682 | err = -EFAULT; |
683 | goto out; | 683 | goto out; |
684 | } | 684 | } |
@@ -692,11 +692,6 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
692 | struct shmid64_ds tbuf; | 692 | struct shmid64_ds tbuf; |
693 | int result; | 693 | int result; |
694 | 694 | ||
695 | if (!buf) { | ||
696 | err = -EFAULT; | ||
697 | goto out; | ||
698 | } | ||
699 | |||
700 | if (cmd == SHM_STAT) { | 695 | if (cmd == SHM_STAT) { |
701 | shp = shm_lock(ns, shmid); | 696 | shp = shm_lock(ns, shmid); |
702 | if (IS_ERR(shp)) { | 697 | if (IS_ERR(shp)) { |
@@ -712,7 +707,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
712 | } | 707 | } |
713 | result = 0; | 708 | result = 0; |
714 | } | 709 | } |
715 | err=-EACCES; | 710 | err = -EACCES; |
716 | if (ipcperms (&shp->shm_perm, S_IRUGO)) | 711 | if (ipcperms (&shp->shm_perm, S_IRUGO)) |
717 | goto out_unlock; | 712 | goto out_unlock; |
718 | err = security_shm_shmctl(shp, cmd); | 713 | err = security_shm_shmctl(shp, cmd); |
@@ -747,14 +742,13 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
747 | goto out; | 742 | goto out; |
748 | } | 743 | } |
749 | 744 | ||
750 | err = audit_ipc_obj(&(shp->shm_perm)); | 745 | audit_ipc_obj(&(shp->shm_perm)); |
751 | if (err) | ||
752 | goto out_unlock; | ||
753 | 746 | ||
754 | if (!capable(CAP_IPC_LOCK)) { | 747 | if (!capable(CAP_IPC_LOCK)) { |
748 | uid_t euid = current_euid(); | ||
755 | err = -EPERM; | 749 | err = -EPERM; |
756 | if (current->euid != shp->shm_perm.uid && | 750 | if (euid != shp->shm_perm.uid && |
757 | current->euid != shp->shm_perm.cuid) | 751 | euid != shp->shm_perm.cuid) |
758 | goto out_unlock; | 752 | goto out_unlock; |
759 | if (cmd == SHM_LOCK && | 753 | if (cmd == SHM_LOCK && |
760 | !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur) | 754 | !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur) |
@@ -766,7 +760,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
766 | goto out_unlock; | 760 | goto out_unlock; |
767 | 761 | ||
768 | if(cmd==SHM_LOCK) { | 762 | if(cmd==SHM_LOCK) { |
769 | struct user_struct * user = current->user; | 763 | struct user_struct *user = current_user(); |
770 | if (!is_file_hugepages(shp->shm_file)) { | 764 | if (!is_file_hugepages(shp->shm_file)) { |
771 | err = shmem_lock(shp->shm_file, 1, user); | 765 | err = shmem_lock(shp->shm_file, 1, user); |
772 | if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){ | 766 | if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){ |
@@ -945,7 +939,7 @@ out_put_dentry: | |||
945 | goto out_nattch; | 939 | goto out_nattch; |
946 | } | 940 | } |
947 | 941 | ||
948 | asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg) | 942 | SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg) |
949 | { | 943 | { |
950 | unsigned long ret; | 944 | unsigned long ret; |
951 | long err; | 945 | long err; |
@@ -961,7 +955,7 @@ asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg) | |||
961 | * detach and kill segment if marked destroyed. | 955 | * detach and kill segment if marked destroyed. |
962 | * The work is done in shm_close. | 956 | * The work is done in shm_close. |
963 | */ | 957 | */ |
964 | asmlinkage long sys_shmdt(char __user *shmaddr) | 958 | SYSCALL_DEFINE1(shmdt, char __user *, shmaddr) |
965 | { | 959 | { |
966 | struct mm_struct *mm = current->mm; | 960 | struct mm_struct *mm = current->mm; |
967 | struct vm_area_struct *vma, *next; | 961 | struct vm_area_struct *vma, *next; |
@@ -996,6 +990,7 @@ asmlinkage long sys_shmdt(char __user *shmaddr) | |||
996 | */ | 990 | */ |
997 | vma = find_vma(mm, addr); | 991 | vma = find_vma(mm, addr); |
998 | 992 | ||
993 | #ifdef CONFIG_MMU | ||
999 | while (vma) { | 994 | while (vma) { |
1000 | next = vma->vm_next; | 995 | next = vma->vm_next; |
1001 | 996 | ||
@@ -1040,6 +1035,17 @@ asmlinkage long sys_shmdt(char __user *shmaddr) | |||
1040 | vma = next; | 1035 | vma = next; |
1041 | } | 1036 | } |
1042 | 1037 | ||
1038 | #else /* CONFIG_MMU */ | ||
1039 | /* under NOMMU conditions, the exact address to be destroyed must be | ||
1040 | * given */ | ||
1041 | retval = -EINVAL; | ||
1042 | if (vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) { | ||
1043 | do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start); | ||
1044 | retval = 0; | ||
1045 | } | ||
1046 | |||
1047 | #endif | ||
1048 | |||
1043 | up_write(&mm->mmap_sem); | 1049 | up_write(&mm->mmap_sem); |
1044 | return retval; | 1050 | return retval; |
1045 | } | 1051 | } |
diff --git a/ipc/util.c b/ipc/util.c index 361fd1c96fcf..7585a72e259b 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -258,6 +258,8 @@ int ipc_get_maxid(struct ipc_ids *ids) | |||
258 | 258 | ||
259 | int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | 259 | int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) |
260 | { | 260 | { |
261 | uid_t euid; | ||
262 | gid_t egid; | ||
261 | int id, err; | 263 | int id, err; |
262 | 264 | ||
263 | if (size > IPCMNI) | 265 | if (size > IPCMNI) |
@@ -280,8 +282,9 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
280 | 282 | ||
281 | ids->in_use++; | 283 | ids->in_use++; |
282 | 284 | ||
283 | new->cuid = new->uid = current->euid; | 285 | current_euid_egid(&euid, &egid); |
284 | new->gid = new->cgid = current->egid; | 286 | new->cuid = new->uid = euid; |
287 | new->gid = new->cgid = egid; | ||
285 | 288 | ||
286 | new->seq = ids->seq++; | 289 | new->seq = ids->seq++; |
287 | if(ids->seq > ids->seq_max) | 290 | if(ids->seq > ids->seq_max) |
@@ -620,13 +623,14 @@ void ipc_rcu_putref(void *ptr) | |||
620 | 623 | ||
621 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) | 624 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) |
622 | { /* 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> */ |
623 | int requested_mode, granted_mode, err; | 626 | uid_t euid = current_euid(); |
627 | int requested_mode, granted_mode; | ||
624 | 628 | ||
625 | if (unlikely((err = audit_ipc_obj(ipcp)))) | 629 | audit_ipc_obj(ipcp); |
626 | return err; | ||
627 | requested_mode = (flag >> 6) | (flag >> 3) | flag; | 630 | requested_mode = (flag >> 6) | (flag >> 3) | flag; |
628 | granted_mode = ipcp->mode; | 631 | granted_mode = ipcp->mode; |
629 | if (current->euid == ipcp->cuid || current->euid == ipcp->uid) | 632 | if (euid == ipcp->cuid || |
633 | euid == ipcp->uid) | ||
630 | granted_mode >>= 6; | 634 | granted_mode >>= 6; |
631 | else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) | 635 | else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) |
632 | granted_mode >>= 3; | 636 | granted_mode >>= 3; |
@@ -788,6 +792,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
788 | struct ipc64_perm *perm, int extra_perm) | 792 | struct ipc64_perm *perm, int extra_perm) |
789 | { | 793 | { |
790 | struct kern_ipc_perm *ipcp; | 794 | struct kern_ipc_perm *ipcp; |
795 | uid_t euid; | ||
791 | int err; | 796 | int err; |
792 | 797 | ||
793 | down_write(&ids->rw_mutex); | 798 | down_write(&ids->rw_mutex); |
@@ -797,22 +802,17 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
797 | goto out_up; | 802 | goto out_up; |
798 | } | 803 | } |
799 | 804 | ||
800 | err = audit_ipc_obj(ipcp); | 805 | audit_ipc_obj(ipcp); |
801 | if (err) | 806 | if (cmd == IPC_SET) |
802 | goto out_unlock; | 807 | audit_ipc_set_perm(extra_perm, perm->uid, |
803 | |||
804 | if (cmd == IPC_SET) { | ||
805 | err = audit_ipc_set_perm(extra_perm, perm->uid, | ||
806 | perm->gid, perm->mode); | 808 | perm->gid, perm->mode); |
807 | if (err) | 809 | |
808 | goto out_unlock; | 810 | euid = current_euid(); |
809 | } | 811 | if (euid == ipcp->cuid || |
810 | if (current->euid == ipcp->cuid || | 812 | euid == ipcp->uid || capable(CAP_SYS_ADMIN)) |
811 | current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) | ||
812 | return ipcp; | 813 | return ipcp; |
813 | 814 | ||
814 | err = -EPERM; | 815 | err = -EPERM; |
815 | out_unlock: | ||
816 | ipc_unlock(ipcp); | 816 | ipc_unlock(ipcp); |
817 | out_up: | 817 | out_up: |
818 | up_write(&ids->rw_mutex); | 818 | up_write(&ids->rw_mutex); |