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/mqueue.c123
-rw-r--r--ipc/msg.c1
-rw-r--r--ipc/shm.c3
-rw-r--r--ipc/syscall.c99
6 files changed, 175 insertions, 54 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/mqueue.c b/ipc/mqueue.c
index c79bd57353e7..722b0130aa94 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -32,6 +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/slab.h>
35 36
36#include <net/sock.h> 37#include <net/sock.h>
37#include "util.h" 38#include "util.h"
@@ -134,7 +135,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
134 init_waitqueue_head(&info->wait_q); 135 init_waitqueue_head(&info->wait_q);
135 INIT_LIST_HEAD(&info->e_wait_q[0].list); 136 INIT_LIST_HEAD(&info->e_wait_q[0].list);
136 INIT_LIST_HEAD(&info->e_wait_q[1].list); 137 INIT_LIST_HEAD(&info->e_wait_q[1].list);
137 info->messages = NULL;
138 info->notify_owner = NULL; 138 info->notify_owner = NULL;
139 info->qsize = 0; 139 info->qsize = 0;
140 info->user = NULL; /* set when all is ok */ 140 info->user = NULL; /* set when all is ok */
@@ -146,26 +146,24 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
146 info->attr.mq_msgsize = attr->mq_msgsize; 146 info->attr.mq_msgsize = attr->mq_msgsize;
147 } 147 }
148 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
149 mq_bytes = (mq_msg_tblsz + 153 mq_bytes = (mq_msg_tblsz +
150 (info->attr.mq_maxmsg * info->attr.mq_msgsize)); 154 (info->attr.mq_maxmsg * info->attr.mq_msgsize));
151 155
152 spin_lock(&mq_lock); 156 spin_lock(&mq_lock);
153 if (u->mq_bytes + mq_bytes < u->mq_bytes || 157 if (u->mq_bytes + mq_bytes < u->mq_bytes ||
154 u->mq_bytes + mq_bytes > 158 u->mq_bytes + mq_bytes >
155 p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur) { 159 task_rlimit(p, RLIMIT_MSGQUEUE)) {
156 spin_unlock(&mq_lock); 160 spin_unlock(&mq_lock);
161 kfree(info->messages);
157 goto out_inode; 162 goto out_inode;
158 } 163 }
159 u->mq_bytes += mq_bytes; 164 u->mq_bytes += mq_bytes;
160 spin_unlock(&mq_lock); 165 spin_unlock(&mq_lock);
161 166
162 info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
163 if (!info->messages) {
164 spin_lock(&mq_lock);
165 u->mq_bytes -= mq_bytes;
166 spin_unlock(&mq_lock);
167 goto out_inode;
168 }
169 /* all is ok */ 167 /* all is ok */
170 info->user = get_uid(u); 168 info->user = get_uid(u);
171 } else if (S_ISDIR(mode)) { 169 } else if (S_ISDIR(mode)) {
@@ -187,7 +185,7 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
187{ 185{
188 struct inode *inode; 186 struct inode *inode;
189 struct ipc_namespace *ns = data; 187 struct ipc_namespace *ns = data;
190 int error = 0; 188 int error;
191 189
192 sb->s_blocksize = PAGE_CACHE_SIZE; 190 sb->s_blocksize = PAGE_CACHE_SIZE;
193 sb->s_blocksize_bits = PAGE_CACHE_SHIFT; 191 sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
@@ -205,7 +203,9 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
205 if (!sb->s_root) { 203 if (!sb->s_root) {
206 iput(inode); 204 iput(inode);
207 error = -ENOMEM; 205 error = -ENOMEM;
206 goto out;
208 } 207 }
208 error = 0;
209 209
210out: 210out:
211 return error; 211 return error;
@@ -264,8 +264,9 @@ static void mqueue_delete_inode(struct inode *inode)
264 264
265 clear_inode(inode); 265 clear_inode(inode);
266 266
267 mq_bytes = (info->attr.mq_maxmsg * sizeof(struct msg_msg *) + 267 /* Total amount of bytes accounted for the mqueue */
268 (info->attr.mq_maxmsg * info->attr.mq_msgsize)); 268 mq_bytes = info->attr.mq_maxmsg * (sizeof(struct msg_msg *)
269 + info->attr.mq_msgsize);
269 user = info->user; 270 user = info->user;
270 if (user) { 271 if (user) {
271 spin_lock(&mq_lock); 272 spin_lock(&mq_lock);
@@ -604,8 +605,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
604 /* check for overflow */ 605 /* check for overflow */
605 if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg) 606 if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg)
606 return 0; 607 return 0;
607 if ((unsigned long)(attr->mq_maxmsg * attr->mq_msgsize) + 608 if ((unsigned long)(attr->mq_maxmsg * (attr->mq_msgsize
608 (attr->mq_maxmsg * sizeof (struct msg_msg *)) < 609 + sizeof (struct msg_msg *))) <
609 (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize)) 610 (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize))
610 return 0; 611 return 0;
611 return 1; 612 return 1;
@@ -623,9 +624,10 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
623 int ret; 624 int ret;
624 625
625 if (attr) { 626 if (attr) {
626 ret = -EINVAL; 627 if (!mq_attr_ok(ipc_ns, attr)) {
627 if (!mq_attr_ok(ipc_ns, attr)) 628 ret = -EINVAL;
628 goto out; 629 goto out;
630 }
629 /* store for use during create */ 631 /* store for use during create */
630 dentry->d_fsdata = attr; 632 dentry->d_fsdata = attr;
631 } 633 }
@@ -659,24 +661,28 @@ out:
659static struct file *do_open(struct ipc_namespace *ipc_ns, 661static struct file *do_open(struct ipc_namespace *ipc_ns,
660 struct dentry *dentry, int oflag) 662 struct dentry *dentry, int oflag)
661{ 663{
664 int ret;
662 const struct cred *cred = current_cred(); 665 const struct cred *cred = current_cred();
663 666
664 static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, 667 static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
665 MAY_READ | MAY_WRITE }; 668 MAY_READ | MAY_WRITE };
666 669
667 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { 670 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
668 dput(dentry); 671 ret = -EINVAL;
669 mntput(ipc_ns->mq_mnt); 672 goto err;
670 return ERR_PTR(-EINVAL);
671 } 673 }
672 674
673 if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { 675 if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
674 dput(dentry); 676 ret = -EACCES;
675 mntput(ipc_ns->mq_mnt); 677 goto err;
676 return ERR_PTR(-EACCES);
677 } 678 }
678 679
679 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);
680} 686}
681 687
682SYSCALL_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,
@@ -705,16 +711,17 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
705 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));
706 if (IS_ERR(dentry)) { 712 if (IS_ERR(dentry)) {
707 error = PTR_ERR(dentry); 713 error = PTR_ERR(dentry);
708 goto out_err; 714 goto out_putfd;
709 } 715 }
710 mntget(ipc_ns->mq_mnt); 716 mntget(ipc_ns->mq_mnt);
711 717
712 if (oflag & O_CREAT) { 718 if (oflag & O_CREAT) {
713 if (dentry->d_inode) { /* entry already exists */ 719 if (dentry->d_inode) { /* entry already exists */
714 audit_inode(name, dentry); 720 audit_inode(name, dentry);
715 error = -EEXIST; 721 if (oflag & O_EXCL) {
716 if (oflag & O_EXCL) 722 error = -EEXIST;
717 goto out; 723 goto out;
724 }
718 filp = do_open(ipc_ns, dentry, oflag); 725 filp = do_open(ipc_ns, dentry, oflag);
719 } else { 726 } else {
720 filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root, 727 filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root,
@@ -722,9 +729,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
722 u_attr ? &attr : NULL); 729 u_attr ? &attr : NULL);
723 } 730 }
724 } else { 731 } else {
725 error = -ENOENT; 732 if (!dentry->d_inode) {
726 if (!dentry->d_inode) 733 error = -ENOENT;
727 goto out; 734 goto out;
735 }
728 audit_inode(name, dentry); 736 audit_inode(name, dentry);
729 filp = do_open(ipc_ns, dentry, oflag); 737 filp = do_open(ipc_ns, dentry, oflag);
730 } 738 }
@@ -742,7 +750,6 @@ out:
742 mntput(ipc_ns->mq_mnt); 750 mntput(ipc_ns->mq_mnt);
743out_putfd: 751out_putfd:
744 put_unused_fd(fd); 752 put_unused_fd(fd);
745out_err:
746 fd = error; 753 fd = error;
747out_upsem: 754out_upsem:
748 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);
@@ -872,19 +879,24 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
872 audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); 879 audit_mq_sendrecv(mqdes, msg_len, msg_prio, p);
873 timeout = prepare_timeout(p); 880 timeout = prepare_timeout(p);
874 881
875 ret = -EBADF;
876 filp = fget(mqdes); 882 filp = fget(mqdes);
877 if (unlikely(!filp)) 883 if (unlikely(!filp)) {
884 ret = -EBADF;
878 goto out; 885 goto out;
886 }
879 887
880 inode = filp->f_path.dentry->d_inode; 888 inode = filp->f_path.dentry->d_inode;
881 if (unlikely(filp->f_op != &mqueue_file_operations)) 889 if (unlikely(filp->f_op != &mqueue_file_operations)) {
890 ret = -EBADF;
882 goto out_fput; 891 goto out_fput;
892 }
883 info = MQUEUE_I(inode); 893 info = MQUEUE_I(inode);
884 audit_inode(NULL, filp->f_path.dentry); 894 audit_inode(NULL, filp->f_path.dentry);
885 895
886 if (unlikely(!(filp->f_mode & FMODE_WRITE))) 896 if (unlikely(!(filp->f_mode & FMODE_WRITE))) {
897 ret = -EBADF;
887 goto out_fput; 898 goto out_fput;
899 }
888 900
889 if (unlikely(msg_len > info->attr.mq_msgsize)) { 901 if (unlikely(msg_len > info->attr.mq_msgsize)) {
890 ret = -EMSGSIZE; 902 ret = -EMSGSIZE;
@@ -961,19 +973,24 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
961 audit_mq_sendrecv(mqdes, msg_len, 0, p); 973 audit_mq_sendrecv(mqdes, msg_len, 0, p);
962 timeout = prepare_timeout(p); 974 timeout = prepare_timeout(p);
963 975
964 ret = -EBADF;
965 filp = fget(mqdes); 976 filp = fget(mqdes);
966 if (unlikely(!filp)) 977 if (unlikely(!filp)) {
978 ret = -EBADF;
967 goto out; 979 goto out;
980 }
968 981
969 inode = filp->f_path.dentry->d_inode; 982 inode = filp->f_path.dentry->d_inode;
970 if (unlikely(filp->f_op != &mqueue_file_operations)) 983 if (unlikely(filp->f_op != &mqueue_file_operations)) {
984 ret = -EBADF;
971 goto out_fput; 985 goto out_fput;
986 }
972 info = MQUEUE_I(inode); 987 info = MQUEUE_I(inode);
973 audit_inode(NULL, filp->f_path.dentry); 988 audit_inode(NULL, filp->f_path.dentry);
974 989
975 if (unlikely(!(filp->f_mode & FMODE_READ))) 990 if (unlikely(!(filp->f_mode & FMODE_READ))) {
991 ret = -EBADF;
976 goto out_fput; 992 goto out_fput;
993 }
977 994
978 /* checks if buffer is big enough */ 995 /* checks if buffer is big enough */
979 if (unlikely(msg_len < info->attr.mq_msgsize)) { 996 if (unlikely(msg_len < info->attr.mq_msgsize)) {
@@ -1063,13 +1080,14 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
1063 1080
1064 /* create the notify skb */ 1081 /* create the notify skb */
1065 nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL); 1082 nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
1066 ret = -ENOMEM; 1083 if (!nc) {
1067 if (!nc) 1084 ret = -ENOMEM;
1068 goto out; 1085 goto out;
1069 ret = -EFAULT; 1086 }
1070 if (copy_from_user(nc->data, 1087 if (copy_from_user(nc->data,
1071 notification.sigev_value.sival_ptr, 1088 notification.sigev_value.sival_ptr,
1072 NOTIFY_COOKIE_LEN)) { 1089 NOTIFY_COOKIE_LEN)) {
1090 ret = -EFAULT;
1073 goto out; 1091 goto out;
1074 } 1092 }
1075 1093
@@ -1078,9 +1096,10 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes,
1078 /* and attach it to the socket */ 1096 /* and attach it to the socket */
1079retry: 1097retry:
1080 filp = fget(notification.sigev_signo); 1098 filp = fget(notification.sigev_signo);
1081 ret = -EBADF; 1099 if (!filp) {
1082 if (!filp) 1100 ret = -EBADF;
1083 goto out; 1101 goto out;
1102 }
1084 sock = netlink_getsockbyfilp(filp); 1103 sock = netlink_getsockbyfilp(filp);
1085 fput(filp); 1104 fput(filp);
1086 if (IS_ERR(sock)) { 1105 if (IS_ERR(sock)) {
@@ -1092,7 +1111,7 @@ retry:
1092 timeo = MAX_SCHEDULE_TIMEOUT; 1111 timeo = MAX_SCHEDULE_TIMEOUT;
1093 ret = netlink_attachskb(sock, nc, &timeo, NULL); 1112 ret = netlink_attachskb(sock, nc, &timeo, NULL);
1094 if (ret == 1) 1113 if (ret == 1)
1095 goto retry; 1114 goto retry;
1096 if (ret) { 1115 if (ret) {
1097 sock = NULL; 1116 sock = NULL;
1098 nc = NULL; 1117 nc = NULL;
@@ -1101,14 +1120,17 @@ retry:
1101 } 1120 }
1102 } 1121 }
1103 1122
1104 ret = -EBADF;
1105 filp = fget(mqdes); 1123 filp = fget(mqdes);
1106 if (!filp) 1124 if (!filp) {
1125 ret = -EBADF;
1107 goto out; 1126 goto out;
1127 }
1108 1128
1109 inode = filp->f_path.dentry->d_inode; 1129 inode = filp->f_path.dentry->d_inode;
1110 if (unlikely(filp->f_op != &mqueue_file_operations)) 1130 if (unlikely(filp->f_op != &mqueue_file_operations)) {
1131 ret = -EBADF;
1111 goto out_fput; 1132 goto out_fput;
1133 }
1112 info = MQUEUE_I(inode); 1134 info = MQUEUE_I(inode);
1113 1135
1114 ret = 0; 1136 ret = 0;
@@ -1171,14 +1193,17 @@ SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
1171 return -EINVAL; 1193 return -EINVAL;
1172 } 1194 }
1173 1195
1174 ret = -EBADF;
1175 filp = fget(mqdes); 1196 filp = fget(mqdes);
1176 if (!filp) 1197 if (!filp) {
1198 ret = -EBADF;
1177 goto out; 1199 goto out;
1200 }
1178 1201
1179 inode = filp->f_path.dentry->d_inode; 1202 inode = filp->f_path.dentry->d_inode;
1180 if (unlikely(filp->f_op != &mqueue_file_operations)) 1203 if (unlikely(filp->f_op != &mqueue_file_operations)) {
1204 ret = -EBADF;
1181 goto out_fput; 1205 goto out_fput;
1206 }
1182 info = MQUEUE_I(inode); 1207 info = MQUEUE_I(inode);
1183 1208
1184 spin_lock(&info->lock); 1209 spin_lock(&info->lock);
@@ -1272,7 +1297,7 @@ static int __init init_mqueue_fs(void)
1272 if (mqueue_inode_cachep == NULL) 1297 if (mqueue_inode_cachep == NULL)
1273 return -ENOMEM; 1298 return -ENOMEM;
1274 1299
1275 /* ignore failues - they are not fatal */ 1300 /* ignore failures - they are not fatal */
1276 mq_sysctl_table = mq_register_sysctl_table(); 1301 mq_sysctl_table = mq_register_sysctl_table();
1277 1302
1278 error = register_filesystem(&mqueue_fs_type); 1303 error = register_filesystem(&mqueue_fs_type);
diff --git a/ipc/msg.c b/ipc/msg.c
index af42ef8900a6..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>
diff --git a/ipc/shm.c b/ipc/shm.c
index 23256b855819..1a314c89f93c 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -764,8 +764,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
764 if (euid != shp->shm_perm.uid && 764 if (euid != shp->shm_perm.uid &&
765 euid != shp->shm_perm.cuid) 765 euid != shp->shm_perm.cuid)
766 goto out_unlock; 766 goto out_unlock;
767 if (cmd == SHM_LOCK && 767 if (cmd == SHM_LOCK && !rlimit(RLIMIT_MEMLOCK))
768 !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur)
769 goto out_unlock; 768 goto out_unlock;
770 } 769 }
771 770
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