aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/sem.c201
1 files changed, 130 insertions, 71 deletions
diff --git a/ipc/sem.c b/ipc/sem.c
index 6013c751156f..69edeb1e2a65 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -64,6 +64,10 @@
64 * 64 *
65 * support for audit of ipc object properties and permission changes 65 * support for audit of ipc object properties and permission changes
66 * Dustin Kirkland <dustin.kirkland@us.ibm.com> 66 * Dustin Kirkland <dustin.kirkland@us.ibm.com>
67 *
68 * namespaces support
69 * OpenVZ, SWsoft Inc.
70 * Pavel Emelianov <xemul@openvz.org>
67 */ 71 */
68 72
69#include <linux/slab.h> 73#include <linux/slab.h>
@@ -78,22 +82,25 @@
78#include <linux/capability.h> 82#include <linux/capability.h>
79#include <linux/seq_file.h> 83#include <linux/seq_file.h>
80#include <linux/mutex.h> 84#include <linux/mutex.h>
85#include <linux/nsproxy.h>
81 86
82#include <asm/uaccess.h> 87#include <asm/uaccess.h>
83#include "util.h" 88#include "util.h"
84 89
90#define sem_ids(ns) (*((ns)->ids[IPC_SEM_IDS]))
91
92#define sem_lock(ns, id) ((struct sem_array*)ipc_lock(&sem_ids(ns), id))
93#define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm)
94#define sem_rmid(ns, id) ((struct sem_array*)ipc_rmid(&sem_ids(ns), id))
95#define sem_checkid(ns, sma, semid) \
96 ipc_checkid(&sem_ids(ns),&sma->sem_perm,semid)
97#define sem_buildid(ns, id, seq) \
98 ipc_buildid(&sem_ids(ns), id, seq)
85 99
86#define sem_lock(id) ((struct sem_array*)ipc_lock(&sem_ids,id)) 100static struct ipc_ids init_sem_ids;
87#define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm)
88#define sem_rmid(id) ((struct sem_array*)ipc_rmid(&sem_ids,id))
89#define sem_checkid(sma, semid) \
90 ipc_checkid(&sem_ids,&sma->sem_perm,semid)
91#define sem_buildid(id, seq) \
92 ipc_buildid(&sem_ids, id, seq)
93static struct ipc_ids sem_ids;
94 101
95static int newary (key_t, int, int); 102static int newary(struct ipc_namespace *, key_t, int, int);
96static void freeary (struct sem_array *sma, int id); 103static void freeary(struct ipc_namespace *ns, struct sem_array *sma, int id);
97#ifdef CONFIG_PROC_FS 104#ifdef CONFIG_PROC_FS
98static int sysvipc_sem_proc_show(struct seq_file *s, void *it); 105static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
99#endif 106#endif
@@ -110,22 +117,61 @@ static int sysvipc_sem_proc_show(struct seq_file *s, void *it);
110 * 117 *
111 */ 118 */
112 119
113int sem_ctls[4] = {SEMMSL, SEMMNS, SEMOPM, SEMMNI}; 120#define sc_semmsl sem_ctls[0]
114#define sc_semmsl (sem_ctls[0]) 121#define sc_semmns sem_ctls[1]
115#define sc_semmns (sem_ctls[1]) 122#define sc_semopm sem_ctls[2]
116#define sc_semopm (sem_ctls[2]) 123#define sc_semmni sem_ctls[3]
117#define sc_semmni (sem_ctls[3]) 124
125static void __ipc_init __sem_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
126{
127 ns->ids[IPC_SEM_IDS] = ids;
128 ns->sc_semmsl = SEMMSL;
129 ns->sc_semmns = SEMMNS;
130 ns->sc_semopm = SEMOPM;
131 ns->sc_semmni = SEMMNI;
132 ns->used_sems = 0;
133 ipc_init_ids(ids, ns->sc_semmni);
134}
135
136#ifdef CONFIG_IPC_NS
137int sem_init_ns(struct ipc_namespace *ns)
138{
139 struct ipc_ids *ids;
140
141 ids = kmalloc(sizeof(struct ipc_ids), GFP_KERNEL);
142 if (ids == NULL)
143 return -ENOMEM;
144
145 __sem_init_ns(ns, ids);
146 return 0;
147}
148
149void sem_exit_ns(struct ipc_namespace *ns)
150{
151 int i;
152 struct sem_array *sma;
153
154 mutex_lock(&sem_ids(ns).mutex);
155 for (i = 0; i <= sem_ids(ns).max_id; i++) {
156 sma = sem_lock(ns, i);
157 if (sma == NULL)
158 continue;
159
160 freeary(ns, sma, i);
161 }
162 mutex_unlock(&sem_ids(ns).mutex);
118 163
119static int used_sems; 164 kfree(ns->ids[IPC_SEM_IDS]);
165 ns->ids[IPC_SEM_IDS] = NULL;
166}
167#endif
120 168
121void __init sem_init (void) 169void __init sem_init (void)
122{ 170{
123 used_sems = 0; 171 __sem_init_ns(&init_ipc_ns, &init_sem_ids);
124 ipc_init_ids(&sem_ids,sc_semmni);
125 ipc_init_proc_interface("sysvipc/sem", 172 ipc_init_proc_interface("sysvipc/sem",
126 " key semid perms nsems uid gid cuid cgid otime ctime\n", 173 " key semid perms nsems uid gid cuid cgid otime ctime\n",
127 &sem_ids, 174 IPC_SEM_IDS, sysvipc_sem_proc_show);
128 sysvipc_sem_proc_show);
129} 175}
130 176
131/* 177/*
@@ -162,7 +208,7 @@ void __init sem_init (void)
162 */ 208 */
163#define IN_WAKEUP 1 209#define IN_WAKEUP 1
164 210
165static int newary (key_t key, int nsems, int semflg) 211static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg)
166{ 212{
167 int id; 213 int id;
168 int retval; 214 int retval;
@@ -171,7 +217,7 @@ static int newary (key_t key, int nsems, int semflg)
171 217
172 if (!nsems) 218 if (!nsems)
173 return -EINVAL; 219 return -EINVAL;
174 if (used_sems + nsems > sc_semmns) 220 if (ns->used_sems + nsems > ns->sc_semmns)
175 return -ENOSPC; 221 return -ENOSPC;
176 222
177 size = sizeof (*sma) + nsems * sizeof (struct sem); 223 size = sizeof (*sma) + nsems * sizeof (struct sem);
@@ -191,15 +237,15 @@ static int newary (key_t key, int nsems, int semflg)
191 return retval; 237 return retval;
192 } 238 }
193 239
194 id = ipc_addid(&sem_ids, &sma->sem_perm, sc_semmni); 240 id = ipc_addid(&sem_ids(ns), &sma->sem_perm, ns->sc_semmni);
195 if(id == -1) { 241 if(id == -1) {
196 security_sem_free(sma); 242 security_sem_free(sma);
197 ipc_rcu_putref(sma); 243 ipc_rcu_putref(sma);
198 return -ENOSPC; 244 return -ENOSPC;
199 } 245 }
200 used_sems += nsems; 246 ns->used_sems += nsems;
201 247
202 sma->sem_id = sem_buildid(id, sma->sem_perm.seq); 248 sma->sem_id = sem_buildid(ns, id, sma->sem_perm.seq);
203 sma->sem_base = (struct sem *) &sma[1]; 249 sma->sem_base = (struct sem *) &sma[1];
204 /* sma->sem_pending = NULL; */ 250 /* sma->sem_pending = NULL; */
205 sma->sem_pending_last = &sma->sem_pending; 251 sma->sem_pending_last = &sma->sem_pending;
@@ -215,29 +261,32 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
215{ 261{
216 int id, err = -EINVAL; 262 int id, err = -EINVAL;
217 struct sem_array *sma; 263 struct sem_array *sma;
264 struct ipc_namespace *ns;
265
266 ns = current->nsproxy->ipc_ns;
218 267
219 if (nsems < 0 || nsems > sc_semmsl) 268 if (nsems < 0 || nsems > ns->sc_semmsl)
220 return -EINVAL; 269 return -EINVAL;
221 mutex_lock(&sem_ids.mutex); 270 mutex_lock(&sem_ids(ns).mutex);
222 271
223 if (key == IPC_PRIVATE) { 272 if (key == IPC_PRIVATE) {
224 err = newary(key, nsems, semflg); 273 err = newary(ns, key, nsems, semflg);
225 } else if ((id = ipc_findkey(&sem_ids, key)) == -1) { /* key not used */ 274 } else if ((id = ipc_findkey(&sem_ids(ns), key)) == -1) { /* key not used */
226 if (!(semflg & IPC_CREAT)) 275 if (!(semflg & IPC_CREAT))
227 err = -ENOENT; 276 err = -ENOENT;
228 else 277 else
229 err = newary(key, nsems, semflg); 278 err = newary(ns, key, nsems, semflg);
230 } else if (semflg & IPC_CREAT && semflg & IPC_EXCL) { 279 } else if (semflg & IPC_CREAT && semflg & IPC_EXCL) {
231 err = -EEXIST; 280 err = -EEXIST;
232 } else { 281 } else {
233 sma = sem_lock(id); 282 sma = sem_lock(ns, id);
234 BUG_ON(sma==NULL); 283 BUG_ON(sma==NULL);
235 if (nsems > sma->sem_nsems) 284 if (nsems > sma->sem_nsems)
236 err = -EINVAL; 285 err = -EINVAL;
237 else if (ipcperms(&sma->sem_perm, semflg)) 286 else if (ipcperms(&sma->sem_perm, semflg))
238 err = -EACCES; 287 err = -EACCES;
239 else { 288 else {
240 int semid = sem_buildid(id, sma->sem_perm.seq); 289 int semid = sem_buildid(ns, id, sma->sem_perm.seq);
241 err = security_sem_associate(sma, semflg); 290 err = security_sem_associate(sma, semflg);
242 if (!err) 291 if (!err)
243 err = semid; 292 err = semid;
@@ -245,7 +294,7 @@ asmlinkage long sys_semget (key_t key, int nsems, int semflg)
245 sem_unlock(sma); 294 sem_unlock(sma);
246 } 295 }
247 296
248 mutex_unlock(&sem_ids.mutex); 297 mutex_unlock(&sem_ids(ns).mutex);
249 return err; 298 return err;
250} 299}
251 300
@@ -444,7 +493,7 @@ static int count_semzcnt (struct sem_array * sma, ushort semnum)
444 * the spinlock for this semaphore set hold. sem_ids.mutex remains locked 493 * the spinlock for this semaphore set hold. sem_ids.mutex remains locked
445 * on exit. 494 * on exit.
446 */ 495 */
447static void freeary (struct sem_array *sma, int id) 496static void freeary (struct ipc_namespace *ns, struct sem_array *sma, int id)
448{ 497{
449 struct sem_undo *un; 498 struct sem_undo *un;
450 struct sem_queue *q; 499 struct sem_queue *q;
@@ -472,10 +521,10 @@ static void freeary (struct sem_array *sma, int id)
472 } 521 }
473 522
474 /* Remove the semaphore set from the ID array*/ 523 /* Remove the semaphore set from the ID array*/
475 sma = sem_rmid(id); 524 sma = sem_rmid(ns, id);
476 sem_unlock(sma); 525 sem_unlock(sma);
477 526
478 used_sems -= sma->sem_nsems; 527 ns->used_sems -= sma->sem_nsems;
479 size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem); 528 size = sizeof (*sma) + sma->sem_nsems * sizeof (struct sem);
480 security_sem_free(sma); 529 security_sem_free(sma);
481 ipc_rcu_putref(sma); 530 ipc_rcu_putref(sma);
@@ -503,7 +552,8 @@ static unsigned long copy_semid_to_user(void __user *buf, struct semid64_ds *in,
503 } 552 }
504} 553}
505 554
506static int semctl_nolock(int semid, int semnum, int cmd, int version, union semun arg) 555static int semctl_nolock(struct ipc_namespace *ns, int semid, int semnum,
556 int cmd, int version, union semun arg)
507{ 557{
508 int err = -EINVAL; 558 int err = -EINVAL;
509 struct sem_array *sma; 559 struct sem_array *sma;
@@ -520,24 +570,24 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
520 return err; 570 return err;
521 571
522 memset(&seminfo,0,sizeof(seminfo)); 572 memset(&seminfo,0,sizeof(seminfo));
523 seminfo.semmni = sc_semmni; 573 seminfo.semmni = ns->sc_semmni;
524 seminfo.semmns = sc_semmns; 574 seminfo.semmns = ns->sc_semmns;
525 seminfo.semmsl = sc_semmsl; 575 seminfo.semmsl = ns->sc_semmsl;
526 seminfo.semopm = sc_semopm; 576 seminfo.semopm = ns->sc_semopm;
527 seminfo.semvmx = SEMVMX; 577 seminfo.semvmx = SEMVMX;
528 seminfo.semmnu = SEMMNU; 578 seminfo.semmnu = SEMMNU;
529 seminfo.semmap = SEMMAP; 579 seminfo.semmap = SEMMAP;
530 seminfo.semume = SEMUME; 580 seminfo.semume = SEMUME;
531 mutex_lock(&sem_ids.mutex); 581 mutex_lock(&sem_ids(ns).mutex);
532 if (cmd == SEM_INFO) { 582 if (cmd == SEM_INFO) {
533 seminfo.semusz = sem_ids.in_use; 583 seminfo.semusz = sem_ids(ns).in_use;
534 seminfo.semaem = used_sems; 584 seminfo.semaem = ns->used_sems;
535 } else { 585 } else {
536 seminfo.semusz = SEMUSZ; 586 seminfo.semusz = SEMUSZ;
537 seminfo.semaem = SEMAEM; 587 seminfo.semaem = SEMAEM;
538 } 588 }
539 max_id = sem_ids.max_id; 589 max_id = sem_ids(ns).max_id;
540 mutex_unlock(&sem_ids.mutex); 590 mutex_unlock(&sem_ids(ns).mutex);
541 if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo))) 591 if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo)))
542 return -EFAULT; 592 return -EFAULT;
543 return (max_id < 0) ? 0: max_id; 593 return (max_id < 0) ? 0: max_id;
@@ -547,12 +597,12 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
547 struct semid64_ds tbuf; 597 struct semid64_ds tbuf;
548 int id; 598 int id;
549 599
550 if(semid >= sem_ids.entries->size) 600 if(semid >= sem_ids(ns).entries->size)
551 return -EINVAL; 601 return -EINVAL;
552 602
553 memset(&tbuf,0,sizeof(tbuf)); 603 memset(&tbuf,0,sizeof(tbuf));
554 604
555 sma = sem_lock(semid); 605 sma = sem_lock(ns, semid);
556 if(sma == NULL) 606 if(sma == NULL)
557 return -EINVAL; 607 return -EINVAL;
558 608
@@ -564,7 +614,7 @@ static int semctl_nolock(int semid, int semnum, int cmd, int version, union semu
564 if (err) 614 if (err)
565 goto out_unlock; 615 goto out_unlock;
566 616
567 id = sem_buildid(semid, sma->sem_perm.seq); 617 id = sem_buildid(ns, semid, sma->sem_perm.seq);
568 618
569 kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm); 619 kernel_to_ipc64_perm(&sma->sem_perm, &tbuf.sem_perm);
570 tbuf.sem_otime = sma->sem_otime; 620 tbuf.sem_otime = sma->sem_otime;
@@ -584,7 +634,8 @@ out_unlock:
584 return err; 634 return err;
585} 635}
586 636
587static int semctl_main(int semid, int semnum, int cmd, int version, union semun arg) 637static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,
638 int cmd, int version, union semun arg)
588{ 639{
589 struct sem_array *sma; 640 struct sem_array *sma;
590 struct sem* curr; 641 struct sem* curr;
@@ -593,14 +644,14 @@ static int semctl_main(int semid, int semnum, int cmd, int version, union semun
593 ushort* sem_io = fast_sem_io; 644 ushort* sem_io = fast_sem_io;
594 int nsems; 645 int nsems;
595 646
596 sma = sem_lock(semid); 647 sma = sem_lock(ns, semid);
597 if(sma==NULL) 648 if(sma==NULL)
598 return -EINVAL; 649 return -EINVAL;
599 650
600 nsems = sma->sem_nsems; 651 nsems = sma->sem_nsems;
601 652
602 err=-EIDRM; 653 err=-EIDRM;
603 if (sem_checkid(sma,semid)) 654 if (sem_checkid(ns,sma,semid))
604 goto out_unlock; 655 goto out_unlock;
605 656
606 err = -EACCES; 657 err = -EACCES;
@@ -802,7 +853,8 @@ static inline unsigned long copy_semid_from_user(struct sem_setbuf *out, void __
802 } 853 }
803} 854}
804 855
805static int semctl_down(int semid, int semnum, int cmd, int version, union semun arg) 856static int semctl_down(struct ipc_namespace *ns, int semid, int semnum,
857 int cmd, int version, union semun arg)
806{ 858{
807 struct sem_array *sma; 859 struct sem_array *sma;
808 int err; 860 int err;
@@ -813,11 +865,11 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
813 if(copy_semid_from_user (&setbuf, arg.buf, version)) 865 if(copy_semid_from_user (&setbuf, arg.buf, version))
814 return -EFAULT; 866 return -EFAULT;
815 } 867 }
816 sma = sem_lock(semid); 868 sma = sem_lock(ns, semid);
817 if(sma==NULL) 869 if(sma==NULL)
818 return -EINVAL; 870 return -EINVAL;
819 871
820 if (sem_checkid(sma,semid)) { 872 if (sem_checkid(ns,sma,semid)) {
821 err=-EIDRM; 873 err=-EIDRM;
822 goto out_unlock; 874 goto out_unlock;
823 } 875 }
@@ -844,7 +896,7 @@ static int semctl_down(int semid, int semnum, int cmd, int version, union semun
844 896
845 switch(cmd){ 897 switch(cmd){
846 case IPC_RMID: 898 case IPC_RMID:
847 freeary(sma, semid); 899 freeary(ns, sma, semid);
848 err = 0; 900 err = 0;
849 break; 901 break;
850 case IPC_SET: 902 case IPC_SET:
@@ -872,17 +924,19 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
872{ 924{
873 int err = -EINVAL; 925 int err = -EINVAL;
874 int version; 926 int version;
927 struct ipc_namespace *ns;
875 928
876 if (semid < 0) 929 if (semid < 0)
877 return -EINVAL; 930 return -EINVAL;
878 931
879 version = ipc_parse_version(&cmd); 932 version = ipc_parse_version(&cmd);
933 ns = current->nsproxy->ipc_ns;
880 934
881 switch(cmd) { 935 switch(cmd) {
882 case IPC_INFO: 936 case IPC_INFO:
883 case SEM_INFO: 937 case SEM_INFO:
884 case SEM_STAT: 938 case SEM_STAT:
885 err = semctl_nolock(semid,semnum,cmd,version,arg); 939 err = semctl_nolock(ns,semid,semnum,cmd,version,arg);
886 return err; 940 return err;
887 case GETALL: 941 case GETALL:
888 case GETVAL: 942 case GETVAL:
@@ -892,13 +946,13 @@ asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
892 case IPC_STAT: 946 case IPC_STAT:
893 case SETVAL: 947 case SETVAL:
894 case SETALL: 948 case SETALL:
895 err = semctl_main(semid,semnum,cmd,version,arg); 949 err = semctl_main(ns,semid,semnum,cmd,version,arg);
896 return err; 950 return err;
897 case IPC_RMID: 951 case IPC_RMID:
898 case IPC_SET: 952 case IPC_SET:
899 mutex_lock(&sem_ids.mutex); 953 mutex_lock(&sem_ids(ns).mutex);
900 err = semctl_down(semid,semnum,cmd,version,arg); 954 err = semctl_down(ns,semid,semnum,cmd,version,arg);
901 mutex_unlock(&sem_ids.mutex); 955 mutex_unlock(&sem_ids(ns).mutex);
902 return err; 956 return err;
903 default: 957 default:
904 return -EINVAL; 958 return -EINVAL;
@@ -986,7 +1040,7 @@ static struct sem_undo *lookup_undo(struct sem_undo_list *ulp, int semid)
986 return un; 1040 return un;
987} 1041}
988 1042
989static struct sem_undo *find_undo(int semid) 1043static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
990{ 1044{
991 struct sem_array *sma; 1045 struct sem_array *sma;
992 struct sem_undo_list *ulp; 1046 struct sem_undo_list *ulp;
@@ -1005,12 +1059,12 @@ static struct sem_undo *find_undo(int semid)
1005 goto out; 1059 goto out;
1006 1060
1007 /* no undo structure around - allocate one. */ 1061 /* no undo structure around - allocate one. */
1008 sma = sem_lock(semid); 1062 sma = sem_lock(ns, semid);
1009 un = ERR_PTR(-EINVAL); 1063 un = ERR_PTR(-EINVAL);
1010 if(sma==NULL) 1064 if(sma==NULL)
1011 goto out; 1065 goto out;
1012 un = ERR_PTR(-EIDRM); 1066 un = ERR_PTR(-EIDRM);
1013 if (sem_checkid(sma,semid)) { 1067 if (sem_checkid(ns,sma,semid)) {
1014 sem_unlock(sma); 1068 sem_unlock(sma);
1015 goto out; 1069 goto out;
1016 } 1070 }
@@ -1070,10 +1124,13 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
1070 int undos = 0, alter = 0, max; 1124 int undos = 0, alter = 0, max;
1071 struct sem_queue queue; 1125 struct sem_queue queue;
1072 unsigned long jiffies_left = 0; 1126 unsigned long jiffies_left = 0;
1127 struct ipc_namespace *ns;
1128
1129 ns = current->nsproxy->ipc_ns;
1073 1130
1074 if (nsops < 1 || semid < 0) 1131 if (nsops < 1 || semid < 0)
1075 return -EINVAL; 1132 return -EINVAL;
1076 if (nsops > sc_semopm) 1133 if (nsops > ns->sc_semopm)
1077 return -E2BIG; 1134 return -E2BIG;
1078 if(nsops > SEMOPM_FAST) { 1135 if(nsops > SEMOPM_FAST) {
1079 sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL); 1136 sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL);
@@ -1109,7 +1166,7 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
1109 1166
1110retry_undos: 1167retry_undos:
1111 if (undos) { 1168 if (undos) {
1112 un = find_undo(semid); 1169 un = find_undo(ns, semid);
1113 if (IS_ERR(un)) { 1170 if (IS_ERR(un)) {
1114 error = PTR_ERR(un); 1171 error = PTR_ERR(un);
1115 goto out_free; 1172 goto out_free;
@@ -1117,12 +1174,12 @@ retry_undos:
1117 } else 1174 } else
1118 un = NULL; 1175 un = NULL;
1119 1176
1120 sma = sem_lock(semid); 1177 sma = sem_lock(ns, semid);
1121 error=-EINVAL; 1178 error=-EINVAL;
1122 if(sma==NULL) 1179 if(sma==NULL)
1123 goto out_free; 1180 goto out_free;
1124 error = -EIDRM; 1181 error = -EIDRM;
1125 if (sem_checkid(sma,semid)) 1182 if (sem_checkid(ns,sma,semid))
1126 goto out_unlock_free; 1183 goto out_unlock_free;
1127 /* 1184 /*
1128 * semid identifies are not unique - find_undo may have 1185 * semid identifies are not unique - find_undo may have
@@ -1190,7 +1247,7 @@ retry_undos:
1190 goto out_free; 1247 goto out_free;
1191 } 1248 }
1192 1249
1193 sma = sem_lock(semid); 1250 sma = sem_lock(ns, semid);
1194 if(sma==NULL) { 1251 if(sma==NULL) {
1195 BUG_ON(queue.prev != NULL); 1252 BUG_ON(queue.prev != NULL);
1196 error = -EIDRM; 1253 error = -EIDRM;
@@ -1267,6 +1324,7 @@ void exit_sem(struct task_struct *tsk)
1267{ 1324{
1268 struct sem_undo_list *undo_list; 1325 struct sem_undo_list *undo_list;
1269 struct sem_undo *u, **up; 1326 struct sem_undo *u, **up;
1327 struct ipc_namespace *ns;
1270 1328
1271 undo_list = tsk->sysvsem.undo_list; 1329 undo_list = tsk->sysvsem.undo_list;
1272 if (!undo_list) 1330 if (!undo_list)
@@ -1275,6 +1333,7 @@ void exit_sem(struct task_struct *tsk)
1275 if (!atomic_dec_and_test(&undo_list->refcnt)) 1333 if (!atomic_dec_and_test(&undo_list->refcnt))
1276 return; 1334 return;
1277 1335
1336 ns = tsk->nsproxy->ipc_ns;
1278 /* There's no need to hold the semundo list lock, as current 1337 /* There's no need to hold the semundo list lock, as current
1279 * is the last task exiting for this undo list. 1338 * is the last task exiting for this undo list.
1280 */ 1339 */
@@ -1288,14 +1347,14 @@ void exit_sem(struct task_struct *tsk)
1288 1347
1289 if(semid == -1) 1348 if(semid == -1)
1290 continue; 1349 continue;
1291 sma = sem_lock(semid); 1350 sma = sem_lock(ns, semid);
1292 if (sma == NULL) 1351 if (sma == NULL)
1293 continue; 1352 continue;
1294 1353
1295 if (u->semid == -1) 1354 if (u->semid == -1)
1296 goto next_entry; 1355 goto next_entry;
1297 1356
1298 BUG_ON(sem_checkid(sma,u->semid)); 1357 BUG_ON(sem_checkid(ns,sma,u->semid));
1299 1358
1300 /* remove u from the sma->undo list */ 1359 /* remove u from the sma->undo list */
1301 for (unp = &sma->undo; (un = *unp); unp = &un->id_next) { 1360 for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {