aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/compat.c2
-rw-r--r--ipc/mqueue.c5
-rw-r--r--ipc/msg.c26
-rw-r--r--ipc/sem.c45
-rw-r--r--ipc/shm.c35
-rw-r--r--ipc/util.c29
-rw-r--r--ipc/util.h4
7 files changed, 77 insertions, 69 deletions
diff --git a/ipc/compat.c b/ipc/compat.c
index 1fe95f6659dd..a544dfbb082a 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -30,7 +30,7 @@
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/syscalls.h> 31#include <linux/syscalls.h>
32 32
33#include <asm/semaphore.h> 33#include <linux/mutex.h>
34#include <asm/uaccess.h> 34#include <asm/uaccess.h>
35 35
36#include "util.h" 36#include "util.h"
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index fd2e26b6f966..41ecbd440fed 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -25,6 +25,8 @@
25#include <linux/netlink.h> 25#include <linux/netlink.h>
26#include <linux/syscalls.h> 26#include <linux/syscalls.h>
27#include <linux/signal.h> 27#include <linux/signal.h>
28#include <linux/mutex.h>
29
28#include <net/sock.h> 30#include <net/sock.h>
29#include "util.h" 31#include "util.h"
30 32
@@ -51,7 +53,6 @@
51#define HARD_MSGMAX (131072/sizeof(void*)) 53#define HARD_MSGMAX (131072/sizeof(void*))
52#define DFLT_MSGSIZEMAX 8192 /* max message size */ 54#define DFLT_MSGSIZEMAX 8192 /* max message size */
53 55
54#define NOTIFY_COOKIE_LEN 32
55 56
56struct ext_wait_queue { /* queue of sleeping tasks */ 57struct ext_wait_queue { /* queue of sleeping tasks */
57 struct task_struct *task; 58 struct task_struct *task;
@@ -761,7 +762,7 @@ out_unlock:
761 * The receiver accepts the message and returns without grabbing the queue 762 * The receiver accepts the message and returns without grabbing the queue
762 * spinlock. Therefore an intermediate STATE_PENDING state and memory barriers 763 * spinlock. Therefore an intermediate STATE_PENDING state and memory barriers
763 * are necessary. The same algorithm is used for sysv semaphores, see 764 * are necessary. The same algorithm is used for sysv semaphores, see
764 * ipc/sem.c fore more details. 765 * ipc/sem.c for more details.
765 * 766 *
766 * The same algorithm is used for senders. 767 * The same algorithm is used for senders.
767 */ 768 */
diff --git a/ipc/msg.c b/ipc/msg.c
index fbf757064a32..48a7f17a7236 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -28,6 +28,8 @@
28#include <linux/syscalls.h> 28#include <linux/syscalls.h>
29#include <linux/audit.h> 29#include <linux/audit.h>
30#include <linux/seq_file.h> 30#include <linux/seq_file.h>
31#include <linux/mutex.h>
32
31#include <asm/current.h> 33#include <asm/current.h>
32#include <asm/uaccess.h> 34#include <asm/uaccess.h>
33#include "util.h" 35#include "util.h"
@@ -179,8 +181,8 @@ static void expunge_all(struct msg_queue* msq, int res)
179 * removes the message queue from message queue ID 181 * removes the message queue from message queue ID
180 * array, and cleans up all the messages associated with this queue. 182 * array, and cleans up all the messages associated with this queue.
181 * 183 *
182 * msg_ids.sem and the spinlock for this message queue is hold 184 * msg_ids.mutex and the spinlock for this message queue is hold
183 * before freeque() is called. msg_ids.sem remains locked on exit. 185 * before freeque() is called. msg_ids.mutex remains locked on exit.
184 */ 186 */
185static void freeque (struct msg_queue *msq, int id) 187static void freeque (struct msg_queue *msq, int id)
186{ 188{
@@ -208,7 +210,7 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
208 int id, ret = -EPERM; 210 int id, ret = -EPERM;
209 struct msg_queue *msq; 211 struct msg_queue *msq;
210 212
211 down(&msg_ids.sem); 213 mutex_lock(&msg_ids.mutex);
212 if (key == IPC_PRIVATE) 214 if (key == IPC_PRIVATE)
213 ret = newque(key, msgflg); 215 ret = newque(key, msgflg);
214 else if ((id = ipc_findkey(&msg_ids, key)) == -1) { /* key not used */ 216 else if ((id = ipc_findkey(&msg_ids, key)) == -1) { /* key not used */
@@ -220,8 +222,7 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
220 ret = -EEXIST; 222 ret = -EEXIST;
221 } else { 223 } else {
222 msq = msg_lock(id); 224 msq = msg_lock(id);
223 if(msq==NULL) 225 BUG_ON(msq==NULL);
224 BUG();
225 if (ipcperms(&msq->q_perm, msgflg)) 226 if (ipcperms(&msq->q_perm, msgflg))
226 ret = -EACCES; 227 ret = -EACCES;
227 else { 228 else {
@@ -232,7 +233,7 @@ asmlinkage long sys_msgget (key_t key, int msgflg)
232 } 233 }
233 msg_unlock(msq); 234 msg_unlock(msq);
234 } 235 }
235 up(&msg_ids.sem); 236 mutex_unlock(&msg_ids.mutex);
236 return ret; 237 return ret;
237} 238}
238 239
@@ -362,7 +363,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
362 msginfo.msgmnb = msg_ctlmnb; 363 msginfo.msgmnb = msg_ctlmnb;
363 msginfo.msgssz = MSGSSZ; 364 msginfo.msgssz = MSGSSZ;
364 msginfo.msgseg = MSGSEG; 365 msginfo.msgseg = MSGSEG;
365 down(&msg_ids.sem); 366 mutex_lock(&msg_ids.mutex);
366 if (cmd == MSG_INFO) { 367 if (cmd == MSG_INFO) {
367 msginfo.msgpool = msg_ids.in_use; 368 msginfo.msgpool = msg_ids.in_use;
368 msginfo.msgmap = atomic_read(&msg_hdrs); 369 msginfo.msgmap = atomic_read(&msg_hdrs);
@@ -373,7 +374,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
373 msginfo.msgtql = MSGTQL; 374 msginfo.msgtql = MSGTQL;
374 } 375 }
375 max_id = msg_ids.max_id; 376 max_id = msg_ids.max_id;
376 up(&msg_ids.sem); 377 mutex_unlock(&msg_ids.mutex);
377 if (copy_to_user (buf, &msginfo, sizeof(struct msginfo))) 378 if (copy_to_user (buf, &msginfo, sizeof(struct msginfo)))
378 return -EFAULT; 379 return -EFAULT;
379 return (max_id < 0) ? 0: max_id; 380 return (max_id < 0) ? 0: max_id;
@@ -429,8 +430,6 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
429 return -EFAULT; 430 return -EFAULT;
430 if (copy_msqid_from_user (&setbuf, buf, version)) 431 if (copy_msqid_from_user (&setbuf, buf, version))
431 return -EFAULT; 432 return -EFAULT;
432 if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode)))
433 return err;
434 break; 433 break;
435 case IPC_RMID: 434 case IPC_RMID:
436 break; 435 break;
@@ -438,7 +437,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
438 return -EINVAL; 437 return -EINVAL;
439 } 438 }
440 439
441 down(&msg_ids.sem); 440 mutex_lock(&msg_ids.mutex);
442 msq = msg_lock(msqid); 441 msq = msg_lock(msqid);
443 err=-EINVAL; 442 err=-EINVAL;
444 if (msq == NULL) 443 if (msq == NULL)
@@ -461,6 +460,9 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
461 switch (cmd) { 460 switch (cmd) {
462 case IPC_SET: 461 case IPC_SET:
463 { 462 {
463 if ((err = audit_ipc_perms(setbuf.qbytes, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
464 goto out_unlock_up;
465
464 err = -EPERM; 466 err = -EPERM;
465 if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE)) 467 if (setbuf.qbytes > msg_ctlmnb && !capable(CAP_SYS_RESOURCE))
466 goto out_unlock_up; 468 goto out_unlock_up;
@@ -489,7 +491,7 @@ asmlinkage long sys_msgctl (int msqid, int cmd, struct msqid_ds __user *buf)
489 } 491 }
490 err = 0; 492 err = 0;
491out_up: 493out_up:
492 up(&msg_ids.sem); 494 mutex_unlock(&msg_ids.mutex);
493 return err; 495 return err;
494out_unlock_up: 496out_unlock_up:
495 msg_unlock(msq); 497 msg_unlock(msq);
diff --git a/ipc/sem.c b/ipc/sem.c
index 31fd4027d2b5..642659cd596b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -75,6 +75,8 @@
75#include <linux/audit.h> 75#include <linux/audit.h>
76#include <linux/capability.h> 76#include <linux/capability.h>
77#include <linux/seq_file.h> 77#include <linux/seq_file.h>
78#include <linux/mutex.h>
79
78#include <asm/uaccess.h> 80#include <asm/uaccess.h>
79#include "util.h" 81#include "util.h"
80 82
@@ -139,7 +141,7 @@ void __init sem_init (void)
139 * * if it's IN_WAKEUP, then it must wait until the value changes 141 * * if it's IN_WAKEUP, then it must wait until the value changes
140 * * if it's not -EINTR, then the operation was completed by 142 * * if it's not -EINTR, then the operation was completed by
141 * update_queue. semtimedop can return queue.status without 143 * update_queue. semtimedop can return queue.status without
142 * performing any operation on the semaphore array. 144 * performing any operation on the sem array.
143 * * otherwise it must acquire the spinlock and check what's up. 145 * * otherwise it must acquire the spinlock and check what's up.
144 * 146 *
145 * The two-stage algorithm is necessary to protect against the following 147 * The two-stage algorithm is necessary to protect against the following
@@ -214,7 +216,7 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
214 216
215 if (nsems < 0 || nsems > sc_semmsl) 217 if (nsems < 0 || nsems > sc_semmsl)
216 return -EINVAL; 218 return -EINVAL;
217 down(&sem_ids.sem); 219 mutex_lock(&sem_ids.mutex);
218 220
219 if (key == IPC_PRIVATE) { 221 if (key == IPC_PRIVATE) {
220 err = newary(key, nsems, semflg); 222 err = newary(key, nsems, semflg);
@@ -227,8 +229,7 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
227 err = -EEXIST; 229 err = -EEXIST;
228 } else { 230 } else {
229 sma = sem_lock(id); 231 sma = sem_lock(id);
230 if(sma==NULL) 232 BUG_ON(sma==NULL);
231 BUG();
232 if (nsems > sma->sem_nsems) 233 if (nsems > sma->sem_nsems)
233 err = -EINVAL; 234 err = -EINVAL;
234 else if (ipcperms(&sma->sem_perm, semflg)) 235 else if (ipcperms(&sma->sem_perm, semflg))
@@ -242,7 +243,7 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
242 sem_unlock(sma); 243 sem_unlock(sma);
243 } 244 }
244 245
245 up(&sem_ids.sem); 246 mutex_unlock(&sem_ids.mutex);
246 return err; 247 return err;
247} 248}
248 249
@@ -437,8 +438,8 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
437 return semzcnt; 438 return semzcnt;
438} 439}
439 440
440/* Free a semaphore set. freeary() is called with sem_ids.sem down and 441/* Free a semaphore set. freeary() is called with sem_ids.mutex locked and
441 * the spinlock for this semaphore set hold. sem_ids.sem remains locked 442 * the spinlock for this semaphore set hold. sem_ids.mutex remains locked
442 * on exit. 443 * on exit.
443 */ 444 */
444static void freeary (struct sem_array *sma, int id) 445static void freeary (struct sem_array *sma, int id)
@@ -525,7 +526,7 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
525 seminfo.semmnu = SEMMNU; 526 seminfo.semmnu = SEMMNU;
526 seminfo.semmap = SEMMAP; 527 seminfo.semmap = SEMMAP;
527 seminfo.semume = SEMUME; 528 seminfo.semume = SEMUME;
528 down(&sem_ids.sem); 529 mutex_lock(&sem_ids.mutex);
529 if (cmd == SEM_INFO) { 530 if (cmd == SEM_INFO) {
530 seminfo.semusz = sem_ids.in_use; 531 seminfo.semusz = sem_ids.in_use;
531 seminfo.semaem = used_sems; 532 seminfo.semaem = used_sems;
@@ -534,7 +535,7 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
534 seminfo.semaem = SEMAEM; 535 seminfo.semaem = SEMAEM;
535 } 536 }
536 max_id = sem_ids.max_id; 537 max_id = sem_ids.max_id;
537 up(&sem_ids.sem); 538 mutex_unlock(&sem_ids.mutex);
538 if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo))) 539 if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo)))
539 return -EFAULT; 540 return -EFAULT;
540 return (max_id < 0) ? 0: max_id; 541 return (max_id < 0) ? 0: max_id;
@@ -809,8 +810,6 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
809 if(cmd == IPC_SET) { 810 if(cmd == IPC_SET) {
810 if(copy_semid_from_user (&setbuf, arg.buf, version)) 811 if(copy_semid_from_user (&setbuf, arg.buf, version))
811 return -EFAULT; 812 return -EFAULT;
812 if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode)))
813 return err;
814 } 813 }
815 sma = sem_lock(semid); 814 sma = sem_lock(semid);
816 if(sma==NULL) 815 if(sma==NULL)
@@ -821,7 +820,6 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
821 goto out_unlock; 820 goto out_unlock;
822 } 821 }
823 ipcp = &sma->sem_perm; 822 ipcp = &sma->sem_perm;
824
825 if (current->euid != ipcp->cuid && 823 if (current->euid != ipcp->cuid &&
826 current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) { 824 current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
827 err=-EPERM; 825 err=-EPERM;
@@ -838,6 +836,8 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
838 err = 0; 836 err = 0;
839 break; 837 break;
840 case IPC_SET: 838 case IPC_SET:
839 if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode, ipcp)))
840 goto out_unlock;
841 ipcp->uid = setbuf.uid; 841 ipcp->uid = setbuf.uid;
842 ipcp->gid = setbuf.gid; 842 ipcp->gid = setbuf.gid;
843 ipcp->mode = (ipcp->mode & ~S_IRWXUGO) 843 ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
@@ -886,9 +886,9 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
886 return err; 886 return err;
887 case IPC_RMID: 887 case IPC_RMID:
888 case IPC_SET: 888 case IPC_SET:
889 down(&sem_ids.sem); 889 mutex_lock(&sem_ids.mutex);
890 err = semctl_down(semid,semnum,cmd,version,arg); 890 err = semctl_down(semid,semnum,cmd,version,arg);
891 up(&sem_ids.sem); 891 mutex_unlock(&sem_ids.mutex);
892 return err; 892 return err;
893 default: 893 default:
894 return -EINVAL; 894 return -EINVAL;
@@ -1182,8 +1182,7 @@ retry_undos:
1182 1182
1183 sma = sem_lock(semid); 1183 sma = sem_lock(semid);
1184 if(sma==NULL) { 1184 if(sma==NULL) {
1185 if(queue.prev != NULL) 1185 BUG_ON(queue.prev != NULL);
1186 BUG();
1187 error = -EIDRM; 1186 error = -EIDRM;
1188 goto out_free; 1187 goto out_free;
1189 } 1188 }
@@ -1300,9 +1299,9 @@ found:
1300 /* perform adjustments registered in u */ 1299 /* perform adjustments registered in u */
1301 nsems = sma->sem_nsems; 1300 nsems = sma->sem_nsems;
1302 for (i = 0; i < nsems; i++) { 1301 for (i = 0; i < nsems; i++) {
1303 struct sem * sem = &sma->sem_base[i]; 1302 struct sem * semaphore = &sma->sem_base[i];
1304 if (u->semadj[i]) { 1303 if (u->semadj[i]) {
1305 sem->semval += u->semadj[i]; 1304 semaphore->semval += u->semadj[i];
1306 /* 1305 /*
1307 * Range checks of the new semaphore value, 1306 * Range checks of the new semaphore value,
1308 * not defined by sus: 1307 * not defined by sus:
@@ -1316,11 +1315,11 @@ found:
1316 * 1315 *
1317 * Manfred <manfred@colorfullife.com> 1316 * Manfred <manfred@colorfullife.com>
1318 */ 1317 */
1319 if (sem->semval < 0) 1318 if (semaphore->semval < 0)
1320 sem->semval = 0; 1319 semaphore->semval = 0;
1321 if (sem->semval > SEMVMX) 1320 if (semaphore->semval > SEMVMX)
1322 sem->semval = SEMVMX; 1321 semaphore->semval = SEMVMX;
1323 sem->sempid = current->tgid; 1322 semaphore->sempid = current->tgid;
1324 } 1323 }
1325 } 1324 }
1326 sma->sem_otime = get_seconds(); 1325 sma->sem_otime = get_seconds();
diff --git a/ipc/shm.c b/ipc/shm.c
index 9162123a7b23..f806a2e314e0 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -30,6 +30,7 @@
30#include <linux/capability.h> 30#include <linux/capability.h>
31#include <linux/ptrace.h> 31#include <linux/ptrace.h>
32#include <linux/seq_file.h> 32#include <linux/seq_file.h>
33#include <linux/mutex.h>
33 34
34#include <asm/uaccess.h> 35#include <asm/uaccess.h>
35 36
@@ -109,7 +110,7 @@ static void shm_open (struct vm_area_struct *shmd)
109 * 110 *
110 * @shp: struct to free 111 * @shp: struct to free
111 * 112 *
112 * It has to be called with shp and shm_ids.sem locked, 113 * It has to be called with shp and shm_ids.mutex locked,
113 * but returns with shp unlocked and freed. 114 * but returns with shp unlocked and freed.
114 */ 115 */
115static void shm_destroy (struct shmid_kernel *shp) 116static void shm_destroy (struct shmid_kernel *shp)
@@ -139,7 +140,7 @@ static void shm_close (struct vm_area_struct *shmd)
139 int id = file->f_dentry->d_inode->i_ino; 140 int id = file->f_dentry->d_inode->i_ino;
140 struct shmid_kernel *shp; 141 struct shmid_kernel *shp;
141 142
142 down (&shm_ids.sem); 143 mutex_lock(&shm_ids.mutex);
143 /* remove from the list of attaches of the shm segment */ 144 /* remove from the list of attaches of the shm segment */
144 if(!(shp = shm_lock(id))) 145 if(!(shp = shm_lock(id)))
145 BUG(); 146 BUG();
@@ -151,7 +152,7 @@ static void shm_close (struct vm_area_struct *shmd)
151 shm_destroy (shp); 152 shm_destroy (shp);
152 else 153 else
153 shm_unlock(shp); 154 shm_unlock(shp);
154 up (&shm_ids.sem); 155 mutex_unlock(&shm_ids.mutex);
155} 156}
156 157
157static int shm_mmap(struct file * file, struct vm_area_struct * vma) 158static int shm_mmap(struct file * file, struct vm_area_struct * vma)
@@ -270,7 +271,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
270 struct shmid_kernel *shp; 271 struct shmid_kernel *shp;
271 int err, id = 0; 272 int err, id = 0;
272 273
273 down(&shm_ids.sem); 274 mutex_lock(&shm_ids.mutex);
274 if (key == IPC_PRIVATE) { 275 if (key == IPC_PRIVATE) {
275 err = newseg(key, shmflg, size); 276 err = newseg(key, shmflg, size);
276 } else if ((id = ipc_findkey(&shm_ids, key)) == -1) { 277 } else if ((id = ipc_findkey(&shm_ids, key)) == -1) {
@@ -296,7 +297,7 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg)
296 } 297 }
297 shm_unlock(shp); 298 shm_unlock(shp);
298 } 299 }
299 up(&shm_ids.sem); 300 mutex_unlock(&shm_ids.mutex);
300 301
301 return err; 302 return err;
302} 303}
@@ -467,14 +468,14 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
467 return err; 468 return err;
468 469
469 memset(&shm_info,0,sizeof(shm_info)); 470 memset(&shm_info,0,sizeof(shm_info));
470 down(&shm_ids.sem); 471 mutex_lock(&shm_ids.mutex);
471 shm_info.used_ids = shm_ids.in_use; 472 shm_info.used_ids = shm_ids.in_use;
472 shm_get_stat (&shm_info.shm_rss, &shm_info.shm_swp); 473 shm_get_stat (&shm_info.shm_rss, &shm_info.shm_swp);
473 shm_info.shm_tot = shm_tot; 474 shm_info.shm_tot = shm_tot;
474 shm_info.swap_attempts = 0; 475 shm_info.swap_attempts = 0;
475 shm_info.swap_successes = 0; 476 shm_info.swap_successes = 0;
476 err = shm_ids.max_id; 477 err = shm_ids.max_id;
477 up(&shm_ids.sem); 478 mutex_unlock(&shm_ids.mutex);
478 if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { 479 if(copy_to_user (buf, &shm_info, sizeof(shm_info))) {
479 err = -EFAULT; 480 err = -EFAULT;
480 goto out; 481 goto out;
@@ -583,7 +584,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
583 * Instead we set a destroyed flag, and then blow 584 * Instead we set a destroyed flag, and then blow
584 * the name away when the usage hits zero. 585 * the name away when the usage hits zero.
585 */ 586 */
586 down(&shm_ids.sem); 587 mutex_lock(&shm_ids.mutex);
587 shp = shm_lock(shmid); 588 shp = shm_lock(shmid);
588 err = -EINVAL; 589 err = -EINVAL;
589 if (shp == NULL) 590 if (shp == NULL)
@@ -610,7 +611,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
610 shm_unlock(shp); 611 shm_unlock(shp);
611 } else 612 } else
612 shm_destroy (shp); 613 shm_destroy (shp);
613 up(&shm_ids.sem); 614 mutex_unlock(&shm_ids.mutex);
614 goto out; 615 goto out;
615 } 616 }
616 617
@@ -620,13 +621,14 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
620 err = -EFAULT; 621 err = -EFAULT;
621 goto out; 622 goto out;
622 } 623 }
623 if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid, setbuf.mode))) 624 mutex_lock(&shm_ids.mutex);
624 return err;
625 down(&shm_ids.sem);
626 shp = shm_lock(shmid); 625 shp = shm_lock(shmid);
627 err=-EINVAL; 626 err=-EINVAL;
628 if(shp==NULL) 627 if(shp==NULL)
629 goto out_up; 628 goto out_up;
629 if ((err = audit_ipc_perms(0, setbuf.uid, setbuf.gid,
630 setbuf.mode, &(shp->shm_perm))))
631 goto out_unlock_up;
630 err = shm_checkid(shp,shmid); 632 err = shm_checkid(shp,shmid);
631 if(err) 633 if(err)
632 goto out_unlock_up; 634 goto out_unlock_up;
@@ -658,7 +660,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
658out_unlock_up: 660out_unlock_up:
659 shm_unlock(shp); 661 shm_unlock(shp);
660out_up: 662out_up:
661 up(&shm_ids.sem); 663 mutex_unlock(&shm_ids.mutex);
662 goto out; 664 goto out;
663out_unlock: 665out_unlock:
664 shm_unlock(shp); 666 shm_unlock(shp);
@@ -771,7 +773,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
771invalid: 773invalid:
772 up_write(&current->mm->mmap_sem); 774 up_write(&current->mm->mmap_sem);
773 775
774 down (&shm_ids.sem); 776 mutex_lock(&shm_ids.mutex);
775 if(!(shp = shm_lock(shmid))) 777 if(!(shp = shm_lock(shmid)))
776 BUG(); 778 BUG();
777 shp->shm_nattch--; 779 shp->shm_nattch--;
@@ -780,7 +782,7 @@ invalid:
780 shm_destroy (shp); 782 shm_destroy (shp);
781 else 783 else
782 shm_unlock(shp); 784 shm_unlock(shp);
783 up (&shm_ids.sem); 785 mutex_unlock(&shm_ids.mutex);
784 786
785 *raddr = (unsigned long) user_addr; 787 *raddr = (unsigned long) user_addr;
786 err = 0; 788 err = 0;
@@ -814,6 +816,9 @@ asmlinkage long sys_shmdt(char __user *shmaddr)
814 loff_t size = 0; 816 loff_t size = 0;
815 int retval = -EINVAL; 817 int retval = -EINVAL;
816 818
819 if (addr & ~PAGE_MASK)
820 return retval;
821
817 down_write(&mm->mmap_sem); 822 down_write(&mm->mmap_sem);
818 823
819 /* 824 /*
diff --git a/ipc/util.c b/ipc/util.c
index 862621980b01..23151ef32590 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -68,7 +68,8 @@ __initcall(ipc_init);
68void __init ipc_init_ids(struct ipc_ids* ids, int size) 68void __init ipc_init_ids(struct ipc_ids* ids, int size)
69{ 69{
70 int i; 70 int i;
71 sema_init(&ids->sem,1); 71
72 mutex_init(&ids->mutex);
72 73
73 if(size > IPCMNI) 74 if(size > IPCMNI)
74 size = IPCMNI; 75 size = IPCMNI;
@@ -138,7 +139,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
138 * @ids: Identifier set 139 * @ids: Identifier set
139 * @key: The key to find 140 * @key: The key to find
140 * 141 *
141 * Requires ipc_ids.sem locked. 142 * Requires ipc_ids.mutex locked.
142 * Returns the identifier if found or -1 if not. 143 * Returns the identifier if found or -1 if not.
143 */ 144 */
144 145
@@ -150,7 +151,7 @@ int ipc_findkey(struct ipc_ids* ids, key_t key)
150 151
151 /* 152 /*
152 * rcu_dereference() is not needed here 153 * rcu_dereference() is not needed here
153 * since ipc_ids.sem is held 154 * since ipc_ids.mutex is held
154 */ 155 */
155 for (id = 0; id <= max_id; id++) { 156 for (id = 0; id <= max_id; id++) {
156 p = ids->entries->p[id]; 157 p = ids->entries->p[id];
@@ -163,7 +164,7 @@ int ipc_findkey(struct ipc_ids* ids, key_t key)
163} 164}
164 165
165/* 166/*
166 * Requires ipc_ids.sem locked 167 * Requires ipc_ids.mutex locked
167 */ 168 */
168static int grow_ary(struct ipc_ids* ids, int newsize) 169static int grow_ary(struct ipc_ids* ids, int newsize)
169{ 170{
@@ -210,7 +211,7 @@ static int grow_ary(struct ipc_ids* ids, int newsize)
210 * is returned. The list is returned in a locked state on success. 211 * is returned. The list is returned in a locked state on success.
211 * On failure the list is not locked and -1 is returned. 212 * On failure the list is not locked and -1 is returned.
212 * 213 *
213 * Called with ipc_ids.sem held. 214 * Called with ipc_ids.mutex held.
214 */ 215 */
215 216
216int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) 217int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
@@ -221,7 +222,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
221 222
222 /* 223 /*
223 * rcu_dereference()() is not needed here since 224 * rcu_dereference()() is not needed here since
224 * ipc_ids.sem is held 225 * ipc_ids.mutex is held
225 */ 226 */
226 for (id = 0; id < size; id++) { 227 for (id = 0; id < size; id++) {
227 if(ids->entries->p[id] == NULL) 228 if(ids->entries->p[id] == NULL)
@@ -257,7 +258,7 @@ found:
257 * fed an invalid identifier. The entry is removed and internal 258 * fed an invalid identifier. The entry is removed and internal
258 * variables recomputed. The object associated with the identifier 259 * variables recomputed. The object associated with the identifier
259 * is returned. 260 * is returned.
260 * ipc_ids.sem and the spinlock for this ID is hold before this function 261 * ipc_ids.mutex and the spinlock for this ID is hold before this function
261 * is called, and remain locked on the exit. 262 * is called, and remain locked on the exit.
262 */ 263 */
263 264
@@ -270,7 +271,7 @@ struct kern_ipc_perm* ipc_rmid(struct ipc_ids* ids, int id)
270 271
271 /* 272 /*
272 * do not need a rcu_dereference()() here to force ordering 273 * do not need a rcu_dereference()() here to force ordering
273 * on Alpha, since the ipc_ids.sem is held. 274 * on Alpha, since the ipc_ids.mutex is held.
274 */ 275 */
275 p = ids->entries->p[lid]; 276 p = ids->entries->p[lid];
276 ids->entries->p[lid] = NULL; 277 ids->entries->p[lid] = NULL;
@@ -530,13 +531,13 @@ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
530 531
531/* 532/*
532 * So far only shm_get_stat() calls ipc_get() via shm_get(), so ipc_get() 533 * So far only shm_get_stat() calls ipc_get() via shm_get(), so ipc_get()
533 * is called with shm_ids.sem locked. Since grow_ary() is also called with 534 * is called with shm_ids.mutex locked. Since grow_ary() is also called with
534 * shm_ids.sem down(for Shared Memory), there is no need to add read 535 * shm_ids.mutex down(for Shared Memory), there is no need to add read
535 * barriers here to gurantee the writes in grow_ary() are seen in order 536 * barriers here to gurantee the writes in grow_ary() are seen in order
536 * here (for Alpha). 537 * here (for Alpha).
537 * 538 *
538 * However ipc_get() itself does not necessary require ipc_ids.sem down. So 539 * However ipc_get() itself does not necessary require ipc_ids.mutex down. So
539 * if in the future ipc_get() is used by other places without ipc_ids.sem 540 * if in the future ipc_get() is used by other places without ipc_ids.mutex
540 * down, then ipc_get() needs read memery barriers as ipc_lock() does. 541 * down, then ipc_get() needs read memery barriers as ipc_lock() does.
541 */ 542 */
542struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id) 543struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id)
@@ -667,7 +668,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
667 * Take the lock - this will be released by the corresponding 668 * Take the lock - this will be released by the corresponding
668 * call to stop(). 669 * call to stop().
669 */ 670 */
670 down(&iface->ids->sem); 671 mutex_lock(&iface->ids->mutex);
671 672
672 /* pos < 0 is invalid */ 673 /* pos < 0 is invalid */
673 if (*pos < 0) 674 if (*pos < 0)
@@ -697,7 +698,7 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it)
697 ipc_unlock(ipc); 698 ipc_unlock(ipc);
698 699
699 /* Release the lock we took in start() */ 700 /* Release the lock we took in start() */
700 up(&iface->ids->sem); 701 mutex_unlock(&iface->ids->mutex);
701} 702}
702 703
703static int sysvipc_proc_show(struct seq_file *s, void *it) 704static int sysvipc_proc_show(struct seq_file *s, void *it)
diff --git a/ipc/util.h b/ipc/util.h
index efaff3ee7de7..0181553d31d8 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -25,7 +25,7 @@ struct ipc_ids {
25 int max_id; 25 int max_id;
26 unsigned short seq; 26 unsigned short seq;
27 unsigned short seq_max; 27 unsigned short seq_max;
28 struct semaphore sem; 28 struct mutex mutex;
29 struct ipc_id_ary nullentry; 29 struct ipc_id_ary nullentry;
30 struct ipc_id_ary* entries; 30 struct ipc_id_ary* entries;
31}; 31};
@@ -40,7 +40,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
40#define ipc_init_proc_interface(path, header, ids, show) do {} while (0) 40#define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
41#endif 41#endif
42 42
43/* must be called with ids->sem acquired.*/ 43/* must be called with ids->mutex acquired.*/
44int ipc_findkey(struct ipc_ids* ids, key_t key); 44int ipc_findkey(struct ipc_ids* ids, key_t key);
45int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size); 45int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size);
46 46