aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/ipc_sysctl.c46
-rw-r--r--ipc/mqueue.c148
-rw-r--r--ipc/msg.c12
-rw-r--r--ipc/sem.c21
-rw-r--r--ipc/shm.c48
-rw-r--r--ipc/util.c36
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 */
38static 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
53static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, 30static 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 */
83static 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
97static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, 97static 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)
112static struct inode *mqueue_get_inode(struct super_block *sb, int mode, 112static 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
527static long prepare_timeout(const struct timespec __user *u_arg) 527static 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 */
594static struct file *do_create(struct dentry *dir, struct dentry *dentry, 590static 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 */
638static struct file *do_open(struct dentry *dentry, int oflag) 631static struct file *do_open(struct dentry *dentry, int oflag)
639{ 632{
640static 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
658asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, 653SYSCALL_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
726asmlinkage long sys_mq_unlink(const char __user *u_name) 724SYSCALL_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
819asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, 817SYSCALL_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
907asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, 910SYSCALL_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 */
992asmlinkage long sys_mq_notify(mqd_t mqdes, 1000SYSCALL_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(&notification, u_notification, 1012 if (copy_from_user(&notification, 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 ? &notification : 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
1118asmlinkage long sys_mq_getsetattr(mqd_t mqdes, 1126SYSCALL_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
diff --git a/ipc/msg.c b/ipc/msg.c
index b4eee1c6101d..2ceab7f12fcb 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -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
312asmlinkage long sys_msgget(key_t key, int msgflg) 312SYSCALL_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
469asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf) 469SYSCALL_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
726asmlinkage long 726SYSCALL_DEFINE4(msgsnd, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
727sys_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
907asmlinkage long sys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, 907SYSCALL_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
diff --git a/ipc/sem.c b/ipc/sem.c
index 082122469b17..16a2189e96f9 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 *
@@ -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
311asmlinkage long sys_semget(key_t key, int nsems, int semflg) 311SYSCALL_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
890asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg) 890SYSCALL_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
927asmlinkage 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}
931SYSCALL_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
1051asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops, 1058SYSCALL_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
1221out_unlock_free: 1227out_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
1229asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsops) 1235SYSCALL_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}
diff --git a/ipc/shm.c b/ipc/shm.c
index 867e5d6a55c2..a9e09ad2263e 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -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
443asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) 443SYSCALL_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
624asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) 624SYSCALL_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
948asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg) 942SYSCALL_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 */
964asmlinkage long sys_shmdt(char __user *shmaddr) 958SYSCALL_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
259int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) 259int 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
621int ipcperms (struct kern_ipc_perm *ipcp, short flag) 624int 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;
815out_unlock:
816 ipc_unlock(ipcp); 816 ipc_unlock(ipcp);
817out_up: 817out_up:
818 up_write(&ids->rw_mutex); 818 up_write(&ids->rw_mutex);