diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2010-03-26 10:55:59 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-03-26 10:55:59 -0400 |
commit | 329f9052dbadf6f4afe2231668bd00c579a4aa10 (patch) | |
tree | e080a5c70df40f3ae8cf28a95a3267757668ab97 /ipc | |
parent | 395b228858778d3c44f7c413693a6acaa8bb62dc (diff) | |
parent | 220bf991b0366cc50a94feede3d7341fa5710ee4 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:
drivers/mtd/nand/sh_flctl.c
Maxim's patch to initialise sysfs attributes depends on the patch which
actually adds sysfs_attr_init().
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/Makefile | 2 | ||||
-rw-r--r-- | ipc/mqueue.c | 122 | ||||
-rw-r--r-- | ipc/shm.c | 3 | ||||
-rw-r--r-- | ipc/syscall.c | 99 |
4 files changed, 174 insertions, 52 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 | ||
5 | obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o | 5 | obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o |
6 | obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o | 6 | obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o syscall.o |
7 | obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o | 7 | obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o |
8 | obj_mq-$(CONFIG_COMPAT) += compat_mq.o | 8 | obj_mq-$(CONFIG_COMPAT) += compat_mq.o |
9 | obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) | 9 | obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index c79bd57353e7..e4e3f04803ca 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -134,7 +134,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, | |||
134 | init_waitqueue_head(&info->wait_q); | 134 | init_waitqueue_head(&info->wait_q); |
135 | INIT_LIST_HEAD(&info->e_wait_q[0].list); | 135 | INIT_LIST_HEAD(&info->e_wait_q[0].list); |
136 | INIT_LIST_HEAD(&info->e_wait_q[1].list); | 136 | INIT_LIST_HEAD(&info->e_wait_q[1].list); |
137 | info->messages = NULL; | ||
138 | info->notify_owner = NULL; | 137 | info->notify_owner = NULL; |
139 | info->qsize = 0; | 138 | info->qsize = 0; |
140 | info->user = NULL; /* set when all is ok */ | 139 | info->user = NULL; /* set when all is ok */ |
@@ -146,26 +145,24 @@ static struct inode *mqueue_get_inode(struct super_block *sb, | |||
146 | info->attr.mq_msgsize = attr->mq_msgsize; | 145 | info->attr.mq_msgsize = attr->mq_msgsize; |
147 | } | 146 | } |
148 | mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *); | 147 | mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *); |
148 | info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL); | ||
149 | if (!info->messages) | ||
150 | goto out_inode; | ||
151 | |||
149 | mq_bytes = (mq_msg_tblsz + | 152 | mq_bytes = (mq_msg_tblsz + |
150 | (info->attr.mq_maxmsg * info->attr.mq_msgsize)); | 153 | (info->attr.mq_maxmsg * info->attr.mq_msgsize)); |
151 | 154 | ||
152 | spin_lock(&mq_lock); | 155 | spin_lock(&mq_lock); |
153 | if (u->mq_bytes + mq_bytes < u->mq_bytes || | 156 | if (u->mq_bytes + mq_bytes < u->mq_bytes || |
154 | u->mq_bytes + mq_bytes > | 157 | u->mq_bytes + mq_bytes > |
155 | p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur) { | 158 | task_rlimit(p, RLIMIT_MSGQUEUE)) { |
156 | spin_unlock(&mq_lock); | 159 | spin_unlock(&mq_lock); |
160 | kfree(info->messages); | ||
157 | goto out_inode; | 161 | goto out_inode; |
158 | } | 162 | } |
159 | u->mq_bytes += mq_bytes; | 163 | u->mq_bytes += mq_bytes; |
160 | spin_unlock(&mq_lock); | 164 | spin_unlock(&mq_lock); |
161 | 165 | ||
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 */ | 166 | /* all is ok */ |
170 | info->user = get_uid(u); | 167 | info->user = get_uid(u); |
171 | } else if (S_ISDIR(mode)) { | 168 | } else if (S_ISDIR(mode)) { |
@@ -187,7 +184,7 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent) | |||
187 | { | 184 | { |
188 | struct inode *inode; | 185 | struct inode *inode; |
189 | struct ipc_namespace *ns = data; | 186 | struct ipc_namespace *ns = data; |
190 | int error = 0; | 187 | int error; |
191 | 188 | ||
192 | sb->s_blocksize = PAGE_CACHE_SIZE; | 189 | sb->s_blocksize = PAGE_CACHE_SIZE; |
193 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 190 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
@@ -205,7 +202,9 @@ static int mqueue_fill_super(struct super_block *sb, void *data, int silent) | |||
205 | if (!sb->s_root) { | 202 | if (!sb->s_root) { |
206 | iput(inode); | 203 | iput(inode); |
207 | error = -ENOMEM; | 204 | error = -ENOMEM; |
205 | goto out; | ||
208 | } | 206 | } |
207 | error = 0; | ||
209 | 208 | ||
210 | out: | 209 | out: |
211 | return error; | 210 | return error; |
@@ -264,8 +263,9 @@ static void mqueue_delete_inode(struct inode *inode) | |||
264 | 263 | ||
265 | clear_inode(inode); | 264 | clear_inode(inode); |
266 | 265 | ||
267 | mq_bytes = (info->attr.mq_maxmsg * sizeof(struct msg_msg *) + | 266 | /* Total amount of bytes accounted for the mqueue */ |
268 | (info->attr.mq_maxmsg * info->attr.mq_msgsize)); | 267 | mq_bytes = info->attr.mq_maxmsg * (sizeof(struct msg_msg *) |
268 | + info->attr.mq_msgsize); | ||
269 | user = info->user; | 269 | user = info->user; |
270 | if (user) { | 270 | if (user) { |
271 | spin_lock(&mq_lock); | 271 | spin_lock(&mq_lock); |
@@ -604,8 +604,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr) | |||
604 | /* check for overflow */ | 604 | /* check for overflow */ |
605 | if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg) | 605 | if (attr->mq_msgsize > ULONG_MAX/attr->mq_maxmsg) |
606 | return 0; | 606 | return 0; |
607 | if ((unsigned long)(attr->mq_maxmsg * attr->mq_msgsize) + | 607 | if ((unsigned long)(attr->mq_maxmsg * (attr->mq_msgsize |
608 | (attr->mq_maxmsg * sizeof (struct msg_msg *)) < | 608 | + sizeof (struct msg_msg *))) < |
609 | (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize)) | 609 | (unsigned long)(attr->mq_maxmsg * attr->mq_msgsize)) |
610 | return 0; | 610 | return 0; |
611 | return 1; | 611 | return 1; |
@@ -623,9 +623,10 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, | |||
623 | int ret; | 623 | int ret; |
624 | 624 | ||
625 | if (attr) { | 625 | if (attr) { |
626 | ret = -EINVAL; | 626 | if (!mq_attr_ok(ipc_ns, attr)) { |
627 | if (!mq_attr_ok(ipc_ns, attr)) | 627 | ret = -EINVAL; |
628 | goto out; | 628 | goto out; |
629 | } | ||
629 | /* store for use during create */ | 630 | /* store for use during create */ |
630 | dentry->d_fsdata = attr; | 631 | dentry->d_fsdata = attr; |
631 | } | 632 | } |
@@ -659,24 +660,28 @@ out: | |||
659 | static struct file *do_open(struct ipc_namespace *ipc_ns, | 660 | static struct file *do_open(struct ipc_namespace *ipc_ns, |
660 | struct dentry *dentry, int oflag) | 661 | struct dentry *dentry, int oflag) |
661 | { | 662 | { |
663 | int ret; | ||
662 | const struct cred *cred = current_cred(); | 664 | const struct cred *cred = current_cred(); |
663 | 665 | ||
664 | static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | 666 | static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, |
665 | MAY_READ | MAY_WRITE }; | 667 | MAY_READ | MAY_WRITE }; |
666 | 668 | ||
667 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { | 669 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { |
668 | dput(dentry); | 670 | ret = -EINVAL; |
669 | mntput(ipc_ns->mq_mnt); | 671 | goto err; |
670 | return ERR_PTR(-EINVAL); | ||
671 | } | 672 | } |
672 | 673 | ||
673 | if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { | 674 | if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { |
674 | dput(dentry); | 675 | ret = -EACCES; |
675 | mntput(ipc_ns->mq_mnt); | 676 | goto err; |
676 | return ERR_PTR(-EACCES); | ||
677 | } | 677 | } |
678 | 678 | ||
679 | return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); | 679 | return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); |
680 | |||
681 | err: | ||
682 | dput(dentry); | ||
683 | mntput(ipc_ns->mq_mnt); | ||
684 | return ERR_PTR(ret); | ||
680 | } | 685 | } |
681 | 686 | ||
682 | SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, | 687 | SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, |
@@ -705,16 +710,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)); | 710 | dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); |
706 | if (IS_ERR(dentry)) { | 711 | if (IS_ERR(dentry)) { |
707 | error = PTR_ERR(dentry); | 712 | error = PTR_ERR(dentry); |
708 | goto out_err; | 713 | goto out_putfd; |
709 | } | 714 | } |
710 | mntget(ipc_ns->mq_mnt); | 715 | mntget(ipc_ns->mq_mnt); |
711 | 716 | ||
712 | if (oflag & O_CREAT) { | 717 | if (oflag & O_CREAT) { |
713 | if (dentry->d_inode) { /* entry already exists */ | 718 | if (dentry->d_inode) { /* entry already exists */ |
714 | audit_inode(name, dentry); | 719 | audit_inode(name, dentry); |
715 | error = -EEXIST; | 720 | if (oflag & O_EXCL) { |
716 | if (oflag & O_EXCL) | 721 | error = -EEXIST; |
717 | goto out; | 722 | goto out; |
723 | } | ||
718 | filp = do_open(ipc_ns, dentry, oflag); | 724 | filp = do_open(ipc_ns, dentry, oflag); |
719 | } else { | 725 | } else { |
720 | filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root, | 726 | filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root, |
@@ -722,9 +728,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, | |||
722 | u_attr ? &attr : NULL); | 728 | u_attr ? &attr : NULL); |
723 | } | 729 | } |
724 | } else { | 730 | } else { |
725 | error = -ENOENT; | 731 | if (!dentry->d_inode) { |
726 | if (!dentry->d_inode) | 732 | error = -ENOENT; |
727 | goto out; | 733 | goto out; |
734 | } | ||
728 | audit_inode(name, dentry); | 735 | audit_inode(name, dentry); |
729 | filp = do_open(ipc_ns, dentry, oflag); | 736 | filp = do_open(ipc_ns, dentry, oflag); |
730 | } | 737 | } |
@@ -742,7 +749,6 @@ out: | |||
742 | mntput(ipc_ns->mq_mnt); | 749 | mntput(ipc_ns->mq_mnt); |
743 | out_putfd: | 750 | out_putfd: |
744 | put_unused_fd(fd); | 751 | put_unused_fd(fd); |
745 | out_err: | ||
746 | fd = error; | 752 | fd = error; |
747 | out_upsem: | 753 | out_upsem: |
748 | mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); | 754 | mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); |
@@ -872,19 +878,24 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, | |||
872 | audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); | 878 | audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); |
873 | timeout = prepare_timeout(p); | 879 | timeout = prepare_timeout(p); |
874 | 880 | ||
875 | ret = -EBADF; | ||
876 | filp = fget(mqdes); | 881 | filp = fget(mqdes); |
877 | if (unlikely(!filp)) | 882 | if (unlikely(!filp)) { |
883 | ret = -EBADF; | ||
878 | goto out; | 884 | goto out; |
885 | } | ||
879 | 886 | ||
880 | inode = filp->f_path.dentry->d_inode; | 887 | inode = filp->f_path.dentry->d_inode; |
881 | if (unlikely(filp->f_op != &mqueue_file_operations)) | 888 | if (unlikely(filp->f_op != &mqueue_file_operations)) { |
889 | ret = -EBADF; | ||
882 | goto out_fput; | 890 | goto out_fput; |
891 | } | ||
883 | info = MQUEUE_I(inode); | 892 | info = MQUEUE_I(inode); |
884 | audit_inode(NULL, filp->f_path.dentry); | 893 | audit_inode(NULL, filp->f_path.dentry); |
885 | 894 | ||
886 | if (unlikely(!(filp->f_mode & FMODE_WRITE))) | 895 | if (unlikely(!(filp->f_mode & FMODE_WRITE))) { |
896 | ret = -EBADF; | ||
887 | goto out_fput; | 897 | goto out_fput; |
898 | } | ||
888 | 899 | ||
889 | if (unlikely(msg_len > info->attr.mq_msgsize)) { | 900 | if (unlikely(msg_len > info->attr.mq_msgsize)) { |
890 | ret = -EMSGSIZE; | 901 | ret = -EMSGSIZE; |
@@ -961,19 +972,24 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, | |||
961 | audit_mq_sendrecv(mqdes, msg_len, 0, p); | 972 | audit_mq_sendrecv(mqdes, msg_len, 0, p); |
962 | timeout = prepare_timeout(p); | 973 | timeout = prepare_timeout(p); |
963 | 974 | ||
964 | ret = -EBADF; | ||
965 | filp = fget(mqdes); | 975 | filp = fget(mqdes); |
966 | if (unlikely(!filp)) | 976 | if (unlikely(!filp)) { |
977 | ret = -EBADF; | ||
967 | goto out; | 978 | goto out; |
979 | } | ||
968 | 980 | ||
969 | inode = filp->f_path.dentry->d_inode; | 981 | inode = filp->f_path.dentry->d_inode; |
970 | if (unlikely(filp->f_op != &mqueue_file_operations)) | 982 | if (unlikely(filp->f_op != &mqueue_file_operations)) { |
983 | ret = -EBADF; | ||
971 | goto out_fput; | 984 | goto out_fput; |
985 | } | ||
972 | info = MQUEUE_I(inode); | 986 | info = MQUEUE_I(inode); |
973 | audit_inode(NULL, filp->f_path.dentry); | 987 | audit_inode(NULL, filp->f_path.dentry); |
974 | 988 | ||
975 | if (unlikely(!(filp->f_mode & FMODE_READ))) | 989 | if (unlikely(!(filp->f_mode & FMODE_READ))) { |
990 | ret = -EBADF; | ||
976 | goto out_fput; | 991 | goto out_fput; |
992 | } | ||
977 | 993 | ||
978 | /* checks if buffer is big enough */ | 994 | /* checks if buffer is big enough */ |
979 | if (unlikely(msg_len < info->attr.mq_msgsize)) { | 995 | if (unlikely(msg_len < info->attr.mq_msgsize)) { |
@@ -1063,13 +1079,14 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes, | |||
1063 | 1079 | ||
1064 | /* create the notify skb */ | 1080 | /* create the notify skb */ |
1065 | nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL); | 1081 | nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL); |
1066 | ret = -ENOMEM; | 1082 | if (!nc) { |
1067 | if (!nc) | 1083 | ret = -ENOMEM; |
1068 | goto out; | 1084 | goto out; |
1069 | ret = -EFAULT; | 1085 | } |
1070 | if (copy_from_user(nc->data, | 1086 | if (copy_from_user(nc->data, |
1071 | notification.sigev_value.sival_ptr, | 1087 | notification.sigev_value.sival_ptr, |
1072 | NOTIFY_COOKIE_LEN)) { | 1088 | NOTIFY_COOKIE_LEN)) { |
1089 | ret = -EFAULT; | ||
1073 | goto out; | 1090 | goto out; |
1074 | } | 1091 | } |
1075 | 1092 | ||
@@ -1078,9 +1095,10 @@ SYSCALL_DEFINE2(mq_notify, mqd_t, mqdes, | |||
1078 | /* and attach it to the socket */ | 1095 | /* and attach it to the socket */ |
1079 | retry: | 1096 | retry: |
1080 | filp = fget(notification.sigev_signo); | 1097 | filp = fget(notification.sigev_signo); |
1081 | ret = -EBADF; | 1098 | if (!filp) { |
1082 | if (!filp) | 1099 | ret = -EBADF; |
1083 | goto out; | 1100 | goto out; |
1101 | } | ||
1084 | sock = netlink_getsockbyfilp(filp); | 1102 | sock = netlink_getsockbyfilp(filp); |
1085 | fput(filp); | 1103 | fput(filp); |
1086 | if (IS_ERR(sock)) { | 1104 | if (IS_ERR(sock)) { |
@@ -1092,7 +1110,7 @@ retry: | |||
1092 | timeo = MAX_SCHEDULE_TIMEOUT; | 1110 | timeo = MAX_SCHEDULE_TIMEOUT; |
1093 | ret = netlink_attachskb(sock, nc, &timeo, NULL); | 1111 | ret = netlink_attachskb(sock, nc, &timeo, NULL); |
1094 | if (ret == 1) | 1112 | if (ret == 1) |
1095 | goto retry; | 1113 | goto retry; |
1096 | if (ret) { | 1114 | if (ret) { |
1097 | sock = NULL; | 1115 | sock = NULL; |
1098 | nc = NULL; | 1116 | nc = NULL; |
@@ -1101,14 +1119,17 @@ retry: | |||
1101 | } | 1119 | } |
1102 | } | 1120 | } |
1103 | 1121 | ||
1104 | ret = -EBADF; | ||
1105 | filp = fget(mqdes); | 1122 | filp = fget(mqdes); |
1106 | if (!filp) | 1123 | if (!filp) { |
1124 | ret = -EBADF; | ||
1107 | goto out; | 1125 | goto out; |
1126 | } | ||
1108 | 1127 | ||
1109 | inode = filp->f_path.dentry->d_inode; | 1128 | inode = filp->f_path.dentry->d_inode; |
1110 | if (unlikely(filp->f_op != &mqueue_file_operations)) | 1129 | if (unlikely(filp->f_op != &mqueue_file_operations)) { |
1130 | ret = -EBADF; | ||
1111 | goto out_fput; | 1131 | goto out_fput; |
1132 | } | ||
1112 | info = MQUEUE_I(inode); | 1133 | info = MQUEUE_I(inode); |
1113 | 1134 | ||
1114 | ret = 0; | 1135 | ret = 0; |
@@ -1171,14 +1192,17 @@ SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes, | |||
1171 | return -EINVAL; | 1192 | return -EINVAL; |
1172 | } | 1193 | } |
1173 | 1194 | ||
1174 | ret = -EBADF; | ||
1175 | filp = fget(mqdes); | 1195 | filp = fget(mqdes); |
1176 | if (!filp) | 1196 | if (!filp) { |
1197 | ret = -EBADF; | ||
1177 | goto out; | 1198 | goto out; |
1199 | } | ||
1178 | 1200 | ||
1179 | inode = filp->f_path.dentry->d_inode; | 1201 | inode = filp->f_path.dentry->d_inode; |
1180 | if (unlikely(filp->f_op != &mqueue_file_operations)) | 1202 | if (unlikely(filp->f_op != &mqueue_file_operations)) { |
1203 | ret = -EBADF; | ||
1181 | goto out_fput; | 1204 | goto out_fput; |
1205 | } | ||
1182 | info = MQUEUE_I(inode); | 1206 | info = MQUEUE_I(inode); |
1183 | 1207 | ||
1184 | spin_lock(&info->lock); | 1208 | spin_lock(&info->lock); |
@@ -1272,7 +1296,7 @@ static int __init init_mqueue_fs(void) | |||
1272 | if (mqueue_inode_cachep == NULL) | 1296 | if (mqueue_inode_cachep == NULL) |
1273 | return -ENOMEM; | 1297 | return -ENOMEM; |
1274 | 1298 | ||
1275 | /* ignore failues - they are not fatal */ | 1299 | /* ignore failures - they are not fatal */ |
1276 | mq_sysctl_table = mq_register_sysctl_table(); | 1300 | mq_sysctl_table = mq_register_sysctl_table(); |
1277 | 1301 | ||
1278 | error = register_filesystem(&mqueue_fs_type); | 1302 | error = register_filesystem(&mqueue_fs_type); |
@@ -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..355a3da9ec73 --- /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 | |||
16 | SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, int, 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 | ||