aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/Makefile2
-rw-r--r--ipc/compat.c1
-rw-r--r--ipc/ipc_sysctl.c77
-rw-r--r--ipc/mq_sysctl.c7
-rw-r--r--ipc/mqueue.c125
-rw-r--r--ipc/msg.c4
-rw-r--r--ipc/sem.c214
-rw-r--r--ipc/shm.c46
-rw-r--r--ipc/syscall.c99
9 files changed, 349 insertions, 226 deletions
diff --git a/ipc/Makefile b/ipc/Makefile
index 4e1955ea815d..9075e172e52c 100644
--- a/ipc/Makefile
+++ b/ipc/Makefile
@@ -3,7 +3,7 @@
3# 3#
4 4
5obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o 5obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
6obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o 6obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o syscall.o
7obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o 7obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
8obj_mq-$(CONFIG_COMPAT) += compat_mq.o 8obj_mq-$(CONFIG_COMPAT) += compat_mq.o
9obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) 9obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
diff --git a/ipc/compat.c b/ipc/compat.c
index ab76fb0ef844..9dc2c7d3c9e6 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -26,7 +26,6 @@
26#include <linux/init.h> 26#include <linux/init.h>
27#include <linux/msg.h> 27#include <linux/msg.h>
28#include <linux/shm.h> 28#include <linux/shm.h>
29#include <linux/slab.h>
30#include <linux/syscalls.h> 29#include <linux/syscalls.h>
31 30
32#include <linux/mutex.h> 31#include <linux/mutex.h>
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 7d3704750efc..56410faa4550 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -129,136 +129,60 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
129#define proc_ipcauto_dointvec_minmax NULL 129#define proc_ipcauto_dointvec_minmax NULL
130#endif 130#endif
131 131
132#ifdef CONFIG_SYSCTL_SYSCALL
133/* The generic sysctl ipc data routine. */
134static int sysctl_ipc_data(ctl_table *table,
135 void __user *oldval, size_t __user *oldlenp,
136 void __user *newval, size_t newlen)
137{
138 size_t len;
139 void *data;
140
141 /* Get out of I don't have a variable */
142 if (!table->data || !table->maxlen)
143 return -ENOTDIR;
144
145 data = get_ipc(table);
146 if (!data)
147 return -ENOTDIR;
148
149 if (oldval && oldlenp) {
150 if (get_user(len, oldlenp))
151 return -EFAULT;
152 if (len) {
153 if (len > table->maxlen)
154 len = table->maxlen;
155 if (copy_to_user(oldval, data, len))
156 return -EFAULT;
157 if (put_user(len, oldlenp))
158 return -EFAULT;
159 }
160 }
161
162 if (newval && newlen) {
163 if (newlen > table->maxlen)
164 newlen = table->maxlen;
165
166 if (copy_from_user(data, newval, newlen))
167 return -EFAULT;
168 }
169 return 1;
170}
171
172static int sysctl_ipc_registered_data(ctl_table *table,
173 void __user *oldval, size_t __user *oldlenp,
174 void __user *newval, size_t newlen)
175{
176 int rc;
177
178 rc = sysctl_ipc_data(table, oldval, oldlenp, newval, newlen);
179
180 if (newval && newlen && rc > 0)
181 /*
182 * Tunable has successfully been changed from userland
183 */
184 unregister_ipcns_notifier(current->nsproxy->ipc_ns);
185
186 return rc;
187}
188#else
189#define sysctl_ipc_data NULL
190#define sysctl_ipc_registered_data NULL
191#endif
192
193static int zero; 132static int zero;
194static int one = 1; 133static int one = 1;
195 134
196static struct ctl_table ipc_kern_table[] = { 135static struct ctl_table ipc_kern_table[] = {
197 { 136 {
198 .ctl_name = KERN_SHMMAX,
199 .procname = "shmmax", 137 .procname = "shmmax",
200 .data = &init_ipc_ns.shm_ctlmax, 138 .data = &init_ipc_ns.shm_ctlmax,
201 .maxlen = sizeof (init_ipc_ns.shm_ctlmax), 139 .maxlen = sizeof (init_ipc_ns.shm_ctlmax),
202 .mode = 0644, 140 .mode = 0644,
203 .proc_handler = proc_ipc_doulongvec_minmax, 141 .proc_handler = proc_ipc_doulongvec_minmax,
204 .strategy = sysctl_ipc_data,
205 }, 142 },
206 { 143 {
207 .ctl_name = KERN_SHMALL,
208 .procname = "shmall", 144 .procname = "shmall",
209 .data = &init_ipc_ns.shm_ctlall, 145 .data = &init_ipc_ns.shm_ctlall,
210 .maxlen = sizeof (init_ipc_ns.shm_ctlall), 146 .maxlen = sizeof (init_ipc_ns.shm_ctlall),
211 .mode = 0644, 147 .mode = 0644,
212 .proc_handler = proc_ipc_doulongvec_minmax, 148 .proc_handler = proc_ipc_doulongvec_minmax,
213 .strategy = sysctl_ipc_data,
214 }, 149 },
215 { 150 {
216 .ctl_name = KERN_SHMMNI,
217 .procname = "shmmni", 151 .procname = "shmmni",
218 .data = &init_ipc_ns.shm_ctlmni, 152 .data = &init_ipc_ns.shm_ctlmni,
219 .maxlen = sizeof (init_ipc_ns.shm_ctlmni), 153 .maxlen = sizeof (init_ipc_ns.shm_ctlmni),
220 .mode = 0644, 154 .mode = 0644,
221 .proc_handler = proc_ipc_dointvec, 155 .proc_handler = proc_ipc_dointvec,
222 .strategy = sysctl_ipc_data,
223 }, 156 },
224 { 157 {
225 .ctl_name = KERN_MSGMAX,
226 .procname = "msgmax", 158 .procname = "msgmax",
227 .data = &init_ipc_ns.msg_ctlmax, 159 .data = &init_ipc_ns.msg_ctlmax,
228 .maxlen = sizeof (init_ipc_ns.msg_ctlmax), 160 .maxlen = sizeof (init_ipc_ns.msg_ctlmax),
229 .mode = 0644, 161 .mode = 0644,
230 .proc_handler = proc_ipc_dointvec, 162 .proc_handler = proc_ipc_dointvec,
231 .strategy = sysctl_ipc_data,
232 }, 163 },
233 { 164 {
234 .ctl_name = KERN_MSGMNI,
235 .procname = "msgmni", 165 .procname = "msgmni",
236 .data = &init_ipc_ns.msg_ctlmni, 166 .data = &init_ipc_ns.msg_ctlmni,
237 .maxlen = sizeof (init_ipc_ns.msg_ctlmni), 167 .maxlen = sizeof (init_ipc_ns.msg_ctlmni),
238 .mode = 0644, 168 .mode = 0644,
239 .proc_handler = proc_ipc_callback_dointvec, 169 .proc_handler = proc_ipc_callback_dointvec,
240 .strategy = sysctl_ipc_registered_data,
241 }, 170 },
242 { 171 {
243 .ctl_name = KERN_MSGMNB,
244 .procname = "msgmnb", 172 .procname = "msgmnb",
245 .data = &init_ipc_ns.msg_ctlmnb, 173 .data = &init_ipc_ns.msg_ctlmnb,
246 .maxlen = sizeof (init_ipc_ns.msg_ctlmnb), 174 .maxlen = sizeof (init_ipc_ns.msg_ctlmnb),
247 .mode = 0644, 175 .mode = 0644,
248 .proc_handler = proc_ipc_dointvec, 176 .proc_handler = proc_ipc_dointvec,
249 .strategy = sysctl_ipc_data,
250 }, 177 },
251 { 178 {
252 .ctl_name = KERN_SEM,
253 .procname = "sem", 179 .procname = "sem",
254 .data = &init_ipc_ns.sem_ctls, 180 .data = &init_ipc_ns.sem_ctls,
255 .maxlen = 4*sizeof (int), 181 .maxlen = 4*sizeof (int),
256 .mode = 0644, 182 .mode = 0644,
257 .proc_handler = proc_ipc_dointvec, 183 .proc_handler = proc_ipc_dointvec,
258 .strategy = sysctl_ipc_data,
259 }, 184 },
260 { 185 {
261 .ctl_name = CTL_UNNUMBERED,
262 .procname = "auto_msgmni", 186 .procname = "auto_msgmni",
263 .data = &init_ipc_ns.auto_msgmni, 187 .data = &init_ipc_ns.auto_msgmni,
264 .maxlen = sizeof(int), 188 .maxlen = sizeof(int),
@@ -272,7 +196,6 @@ static struct ctl_table ipc_kern_table[] = {
272 196
273static struct ctl_table ipc_root_table[] = { 197static struct ctl_table ipc_root_table[] = {
274 { 198 {
275 .ctl_name = CTL_KERN,
276 .procname = "kernel", 199 .procname = "kernel",
277 .mode = 0555, 200 .mode = 0555,
278 .child = ipc_kern_table, 201 .child = ipc_kern_table,
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c
index 8a058711fc10..0c09366b96f3 100644
--- a/ipc/mq_sysctl.c
+++ b/ipc/mq_sysctl.c
@@ -88,7 +88,7 @@ static ctl_table mq_sysctls[] = {
88 .extra1 = &msg_maxsize_limit_min, 88 .extra1 = &msg_maxsize_limit_min,
89 .extra2 = &msg_maxsize_limit_max, 89 .extra2 = &msg_maxsize_limit_max,
90 }, 90 },
91 { .ctl_name = 0 } 91 {}
92}; 92};
93 93
94static ctl_table mq_sysctl_dir[] = { 94static ctl_table mq_sysctl_dir[] = {
@@ -97,17 +97,16 @@ static ctl_table mq_sysctl_dir[] = {
97 .mode = 0555, 97 .mode = 0555,
98 .child = mq_sysctls, 98 .child = mq_sysctls,
99 }, 99 },
100 { .ctl_name = 0 } 100 {}
101}; 101};
102 102
103static ctl_table mq_sysctl_root[] = { 103static ctl_table mq_sysctl_root[] = {
104 { 104 {
105 .ctl_name = CTL_FS,
106 .procname = "fs", 105 .procname = "fs",
107 .mode = 0555, 106 .mode = 0555,
108 .child = mq_sysctl_dir, 107 .child = mq_sysctl_dir,
109 }, 108 },
110 { .ctl_name = 0 } 109 {}
111}; 110};
112 111
113struct ctl_table_header *mq_register_sysctl_table(void) 112struct ctl_table_header *mq_register_sysctl_table(void)
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index ee9d69707c0a..59a009dc54a8 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -32,7 +32,7 @@
32#include <linux/nsproxy.h> 32#include <linux/nsproxy.h>
33#include <linux/pid.h> 33#include <linux/pid.h>
34#include <linux/ipc_namespace.h> 34#include <linux/ipc_namespace.h>
35#include <linux/ima.h> 35#include <linux/slab.h>
36 36
37#include <net/sock.h> 37#include <net/sock.h>
38#include "util.h" 38#include "util.h"
@@ -135,7 +135,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
135 init_waitqueue_head(&info->wait_q); 135 init_waitqueue_head(&info->wait_q);
136 INIT_LIST_HEAD(&info->e_wait_q[0].list); 136 INIT_LIST_HEAD(&info->e_wait_q[0].list);
137 INIT_LIST_HEAD(&info->e_wait_q[1].list); 137 INIT_LIST_HEAD(&info->e_wait_q[1].list);
138 info->messages = NULL;
139 info->notify_owner = NULL; 138 info->notify_owner = NULL;
140 info->qsize = 0; 139 info->qsize = 0;
141 info->user = NULL; /* set when all is ok */ 140 info->user = NULL; /* set when all is ok */
@@ -147,26 +146,24 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
147 info->attr.mq_msgsize = attr->mq_msgsize; 146 info->attr.mq_msgsize = attr->mq_msgsize;
148 } 147 }
149 mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *); 148 mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
149 info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
150 if (!info->messages)
151 goto out_inode;
152
150 mq_bytes = (mq_msg_tblsz + 153 mq_bytes = (mq_msg_tblsz +
151 (info->attr.mq_maxmsg * info->attr.mq_msgsize)); 154 (info->attr.mq_maxmsg * info->attr.mq_msgsize));
152 155
153 spin_lock(&mq_lock); 156 spin_lock(&mq_lock);
154 if (u->mq_bytes + mq_bytes < u->mq_bytes || 157 if (u->mq_bytes + mq_bytes < u->mq_bytes ||
155 u->mq_bytes + mq_bytes > 158 u->mq_bytes + mq_bytes >
156 p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur) { 159 task_rlimit(p, RLIMIT_MSGQUEUE)) {
157 spin_unlock(&mq_lock); 160 spin_unlock(&mq_lock);
161 /* mqueue_delete_inode() releases info->messages */
158 goto out_inode; 162 goto out_inode;
159 } 163 }
160 u->mq_bytes += mq_bytes; 164 u->mq_bytes += mq_bytes;
161 spin_unlock(&mq_lock); 165 spin_unlock(&mq_lock);
162 166
163 info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
164 if (!info->messages) {
165 spin_lock(&mq_lock);
166 u->mq_bytes -= mq_bytes;
167 spin_unlock(&mq_lock);
168 goto out_inode;
169 }
170 /* all is ok */ 167 /* all is ok */
171 info->user = get_uid(u); 168 info->user = get_uid(u);
172 } else if (S_ISDIR(mode)) { 169 } else if (S_ISDIR(mode)) {
@@ -188,7 +185,7 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
188{ 185{
189 struct inode *inode; 186 struct inode *inode;
190 struct ipc_namespace *ns = data; 187 struct ipc_namespace *ns = data;
191 int error = 0; 188 int error;
192 189
193 sb->s_blocksize = PAGE_CACHE_SIZE; 190 sb->s_blocksize = PAGE_CACHE_SIZE;
194 sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 191 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -206,7 +203,9 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
206 if (!sb->s_root) { 203 if (!sb->s_root) {
207 iput(inode); 204 iput(inode);
208 error = -ENOMEM; 205 error = -ENOMEM;
206 goto out;
209 } 207 }
208 error = 0;
210 209
211out: 210out:
212 return error; 211 return error;
@@ -265,8 +264,9 @@ static void mqueue_delete_inode(struct inode *inode)
265 264
266 clear_inode(inode); 265 clear_inode(inode);
267 266
268 mq_bytes = (info->attr.mq_maxmsg * sizeof(struct msg_msg *) + 267 /* Total amount of bytes accounted for the mqueue */
269 (info->attr.mq_maxmsg * info->attr.mq_msgsize)); 268 mq_bytes = info->attr.mq_maxmsg * (sizeof(struct msg_msg *)
269 + info->attr.mq_msgsize);
270 user = info->user; 270 user = info->user;
271 if (user) { 271 if (user) {
272 spin_lock(&mq_lock); 272 spin_lock(&mq_lock);
@@ -605,8 +605,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
605 /* check for overflow */ 605 /* check for overflow */
606 if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg) 606 if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
607 return 0; 607 return 0;
608 if ((unsigned long)(attr->mq_maxmsg * attr->mq_msgsize) + 608 if ((unsigned long)(attr->mq_maxmsg * (attr->mq_msgsize
609 (attr->mq_maxmsg * sizeof (struct msg_msg *)) < 609 + sizeof (struct msg_msg *))) <
610 (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize)) 610 (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize))
611 return 0; 611 return 0;
612 return 1; 612 return 1;
@@ -624,9 +624,10 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
624 int ret; 624 int ret;
625 625
626 if (attr) { 626 if (attr) {
627 ret = -EINVAL; 627 if (!mq_attr_ok(ipc_ns, attr)) {
628 if (!mq_attr_ok(ipc_ns, attr)) 628 ret = -EINVAL;
629 goto out; 629 goto out;
630 }
630 /* store for use during create */ 631 /* store for use during create */
631 dentry->d_fsdata = attr; 632 dentry->d_fsdata = attr;
632 } 633 }
@@ -660,24 +661,28 @@ out:
660static struct file *do_open(struct ipc_namespace *ipc_ns, 661static struct file *do_open(struct ipc_namespace *ipc_ns,
661 struct dentry *dentry, int oflag) 662 struct dentry *dentry, int oflag)
662{ 663{
664 int ret;
663 const struct cred *cred = current_cred(); 665 const struct cred *cred = current_cred();
664 666
665 static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, 667 static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
666 MAY_READ | MAY_WRITE }; 668 MAY_READ | MAY_WRITE };
667 669
668 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { 670 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
669 dput(dentry); 671 ret = -EINVAL;
670 mntput(ipc_ns->mq_mnt); 672 goto err;
671 return ERR_PTR(-EINVAL);
672 } 673 }
673 674
674 if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { 675 if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
675 dput(dentry); 676 ret = -EACCES;
676 mntput(ipc_ns->mq_mnt); 677 goto err;
677 return ERR_PTR(-EACCES);
678 } 678 }
679 679
680 return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); 680 return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
681
682err:
683 dput(dentry);
684 mntput(ipc_ns->mq_mnt);
685 return ERR_PTR(ret);
681} 686}
682 687
683SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, 688SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
@@ -706,16 +711,17 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
706 dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); 711 dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
707 if (IS_ERR(dentry)) { 712 if (IS_ERR(dentry)) {
708 error = PTR_ERR(dentry); 713 error = PTR_ERR(dentry);
709 goto out_err; 714 goto out_putfd;
710 } 715 }
711 mntget(ipc_ns->mq_mnt); 716 mntget(ipc_ns->mq_mnt);
712 717
713 if (oflag & O_CREAT) { 718 if (oflag & O_CREAT) {
714 if (dentry->d_inode) { /* entry already exists */ 719 if (dentry->d_inode) { /* entry already exists */
715 audit_inode(name, dentry); 720 audit_inode(name, dentry);
716 error = -EEXIST; 721 if (oflag & O_EXCL) {
717 if (oflag & O_EXCL) 722 error = -EEXIST;
718 goto out; 723 goto out;
724 }
719 filp = do_open(ipc_ns, dentry, oflag); 725 filp = do_open(ipc_ns, dentry, oflag);
720 } else { 726 } else {
721 filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root, 727 filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root,
@@ -723,9 +729,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
723 u_attr ? &attr : NULL); 729 u_attr ? &attr : NULL);
724 } 730 }
725 } else { 731 } else {
726 error = -ENOENT; 732 if (!dentry->d_inode) {
727 if (!dentry->d_inode) 733 error = -ENOENT;
728 goto out; 734 goto out;
735 }
729 audit_inode(name, dentry); 736 audit_inode(name, dentry);
730 filp = do_open(ipc_ns, dentry, oflag); 737 filp = do_open(ipc_ns, dentry, oflag);
731 } 738 }
@@ -734,7 +741,6 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
734 error = PTR_ERR(filp); 741 error = PTR_ERR(filp);
735 goto out_putfd; 742 goto out_putfd;
736 } 743 }
737 ima_counts_get(filp);
738 744
739 fd_install(fd, filp); 745 fd_install(fd, filp);
740 goto out_upsem; 746 goto out_upsem;
@@ -744,7 +750,6 @@ out:
744 mntput(ipc_ns->mq_mnt); 750 mntput(ipc_ns->mq_mnt);
745out_putfd: 751out_putfd:
746 put_unused_fd(fd); 752 put_unused_fd(fd);
747out_err:
748 fd = error; 753 fd = error;
749out_upsem: 754out_upsem:
750 mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); 755 mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
@@ -874,19 +879,24 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
874 audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); 879 audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
875 timeout = prepare_timeout(p); 880 timeout = prepare_timeout(p);
876 881
877 ret = -EBADF;
878 filp = fget(mqdes); 882 filp = fget(mqdes);
879 if (unlikely(!filp)) 883 if (unlikely(!filp)) {
884 ret = -EBADF;
880 goto out; 885 goto out;
886 }
881 887
882 inode = filp->f_path.dentry->d_inode; 888 inode = filp->f_path.dentry->d_inode;
883 if (unlikely(filp->f_op != &mqueue_file_operations)) 889 if (unlikely(filp->f_op != &mqueue_file_operations)) {
890 ret = -EBADF;
884 goto out_fput; 891 goto out_fput;
892 }
885 info = MQUEUE_I(inode); 893 info = MQUEUE_I(inode);
886 audit_inode(NULL, filp->f_path.dentry); 894 audit_inode(NULL, filp->f_path.dentry);
887 895
888 if (unlikely(!(filp->f_mode & FMODE_WRITE))) 896 if (unlikely(!(filp->f_mode & FMODE_WRITE))) {
897 ret = -EBADF;
889 goto out_fput; 898 goto out_fput;
899 }
890 900
891 if (unlikely(msg_len > info->attr.mq_msgsize)) { 901 if (unlikely(msg_len > info->attr.mq_msgsize)) {
892 ret = -EMSGSIZE; 902 ret = -EMSGSIZE;
@@ -963,19 +973,24 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
963 audit_mq_sendrecv(mqdes, msg_len, 0, p); 973 audit_mq_sendrecv(mqdes, msg_len, 0, p);
964 timeout = prepare_timeout(p); 974 timeout = prepare_timeout(p);
965 975
966 ret = -EBADF;
967 filp = fget(mqdes); 976 filp = fget(mqdes);
968 if (unlikely(!filp)) 977 if (unlikely(!filp)) {
978 ret = -EBADF;
969 goto out; 979 goto out;
980 }
970 981
971 inode = filp->f_path.dentry->d_inode; 982 inode = filp->f_path.dentry->d_inode;
972 if (unlikely(filp->f_op != &mqueue_file_operations)) 983 if (unlikely(filp->f_op != &mqueue_file_operations)) {
984 ret = -EBADF;
973 goto out_fput; 985 goto out_fput;
986 }
974 info = MQUEUE_I(inode); 987 info = MQUEUE_I(inode);
975 audit_inode(NULL, filp->f_path.dentry); 988 audit_inode(NULL, filp->f_path.dentry);
976 989
977 if (unlikely(!(filp->f_mode & FMODE_READ))) 990 if (unlikely(!(filp->f_mode & FMODE_READ))) {
991 ret = -EBADF;
978 goto out_fput; 992 goto out_fput;
993 }
979 994
980 /* checks if buffer is big enough */ 995 /* checks if buffer is big enough */
981 if (unlikely(msg_len < info->attr.mq_msgsize)) { 996 if (unlikely(msg_len < info->attr.mq_msgsize)) {
@@ -1065,13 +1080,14 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
1065 1080
1066 /* create the notify skb */ 1081 /* create the notify skb */
1067 nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL); 1082 nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
1068 ret = -ENOMEM; 1083 if (!nc) {
1069 if (!nc) 1084 ret = -ENOMEM;
1070 goto out; 1085 goto out;
1071 ret = -EFAULT; 1086 }
1072 if (copy_from_user(nc->data, 1087 if (copy_from_user(nc->data,
1073 notification.sigev_value.sival_ptr, 1088 notification.sigev_value.sival_ptr,
1074 NOTIFY_COOKIE_LEN)) { 1089 NOTIFY_COOKIE_LEN)) {
1090 ret = -EFAULT;
1075 goto out; 1091 goto out;
1076 } 1092 }
1077 1093
@@ -1080,9 +1096,10 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
1080 /* and attach it to the socket */ 1096 /* and attach it to the socket */
1081retry: 1097retry:
1082 filp = fget(notification.sigev_signo); 1098 filp = fget(notification.sigev_signo);
1083 ret = -EBADF; 1099 if (!filp) {
1084 if (!filp) 1100 ret = -EBADF;
1085 goto out; 1101 goto out;
1102 }
1086 sock = netlink_getsockbyfilp(filp); 1103 sock = netlink_getsockbyfilp(filp);
1087 fput(filp); 1104 fput(filp);
1088 if (IS_ERR(sock)) { 1105 if (IS_ERR(sock)) {
@@ -1094,7 +1111,7 @@ retry:
1094 timeo = MAX_SCHEDULE_TIMEOUT; 1111 timeo = MAX_SCHEDULE_TIMEOUT;
1095 ret = netlink_attachskb(sock, nc, &timeo, NULL); 1112 ret = netlink_attachskb(sock, nc, &timeo, NULL);
1096 if (ret == 1) 1113 if (ret == 1)
1097 goto retry; 1114 goto retry;
1098 if (ret) { 1115 if (ret) {
1099 sock = NULL; 1116 sock = NULL;
1100 nc = NULL; 1117 nc = NULL;
@@ -1103,14 +1120,17 @@ retry:
1103 } 1120 }
1104 } 1121 }
1105 1122
1106 ret = -EBADF;
1107 filp = fget(mqdes); 1123 filp = fget(mqdes);
1108 if (!filp) 1124 if (!filp) {
1125 ret = -EBADF;
1109 goto out; 1126 goto out;
1127 }
1110 1128
1111 inode = filp->f_path.dentry->d_inode; 1129 inode = filp->f_path.dentry->d_inode;
1112 if (unlikely(filp->f_op != &mqueue_file_operations)) 1130 if (unlikely(filp->f_op != &mqueue_file_operations)) {
1131 ret = -EBADF;
1113 goto out_fput; 1132 goto out_fput;
1133 }
1114 info = MQUEUE_I(inode); 1134 info = MQUEUE_I(inode);
1115 1135
1116 ret = 0; 1136 ret = 0;
@@ -1173,14 +1193,17 @@ SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
1173 return -EINVAL; 1193 return -EINVAL;
1174 } 1194 }
1175 1195
1176 ret = -EBADF;
1177 filp = fget(mqdes); 1196 filp = fget(mqdes);
1178 if (!filp) 1197 if (!filp) {
1198 ret = -EBADF;
1179 goto out; 1199 goto out;
1200 }
1180 1201
1181 inode = filp->f_path.dentry->d_inode; 1202 inode = filp->f_path.dentry->d_inode;
1182 if (unlikely(filp->f_op != &mqueue_file_operations)) 1203 if (unlikely(filp->f_op != &mqueue_file_operations)) {
1204 ret = -EBADF;
1183 goto out_fput; 1205 goto out_fput;
1206 }
1184 info = MQUEUE_I(inode); 1207 info = MQUEUE_I(inode);
1185 1208
1186 spin_lock(&info->lock); 1209 spin_lock(&info->lock);
@@ -1274,7 +1297,7 @@ static int __init init_mqueue_fs(void)
1274 if (mqueue_inode_cachep == NULL) 1297 if (mqueue_inode_cachep == NULL)
1275 return -ENOMEM; 1298 return -ENOMEM;
1276 1299
1277 /* ignore failues - they are not fatal */ 1300 /* ignore failures - they are not fatal */
1278 mq_sysctl_table = mq_register_sysctl_table(); 1301 mq_sysctl_table = mq_register_sysctl_table();
1279 1302
1280 error = register_filesystem(&mqueue_fs_type); 1303 error = register_filesystem(&mqueue_fs_type);
diff --git a/ipc/msg.c b/ipc/msg.c
index 2ceab7f12fcb..9547cb7ac313 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -23,7 +23,6 @@
23 */ 23 */
24 24
25#include <linux/capability.h> 25#include <linux/capability.h>
26#include <linux/slab.h>
27#include <linux/msg.h> 26#include <linux/msg.h>
28#include <linux/spinlock.h> 27#include <linux/spinlock.h>
29#include <linux/init.h> 28#include <linux/init.h>
@@ -125,6 +124,7 @@ void msg_init_ns(struct ipc_namespace *ns)
125void msg_exit_ns(struct ipc_namespace *ns) 124void msg_exit_ns(struct ipc_namespace *ns)
126{ 125{
127 free_ipcs(ns, &msg_ids(ns), freeque); 126 free_ipcs(ns, &msg_ids(ns), freeque);
127 idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr);
128} 128}
129#endif 129#endif
130 130
@@ -412,7 +412,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,
412 struct msqid_ds __user *buf, int version) 412 struct msqid_ds __user *buf, int version)
413{ 413{
414 struct kern_ipc_perm *ipcp; 414 struct kern_ipc_perm *ipcp;
415 struct msqid64_ds msqid64; 415 struct msqid64_ds uninitialized_var(msqid64);
416 struct msg_queue *msq; 416 struct msg_queue *msq;
417 int err; 417 int err;
418 418
diff --git a/ipc/sem.c b/ipc/sem.c
index 87c2b641fd7b..dbef95b15941 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -129,6 +129,7 @@ void sem_init_ns(struct ipc_namespace *ns)
129void sem_exit_ns(struct ipc_namespace *ns) 129void sem_exit_ns(struct ipc_namespace *ns)
130{ 130{
131 free_ipcs(ns, &sem_ids(ns), freeary); 131 free_ipcs(ns, &sem_ids(ns), freeary);
132 idr_destroy(&ns->ids[IPC_SEM_IDS].ipcs_idr);
132} 133}
133#endif 134#endif
134 135
@@ -240,6 +241,7 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
240 key_t key = params->key; 241 key_t key = params->key;
241 int nsems = params->u.nsems; 242 int nsems = params->u.nsems;
242 int semflg = params->flg; 243 int semflg = params->flg;
244 int i;
243 245
244 if (!nsems) 246 if (!nsems)
245 return -EINVAL; 247 return -EINVAL;
@@ -272,6 +274,11 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
272 ns->used_sems += nsems; 274 ns->used_sems += nsems;
273 275
274 sma->sem_base = (struct sem *) &sma[1]; 276 sma->sem_base = (struct sem *) &sma[1];
277
278 for (i = 0; i < nsems; i++)
279 INIT_LIST_HEAD(&sma->sem_base[i].sem_pending);
280
281 sma->complex_count = 0;
275 INIT_LIST_HEAD(&sma->sem_pending); 282 INIT_LIST_HEAD(&sma->sem_pending);
276 INIT_LIST_HEAD(&sma->list_id); 283 INIT_LIST_HEAD(&sma->list_id);
277 sma->sem_nsems = nsems; 284 sma->sem_nsems = nsems;
@@ -397,63 +404,109 @@ undo:
397 return result; 404 return result;
398} 405}
399 406
400/* Go through the pending queue for the indicated semaphore 407/*
401 * looking for tasks that can be completed. 408 * Wake up a process waiting on the sem queue with a given error.
409 * The queue is invalid (may not be accessed) after the function returns.
402 */ 410 */
403static void update_queue (struct sem_array * sma) 411static void wake_up_sem_queue(struct sem_queue *q, int error)
404{ 412{
405 int error; 413 /*
406 struct sem_queue * q; 414 * Hold preempt off so that we don't get preempted and have the
415 * wakee busy-wait until we're scheduled back on. We're holding
416 * locks here so it may not strictly be needed, however if the
417 * locks become preemptible then this prevents such a problem.
418 */
419 preempt_disable();
420 q->status = IN_WAKEUP;
421 wake_up_process(q->sleeper);
422 /* hands-off: q can disappear immediately after writing q->status. */
423 smp_wmb();
424 q->status = error;
425 preempt_enable();
426}
427
428static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
429{
430 list_del(&q->list);
431 if (q->nsops == 1)
432 list_del(&q->simple_list);
433 else
434 sma->complex_count--;
435}
436
437
438/**
439 * update_queue(sma, semnum): Look for tasks that can be completed.
440 * @sma: semaphore array.
441 * @semnum: semaphore that was modified.
442 *
443 * update_queue must be called after a semaphore in a semaphore array
444 * was modified. If multiple semaphore were modified, then @semnum
445 * must be set to -1.
446 */
447static void update_queue(struct sem_array *sma, int semnum)
448{
449 struct sem_queue *q;
450 struct list_head *walk;
451 struct list_head *pending_list;
452 int offset;
453
454 /* if there are complex operations around, then knowing the semaphore
455 * that was modified doesn't help us. Assume that multiple semaphores
456 * were modified.
457 */
458 if (sma->complex_count)
459 semnum = -1;
460
461 if (semnum == -1) {
462 pending_list = &sma->sem_pending;
463 offset = offsetof(struct sem_queue, list);
464 } else {
465 pending_list = &sma->sem_base[semnum].sem_pending;
466 offset = offsetof(struct sem_queue, simple_list);
467 }
468
469again:
470 walk = pending_list->next;
471 while (walk != pending_list) {
472 int error, alter;
473
474 q = (struct sem_queue *)((char *)walk - offset);
475 walk = walk->next;
476
477 /* If we are scanning the single sop, per-semaphore list of
478 * one semaphore and that semaphore is 0, then it is not
479 * necessary to scan the "alter" entries: simple increments
480 * that affect only one entry succeed immediately and cannot
481 * be in the per semaphore pending queue, and decrements
482 * cannot be successful if the value is already 0.
483 */
484 if (semnum != -1 && sma->sem_base[semnum].semval == 0 &&
485 q->alter)
486 break;
407 487
408 q = list_entry(sma->sem_pending.next, struct sem_queue, list);
409 while (&q->list != &sma->sem_pending) {
410 error = try_atomic_semop(sma, q->sops, q->nsops, 488 error = try_atomic_semop(sma, q->sops, q->nsops,
411 q->undo, q->pid); 489 q->undo, q->pid);
412 490
413 /* Does q->sleeper still need to sleep? */ 491 /* Does q->sleeper still need to sleep? */
414 if (error <= 0) { 492 if (error > 0)
415 struct sem_queue *n; 493 continue;
416
417 /*
418 * Continue scanning. The next operation
419 * that must be checked depends on the type of the
420 * completed operation:
421 * - if the operation modified the array, then
422 * restart from the head of the queue and
423 * check for threads that might be waiting
424 * for semaphore values to become 0.
425 * - if the operation didn't modify the array,
426 * then just continue.
427 * The order of list_del() and reading ->next
428 * is crucial: In the former case, the list_del()
429 * must be done first [because we might be the
430 * first entry in ->sem_pending], in the latter
431 * case the list_del() must be done last
432 * [because the list is invalid after the list_del()]
433 */
434 if (q->alter) {
435 list_del(&q->list);
436 n = list_entry(sma->sem_pending.next,
437 struct sem_queue, list);
438 } else {
439 n = list_entry(q->list.next, struct sem_queue,
440 list);
441 list_del(&q->list);
442 }
443
444 /* wake up the waiting thread */
445 q->status = IN_WAKEUP;
446 494
447 wake_up_process(q->sleeper); 495 unlink_queue(sma, q);
448 /* hands-off: q will disappear immediately after 496
449 * writing q->status. 497 /*
450 */ 498 * The next operation that must be checked depends on the type
451 smp_wmb(); 499 * of the completed operation:
452 q->status = error; 500 * - if the operation modified the array, then restart from the
453 q = n; 501 * head of the queue and check for threads that might be
454 } else { 502 * waiting for the new semaphore values.
455 q = list_entry(q->list.next, struct sem_queue, list); 503 * - if the operation didn't modify the array, then just
456 } 504 * continue.
505 */
506 alter = q->alter;
507 wake_up_sem_queue(q, error);
508 if (alter && !error)
509 goto again;
457 } 510 }
458} 511}
459 512
@@ -533,12 +586,8 @@ static void freeary(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
533 586
534 /* Wake up all pending processes and let them fail with EIDRM. */ 587 /* Wake up all pending processes and let them fail with EIDRM. */
535 list_for_each_entry_safe(q, tq, &sma->sem_pending, list) { 588 list_for_each_entry_safe(q, tq, &sma->sem_pending, list) {
536 list_del(&q->list); 589 unlink_queue(sma, q);
537 590 wake_up_sem_queue(q, -EIDRM);
538 q->status = IN_WAKEUP;
539 wake_up_process(q->sleeper); /* doesn't sleep */
540 smp_wmb();
541 q->status = -EIDRM; /* hands-off q */
542 } 591 }
543 592
544 /* Remove the semaphore set from the IDR */ 593 /* Remove the semaphore set from the IDR */
@@ -575,7 +624,7 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
575static int semctl_nolock(struct ipc_namespace *ns, int semid, 624static int semctl_nolock(struct ipc_namespace *ns, int semid,
576 int cmd, int version, union semun arg) 625 int cmd, int version, union semun arg)
577{ 626{
578 int err = -EINVAL; 627 int err;
579 struct sem_array *sma; 628 struct sem_array *sma;
580 629
581 switch(cmd) { 630 switch(cmd) {
@@ -652,7 +701,6 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,
652 default: 701 default:
653 return -EINVAL; 702 return -EINVAL;
654 } 703 }
655 return err;
656out_unlock: 704out_unlock:
657 sem_unlock(sma); 705 sem_unlock(sma);
658 return err; 706 return err;
@@ -759,7 +807,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
759 } 807 }
760 sma->sem_ctime = get_seconds(); 808 sma->sem_ctime = get_seconds();
761 /* maybe some queued-up processes were waiting for this */ 809 /* maybe some queued-up processes were waiting for this */
762 update_queue(sma); 810 update_queue(sma, -1);
763 err = 0; 811 err = 0;
764 goto out_unlock; 812 goto out_unlock;
765 } 813 }
@@ -801,7 +849,7 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
801 curr->sempid = task_tgid_vnr(current); 849 curr->sempid = task_tgid_vnr(current);
802 sma->sem_ctime = get_seconds(); 850 sma->sem_ctime = get_seconds();
803 /* maybe some queued-up processes were waiting for this */ 851 /* maybe some queued-up processes were waiting for this */
804 update_queue(sma); 852 update_queue(sma, semnum);
805 err = 0; 853 err = 0;
806 goto out_unlock; 854 goto out_unlock;
807 } 855 }
@@ -961,17 +1009,31 @@ static inline int get_undo_list(struct sem_undo_list **undo_listp)
961 return 0; 1009 return 0;
962} 1010}
963 1011
964static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid) 1012static struct sem_undo *__lookup_undo(struct sem_undo_list *ulp, int semid)
965{ 1013{
966 struct sem_undo *walk; 1014 struct sem_undo *un;
967 1015
968 list_for_each_entry_rcu(walk, &ulp->list_proc, list_proc) { 1016 list_for_each_entry_rcu(un, &ulp->list_proc, list_proc) {
969 if (walk->semid == semid) 1017 if (un->semid == semid)
970 return walk; 1018 return un;
971 } 1019 }
972 return NULL; 1020 return NULL;
973} 1021}
974 1022
1023static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
1024{
1025 struct sem_undo *un;
1026
1027 assert_spin_locked(&ulp->lock);
1028
1029 un = __lookup_undo(ulp, semid);
1030 if (un) {
1031 list_del_rcu(&un->list_proc);
1032 list_add_rcu(&un->list_proc, &ulp->list_proc);
1033 }
1034 return un;
1035}
1036
975/** 1037/**
976 * find_alloc_undo - Lookup (and if not present create) undo array 1038 * find_alloc_undo - Lookup (and if not present create) undo array
977 * @ns: namespace 1039 * @ns: namespace
@@ -1163,7 +1225,8 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1163 error = try_atomic_semop (sma, sops, nsops, un, task_tgid_vnr(current)); 1225 error = try_atomic_semop (sma, sops, nsops, un, task_tgid_vnr(current));
1164 if (error <= 0) { 1226 if (error <= 0) {
1165 if (alter && error == 0) 1227 if (alter && error == 0)
1166 update_queue (sma); 1228 update_queue(sma, (nsops == 1) ? sops[0].sem_num : -1);
1229
1167 goto out_unlock_free; 1230 goto out_unlock_free;
1168 } 1231 }
1169 1232
@@ -1181,6 +1244,19 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1181 else 1244 else
1182 list_add(&queue.list, &sma->sem_pending); 1245 list_add(&queue.list, &sma->sem_pending);
1183 1246
1247 if (nsops == 1) {
1248 struct sem *curr;
1249 curr = &sma->sem_base[sops->sem_num];
1250
1251 if (alter)
1252 list_add_tail(&queue.simple_list, &curr->sem_pending);
1253 else
1254 list_add(&queue.simple_list, &curr->sem_pending);
1255 } else {
1256 INIT_LIST_HEAD(&queue.simple_list);
1257 sma->complex_count++;
1258 }
1259
1184 queue.status = -EINTR; 1260 queue.status = -EINTR;
1185 queue.sleeper = current; 1261 queue.sleeper = current;
1186 current->state = TASK_INTERRUPTIBLE; 1262 current->state = TASK_INTERRUPTIBLE;
@@ -1222,7 +1298,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
1222 */ 1298 */
1223 if (timeout && jiffies_left == 0) 1299 if (timeout && jiffies_left == 0)
1224 error = -EAGAIN; 1300 error = -EAGAIN;
1225 list_del(&queue.list); 1301 unlink_queue(sma, &queue);
1226 1302
1227out_unlock_free: 1303out_unlock_free:
1228 sem_unlock(sma); 1304 sem_unlock(sma);
@@ -1307,7 +1383,7 @@ void exit_sem(struct task_struct *tsk)
1307 if (IS_ERR(sma)) 1383 if (IS_ERR(sma))
1308 continue; 1384 continue;
1309 1385
1310 un = lookup_undo(ulp, semid); 1386 un = __lookup_undo(ulp, semid);
1311 if (un == NULL) { 1387 if (un == NULL) {
1312 /* exit_sem raced with IPC_RMID+semget() that created 1388 /* exit_sem raced with IPC_RMID+semget() that created
1313 * exactly the same semid. Nothing to do. 1389 * exactly the same semid. Nothing to do.
@@ -1351,7 +1427,7 @@ void exit_sem(struct task_struct *tsk)
1351 } 1427 }
1352 sma->sem_otime = get_seconds(); 1428 sma->sem_otime = get_seconds();
1353 /* maybe some queued-up processes were waiting for this */ 1429 /* maybe some queued-up processes were waiting for this */
1354 update_queue(sma); 1430 update_queue(sma, -1);
1355 sem_unlock(sma); 1431 sem_unlock(sma);
1356 1432
1357 call_rcu(&un->rcu, free_un); 1433 call_rcu(&un->rcu, free_un);
@@ -1365,7 +1441,7 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it)
1365 struct sem_array *sma = it; 1441 struct sem_array *sma = it;
1366 1442
1367 return seq_printf(s, 1443 return seq_printf(s,
1368 "%10d %10d %4o %10lu %5u %5u %5u %5u %10lu %10lu\n", 1444 "%10d %10d %4o %10u %5u %5u %5u %5u %10lu %10lu\n",
1369 sma->sem_perm.key, 1445 sma->sem_perm.key,
1370 sma->sem_perm.id, 1446 sma->sem_perm.id,
1371 sma->sem_perm.mode, 1447 sma->sem_perm.mode,
diff --git a/ipc/shm.c b/ipc/shm.c
index 464694e0aa4a..1a314c89f93c 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -39,7 +39,6 @@
39#include <linux/nsproxy.h> 39#include <linux/nsproxy.h>
40#include <linux/mount.h> 40#include <linux/mount.h>
41#include <linux/ipc_namespace.h> 41#include <linux/ipc_namespace.h>
42#include <linux/ima.h>
43 42
44#include <asm/uaccess.h> 43#include <asm/uaccess.h>
45 44
@@ -101,6 +100,7 @@ static void do_shm_rmid(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp)
101void shm_exit_ns(struct ipc_namespace *ns) 100void shm_exit_ns(struct ipc_namespace *ns)
102{ 101{
103 free_ipcs(ns, &shm_ids(ns), do_shm_rmid); 102 free_ipcs(ns, &shm_ids(ns), do_shm_rmid);
103 idr_destroy(&ns->ids[IPC_SHM_IDS].ipcs_idr);
104} 104}
105#endif 105#endif
106 106
@@ -290,28 +290,31 @@ static unsigned long shm_get_unmapped_area(struct file *file,
290 unsigned long flags) 290 unsigned long flags)
291{ 291{
292 struct shm_file_data *sfd = shm_file_data(file); 292 struct shm_file_data *sfd = shm_file_data(file);
293 return get_unmapped_area(sfd->file, addr, len, pgoff, flags); 293 return sfd->file->f_op->get_unmapped_area(sfd->file, addr, len,
294} 294 pgoff, flags);
295
296int is_file_shm_hugepages(struct file *file)
297{
298 int ret = 0;
299
300 if (file->f_op == &shm_file_operations) {
301 struct shm_file_data *sfd;
302 sfd = shm_file_data(file);
303 ret = is_file_hugepages(sfd->file);
304 }
305 return ret;
306} 295}
307 296
308static const struct file_operations shm_file_operations = { 297static const struct file_operations shm_file_operations = {
309 .mmap = shm_mmap, 298 .mmap = shm_mmap,
310 .fsync = shm_fsync, 299 .fsync = shm_fsync,
311 .release = shm_release, 300 .release = shm_release,
301#ifndef CONFIG_MMU
302 .get_unmapped_area = shm_get_unmapped_area,
303#endif
304};
305
306static const struct file_operations shm_file_operations_huge = {
307 .mmap = shm_mmap,
308 .fsync = shm_fsync,
309 .release = shm_release,
312 .get_unmapped_area = shm_get_unmapped_area, 310 .get_unmapped_area = shm_get_unmapped_area,
313}; 311};
314 312
313int is_file_shm_hugepages(struct file *file)
314{
315 return file->f_op == &shm_file_operations_huge;
316}
317
315static const struct vm_operations_struct shm_vm_ops = { 318static const struct vm_operations_struct shm_vm_ops = {
316 .open = shm_open, /* callback for a new vm-area open */ 319 .open = shm_open, /* callback for a new vm-area open */
317 .close = shm_close, /* callback for when the vm-area is released */ 320 .close = shm_close, /* callback for when the vm-area is released */
@@ -761,8 +764,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
761 if (euid != shp->shm_perm.uid && 764 if (euid != shp->shm_perm.uid &&
762 euid != shp->shm_perm.cuid) 765 euid != shp->shm_perm.cuid)
763 goto out_unlock; 766 goto out_unlock;
764 if (cmd == SHM_LOCK && 767 if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK))
765 !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
766 goto out_unlock; 768 goto out_unlock;
767 } 769 }
768 770
@@ -878,8 +880,8 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
878 if (err) 880 if (err)
879 goto out_unlock; 881 goto out_unlock;
880 882
881 path.dentry = dget(shp->shm_file->f_path.dentry); 883 path = shp->shm_file->f_path;
882 path.mnt = shp->shm_file->f_path.mnt; 884 path_get(&path);
883 shp->shm_nattch++; 885 shp->shm_nattch++;
884 size = i_size_read(path.dentry->d_inode); 886 size = i_size_read(path.dentry->d_inode);
885 shm_unlock(shp); 887 shm_unlock(shp);
@@ -889,10 +891,12 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
889 if (!sfd) 891 if (!sfd)
890 goto out_put_dentry; 892 goto out_put_dentry;
891 893
892 file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); 894 file = alloc_file(&path, f_mode,
895 is_file_hugepages(shp->shm_file) ?
896 &shm_file_operations_huge :
897 &shm_file_operations);
893 if (!file) 898 if (!file)
894 goto out_free; 899 goto out_free;
895 ima_counts_get(file);
896 900
897 file->private_data = sfd; 901 file->private_data = sfd;
898 file->f_mapping = shp->shm_file->f_mapping; 902 file->f_mapping = shp->shm_file->f_mapping;
@@ -947,7 +951,7 @@ out_unlock:
947out_free: 951out_free:
948 kfree(sfd); 952 kfree(sfd);
949out_put_dentry: 953out_put_dentry:
950 dput(path.dentry); 954 path_put(&path);
951 goto out_nattch; 955 goto out_nattch;
952} 956}
953 957
diff --git a/ipc/syscall.c b/ipc/syscall.c
new file mode 100644
index 000000000000..1d6f53f6b562
--- /dev/null
+++ b/ipc/syscall.c
@@ -0,0 +1,99 @@
1/*
2 * sys_ipc() is the old de-multiplexer for the SysV IPC calls.
3 *
4 * This is really horribly ugly, and new architectures should just wire up
5 * the individual syscalls instead.
6 */
7#include <linux/unistd.h>
8
9#ifdef __ARCH_WANT_SYS_IPC
10#include <linux/errno.h>
11#include <linux/ipc.h>
12#include <linux/shm.h>
13#include <linux/syscalls.h>
14#include <linux/uaccess.h>
15
16SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
17 unsigned long, third, void __user *, ptr, long, fifth)
18{
19 int version, ret;
20
21 version = call >> 16; /* hack for backward compatibility */
22 call &= 0xffff;
23
24 switch (call) {
25 case SEMOP:
26 return sys_semtimedop(first, (struct sembuf __user *)ptr,
27 second, NULL);
28 case SEMTIMEDOP:
29 return sys_semtimedop(first, (struct sembuf __user *)ptr,
30 second,
31 (const struct timespec __user *)fifth);
32
33 case SEMGET:
34 return sys_semget(first, second, third);
35 case SEMCTL: {
36 union semun fourth;
37 if (!ptr)
38 return -EINVAL;
39 if (get_user(fourth.__pad, (void __user * __user *) ptr))
40 return -EFAULT;
41 return sys_semctl(first, second, third, fourth);
42 }
43
44 case MSGSND:
45 return sys_msgsnd(first, (struct msgbuf __user *) ptr,
46 second, third);
47 case MSGRCV:
48 switch (version) {
49 case 0: {
50 struct ipc_kludge tmp;
51 if (!ptr)
52 return -EINVAL;
53
54 if (copy_from_user(&tmp,
55 (struct ipc_kludge __user *) ptr,
56 sizeof(tmp)))
57 return -EFAULT;
58 return sys_msgrcv(first, tmp.msgp, second,
59 tmp.msgtyp, third);
60 }
61 default:
62 return sys_msgrcv(first,
63 (struct msgbuf __user *) ptr,
64 second, fifth, third);
65 }
66 case MSGGET:
67 return sys_msgget((key_t) first, second);
68 case MSGCTL:
69 return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
70
71 case SHMAT:
72 switch (version) {
73 default: {
74 unsigned long raddr;
75 ret = do_shmat(first, (char __user *)ptr,
76 second, &raddr);
77 if (ret)
78 return ret;
79 return put_user(raddr, (unsigned long __user *) third);
80 }
81 case 1:
82 /*
83 * This was the entry point for kernel-originating calls
84 * from iBCS2 in 2.2 days.
85 */
86 return -EINVAL;
87 }
88 case SHMDT:
89 return sys_shmdt((char __user *)ptr);
90 case SHMGET:
91 return sys_shmget(first, second, third);
92 case SHMCTL:
93 return sys_shmctl(first, second,
94 (struct shmid_ds __user *) ptr);
95 default:
96 return -ENOSYS;
97 }
98}
99#endif