diff options
-rw-r--r-- | ipc/shm.c | 254 |
1 files changed, 168 insertions, 86 deletions
@@ -15,6 +15,10 @@ | |||
15 | * | 15 | * |
16 | * support for audit of ipc object properties and permission changes | 16 | * support for audit of ipc object properties and permission changes |
17 | * Dustin Kirkland <dustin.kirkland@us.ibm.com> | 17 | * Dustin Kirkland <dustin.kirkland@us.ibm.com> |
18 | * | ||
19 | * namespaces support | ||
20 | * OpenVZ, SWsoft Inc. | ||
21 | * Pavel Emelianov <xemul@openvz.org> | ||
18 | */ | 22 | */ |
19 | 23 | ||
20 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
@@ -32,6 +36,7 @@ | |||
32 | #include <linux/ptrace.h> | 36 | #include <linux/ptrace.h> |
33 | #include <linux/seq_file.h> | 37 | #include <linux/seq_file.h> |
34 | #include <linux/mutex.h> | 38 | #include <linux/mutex.h> |
39 | #include <linux/nsproxy.h> | ||
35 | 40 | ||
36 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
37 | 42 | ||
@@ -40,59 +45,115 @@ | |||
40 | static struct file_operations shm_file_operations; | 45 | static struct file_operations shm_file_operations; |
41 | static struct vm_operations_struct shm_vm_ops; | 46 | static struct vm_operations_struct shm_vm_ops; |
42 | 47 | ||
43 | static struct ipc_ids shm_ids; | 48 | static struct ipc_ids init_shm_ids; |
49 | |||
50 | #define shm_ids(ns) (*((ns)->ids[IPC_SHM_IDS])) | ||
44 | 51 | ||
45 | #define shm_lock(id) ((struct shmid_kernel*)ipc_lock(&shm_ids,id)) | 52 | #define shm_lock(ns, id) \ |
46 | #define shm_unlock(shp) ipc_unlock(&(shp)->shm_perm) | 53 | ((struct shmid_kernel*)ipc_lock(&shm_ids(ns),id)) |
47 | #define shm_get(id) ((struct shmid_kernel*)ipc_get(&shm_ids,id)) | 54 | #define shm_unlock(shp) \ |
48 | #define shm_buildid(id, seq) \ | 55 | ipc_unlock(&(shp)->shm_perm) |
49 | ipc_buildid(&shm_ids, id, seq) | 56 | #define shm_get(ns, id) \ |
57 | ((struct shmid_kernel*)ipc_get(&shm_ids(ns),id)) | ||
58 | #define shm_buildid(ns, id, seq) \ | ||
59 | ipc_buildid(&shm_ids(ns), id, seq) | ||
50 | 60 | ||
51 | static int newseg (key_t key, int shmflg, size_t size); | 61 | static int newseg (struct ipc_namespace *ns, key_t key, |
62 | int shmflg, size_t size); | ||
52 | static void shm_open (struct vm_area_struct *shmd); | 63 | static void shm_open (struct vm_area_struct *shmd); |
53 | static void shm_close (struct vm_area_struct *shmd); | 64 | static void shm_close (struct vm_area_struct *shmd); |
65 | static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp); | ||
54 | #ifdef CONFIG_PROC_FS | 66 | #ifdef CONFIG_PROC_FS |
55 | static int sysvipc_shm_proc_show(struct seq_file *s, void *it); | 67 | static int sysvipc_shm_proc_show(struct seq_file *s, void *it); |
56 | #endif | 68 | #endif |
57 | 69 | ||
58 | size_t shm_ctlmax = SHMMAX; | 70 | static void __ipc_init __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) |
59 | size_t shm_ctlall = SHMALL; | 71 | { |
60 | int shm_ctlmni = SHMMNI; | 72 | ns->ids[IPC_SHM_IDS] = ids; |
73 | ns->shm_ctlmax = SHMMAX; | ||
74 | ns->shm_ctlall = SHMALL; | ||
75 | ns->shm_ctlmni = SHMMNI; | ||
76 | ns->shm_tot = 0; | ||
77 | ipc_init_ids(ids, 1); | ||
78 | } | ||
79 | |||
80 | static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp) | ||
81 | { | ||
82 | if (shp->shm_nattch){ | ||
83 | shp->shm_perm.mode |= SHM_DEST; | ||
84 | /* Do not find it any more */ | ||
85 | shp->shm_perm.key = IPC_PRIVATE; | ||
86 | shm_unlock(shp); | ||
87 | } else | ||
88 | shm_destroy(ns, shp); | ||
89 | } | ||
90 | |||
91 | #ifdef CONFIG_IPC_NS | ||
92 | int shm_init_ns(struct ipc_namespace *ns) | ||
93 | { | ||
94 | struct ipc_ids *ids; | ||
95 | |||
96 | ids = kmalloc(sizeof(struct ipc_ids), GFP_KERNEL); | ||
97 | if (ids == NULL) | ||
98 | return -ENOMEM; | ||
61 | 99 | ||
62 | static int shm_tot; /* total number of shared memory pages */ | 100 | __shm_init_ns(ns, ids); |
101 | return 0; | ||
102 | } | ||
103 | |||
104 | void shm_exit_ns(struct ipc_namespace *ns) | ||
105 | { | ||
106 | int i; | ||
107 | struct shmid_kernel *shp; | ||
108 | |||
109 | mutex_lock(&shm_ids(ns).mutex); | ||
110 | for (i = 0; i <= shm_ids(ns).max_id; i++) { | ||
111 | shp = shm_lock(ns, i); | ||
112 | if (shp == NULL) | ||
113 | continue; | ||
114 | |||
115 | do_shm_rmid(ns, shp); | ||
116 | } | ||
117 | mutex_unlock(&shm_ids(ns).mutex); | ||
118 | |||
119 | kfree(ns->ids[IPC_SHM_IDS]); | ||
120 | ns->ids[IPC_SHM_IDS] = NULL; | ||
121 | } | ||
122 | #endif | ||
63 | 123 | ||
64 | void __init shm_init (void) | 124 | void __init shm_init (void) |
65 | { | 125 | { |
66 | ipc_init_ids(&shm_ids, 1); | 126 | __shm_init_ns(&init_ipc_ns, &init_shm_ids); |
67 | ipc_init_proc_interface("sysvipc/shm", | 127 | ipc_init_proc_interface("sysvipc/shm", |
68 | " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n", | 128 | " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n", |
69 | &shm_ids, | 129 | IPC_SHM_IDS, sysvipc_shm_proc_show); |
70 | sysvipc_shm_proc_show); | ||
71 | } | 130 | } |
72 | 131 | ||
73 | static inline int shm_checkid(struct shmid_kernel *s, int id) | 132 | static inline int shm_checkid(struct ipc_namespace *ns, |
133 | struct shmid_kernel *s, int id) | ||
74 | { | 134 | { |
75 | if (ipc_checkid(&shm_ids,&s->shm_perm,id)) | 135 | if (ipc_checkid(&shm_ids(ns), &s->shm_perm, id)) |
76 | return -EIDRM; | 136 | return -EIDRM; |
77 | return 0; | 137 | return 0; |
78 | } | 138 | } |
79 | 139 | ||
80 | static inline struct shmid_kernel *shm_rmid(int id) | 140 | static inline struct shmid_kernel *shm_rmid(struct ipc_namespace *ns, int id) |
81 | { | 141 | { |
82 | return (struct shmid_kernel *)ipc_rmid(&shm_ids,id); | 142 | return (struct shmid_kernel *)ipc_rmid(&shm_ids(ns), id); |
83 | } | 143 | } |
84 | 144 | ||
85 | static inline int shm_addid(struct shmid_kernel *shp) | 145 | static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp) |
86 | { | 146 | { |
87 | return ipc_addid(&shm_ids, &shp->shm_perm, shm_ctlmni); | 147 | return ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); |
88 | } | 148 | } |
89 | 149 | ||
90 | 150 | ||
91 | 151 | ||
92 | static inline void shm_inc (int id) { | 152 | static inline void shm_inc(struct ipc_namespace *ns, int id) |
153 | { | ||
93 | struct shmid_kernel *shp; | 154 | struct shmid_kernel *shp; |
94 | 155 | ||
95 | shp = shm_lock(id); | 156 | shp = shm_lock(ns, id); |
96 | BUG_ON(!shp); | 157 | BUG_ON(!shp); |
97 | shp->shm_atim = get_seconds(); | 158 | shp->shm_atim = get_seconds(); |
98 | shp->shm_lprid = current->tgid; | 159 | shp->shm_lprid = current->tgid; |
@@ -100,10 +161,13 @@ static inline void shm_inc (int id) { | |||
100 | shm_unlock(shp); | 161 | shm_unlock(shp); |
101 | } | 162 | } |
102 | 163 | ||
164 | #define shm_file_ns(file) (*((struct ipc_namespace **)&(file)->private_data)) | ||
165 | |||
103 | /* This is called by fork, once for every shm attach. */ | 166 | /* This is called by fork, once for every shm attach. */ |
104 | static void shm_open (struct vm_area_struct *shmd) | 167 | static void shm_open(struct vm_area_struct *shmd) |
105 | { | 168 | { |
106 | shm_inc (shmd->vm_file->f_dentry->d_inode->i_ino); | 169 | shm_inc(shm_file_ns(shmd->vm_file), |
170 | shmd->vm_file->f_dentry->d_inode->i_ino); | ||
107 | } | 171 | } |
108 | 172 | ||
109 | /* | 173 | /* |
@@ -114,10 +178,10 @@ static void shm_open (struct vm_area_struct *shmd) | |||
114 | * It has to be called with shp and shm_ids.mutex locked, | 178 | * It has to be called with shp and shm_ids.mutex locked, |
115 | * but returns with shp unlocked and freed. | 179 | * but returns with shp unlocked and freed. |
116 | */ | 180 | */ |
117 | static void shm_destroy (struct shmid_kernel *shp) | 181 | static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) |
118 | { | 182 | { |
119 | shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; | 183 | ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; |
120 | shm_rmid (shp->id); | 184 | shm_rmid(ns, shp->id); |
121 | shm_unlock(shp); | 185 | shm_unlock(shp); |
122 | if (!is_file_hugepages(shp->shm_file)) | 186 | if (!is_file_hugepages(shp->shm_file)) |
123 | shmem_lock(shp->shm_file, 0, shp->mlock_user); | 187 | shmem_lock(shp->shm_file, 0, shp->mlock_user); |
@@ -140,20 +204,23 @@ static void shm_close (struct vm_area_struct *shmd) | |||
140 | struct file * file = shmd->vm_file; | 204 | struct file * file = shmd->vm_file; |
141 | int id = file->f_dentry->d_inode->i_ino; | 205 | int id = file->f_dentry->d_inode->i_ino; |
142 | struct shmid_kernel *shp; | 206 | struct shmid_kernel *shp; |
207 | struct ipc_namespace *ns; | ||
143 | 208 | ||
144 | mutex_lock(&shm_ids.mutex); | 209 | ns = shm_file_ns(file); |
210 | |||
211 | mutex_lock(&shm_ids(ns).mutex); | ||
145 | /* remove from the list of attaches of the shm segment */ | 212 | /* remove from the list of attaches of the shm segment */ |
146 | shp = shm_lock(id); | 213 | shp = shm_lock(ns, id); |
147 | BUG_ON(!shp); | 214 | BUG_ON(!shp); |
148 | shp->shm_lprid = current->tgid; | 215 | shp->shm_lprid = current->tgid; |
149 | shp->shm_dtim = get_seconds(); | 216 | shp->shm_dtim = get_seconds(); |
150 | shp->shm_nattch--; | 217 | shp->shm_nattch--; |
151 | if(shp->shm_nattch == 0 && | 218 | if(shp->shm_nattch == 0 && |
152 | shp->shm_perm.mode & SHM_DEST) | 219 | shp->shm_perm.mode & SHM_DEST) |
153 | shm_destroy (shp); | 220 | shm_destroy(ns, shp); |
154 | else | 221 | else |
155 | shm_unlock(shp); | 222 | shm_unlock(shp); |
156 | mutex_unlock(&shm_ids.mutex); | 223 | mutex_unlock(&shm_ids(ns).mutex); |
157 | } | 224 | } |
158 | 225 | ||
159 | static int shm_mmap(struct file * file, struct vm_area_struct * vma) | 226 | static int shm_mmap(struct file * file, struct vm_area_struct * vma) |
@@ -165,14 +232,25 @@ static int shm_mmap(struct file * file, struct vm_area_struct * vma) | |||
165 | vma->vm_ops = &shm_vm_ops; | 232 | vma->vm_ops = &shm_vm_ops; |
166 | if (!(vma->vm_flags & VM_WRITE)) | 233 | if (!(vma->vm_flags & VM_WRITE)) |
167 | vma->vm_flags &= ~VM_MAYWRITE; | 234 | vma->vm_flags &= ~VM_MAYWRITE; |
168 | shm_inc(file->f_dentry->d_inode->i_ino); | 235 | shm_inc(shm_file_ns(file), file->f_dentry->d_inode->i_ino); |
169 | } | 236 | } |
170 | 237 | ||
171 | return ret; | 238 | return ret; |
172 | } | 239 | } |
173 | 240 | ||
241 | static int shm_release(struct inode *ino, struct file *file) | ||
242 | { | ||
243 | struct ipc_namespace *ns; | ||
244 | |||
245 | ns = shm_file_ns(file); | ||
246 | put_ipc_ns(ns); | ||
247 | shm_file_ns(file) = NULL; | ||
248 | return 0; | ||
249 | } | ||
250 | |||
174 | static struct file_operations shm_file_operations = { | 251 | static struct file_operations shm_file_operations = { |
175 | .mmap = shm_mmap, | 252 | .mmap = shm_mmap, |
253 | .release = shm_release, | ||
176 | #ifndef CONFIG_MMU | 254 | #ifndef CONFIG_MMU |
177 | .get_unmapped_area = shmem_get_unmapped_area, | 255 | .get_unmapped_area = shmem_get_unmapped_area, |
178 | #endif | 256 | #endif |
@@ -188,7 +266,7 @@ static struct vm_operations_struct shm_vm_ops = { | |||
188 | #endif | 266 | #endif |
189 | }; | 267 | }; |
190 | 268 | ||
191 | static int newseg (key_t key, int shmflg, size_t size) | 269 | static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size) |
192 | { | 270 | { |
193 | int error; | 271 | int error; |
194 | struct shmid_kernel *shp; | 272 | struct shmid_kernel *shp; |
@@ -197,10 +275,10 @@ static int newseg (key_t key, int shmflg, size_t size) | |||
197 | char name[13]; | 275 | char name[13]; |
198 | int id; | 276 | int id; |
199 | 277 | ||
200 | if (size < SHMMIN || size > shm_ctlmax) | 278 | if (size < SHMMIN || size > ns->shm_ctlmax) |
201 | return -EINVAL; | 279 | return -EINVAL; |
202 | 280 | ||
203 | if (shm_tot + numpages >= shm_ctlall) | 281 | if (ns->shm_tot + numpages >= ns->shm_ctlall) |
204 | return -ENOSPC; | 282 | return -ENOSPC; |
205 | 283 | ||
206 | shp = ipc_rcu_alloc(sizeof(*shp)); | 284 | shp = ipc_rcu_alloc(sizeof(*shp)); |
@@ -239,7 +317,7 @@ static int newseg (key_t key, int shmflg, size_t size) | |||
239 | goto no_file; | 317 | goto no_file; |
240 | 318 | ||
241 | error = -ENOSPC; | 319 | error = -ENOSPC; |
242 | id = shm_addid(shp); | 320 | id = shm_addid(ns, shp); |
243 | if(id == -1) | 321 | if(id == -1) |
244 | goto no_id; | 322 | goto no_id; |
245 | 323 | ||
@@ -249,15 +327,17 @@ static int newseg (key_t key, int shmflg, size_t size) | |||
249 | shp->shm_ctim = get_seconds(); | 327 | shp->shm_ctim = get_seconds(); |
250 | shp->shm_segsz = size; | 328 | shp->shm_segsz = size; |
251 | shp->shm_nattch = 0; | 329 | shp->shm_nattch = 0; |
252 | shp->id = shm_buildid(id,shp->shm_perm.seq); | 330 | shp->id = shm_buildid(ns, id, shp->shm_perm.seq); |
253 | shp->shm_file = file; | 331 | shp->shm_file = file; |
254 | file->f_dentry->d_inode->i_ino = shp->id; | 332 | file->f_dentry->d_inode->i_ino = shp->id; |
255 | 333 | ||
334 | shm_file_ns(file) = get_ipc_ns(ns); | ||
335 | |||
256 | /* Hugetlb ops would have already been assigned. */ | 336 | /* Hugetlb ops would have already been assigned. */ |
257 | if (!(shmflg & SHM_HUGETLB)) | 337 | if (!(shmflg & SHM_HUGETLB)) |
258 | file->f_op = &shm_file_operations; | 338 | file->f_op = &shm_file_operations; |
259 | 339 | ||
260 | shm_tot += numpages; | 340 | ns->shm_tot += numpages; |
261 | shm_unlock(shp); | 341 | shm_unlock(shp); |
262 | return shp->id; | 342 | return shp->id; |
263 | 343 | ||
@@ -273,33 +353,36 @@ asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) | |||
273 | { | 353 | { |
274 | struct shmid_kernel *shp; | 354 | struct shmid_kernel *shp; |
275 | int err, id = 0; | 355 | int err, id = 0; |
356 | struct ipc_namespace *ns; | ||
357 | |||
358 | ns = current->nsproxy->ipc_ns; | ||
276 | 359 | ||
277 | mutex_lock(&shm_ids.mutex); | 360 | mutex_lock(&shm_ids(ns).mutex); |
278 | if (key == IPC_PRIVATE) { | 361 | if (key == IPC_PRIVATE) { |
279 | err = newseg(key, shmflg, size); | 362 | err = newseg(ns, key, shmflg, size); |
280 | } else if ((id = ipc_findkey(&shm_ids, key)) == -1) { | 363 | } else if ((id = ipc_findkey(&shm_ids(ns), key)) == -1) { |
281 | if (!(shmflg & IPC_CREAT)) | 364 | if (!(shmflg & IPC_CREAT)) |
282 | err = -ENOENT; | 365 | err = -ENOENT; |
283 | else | 366 | else |
284 | err = newseg(key, shmflg, size); | 367 | err = newseg(ns, key, shmflg, size); |
285 | } else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) { | 368 | } else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) { |
286 | err = -EEXIST; | 369 | err = -EEXIST; |
287 | } else { | 370 | } else { |
288 | shp = shm_lock(id); | 371 | shp = shm_lock(ns, id); |
289 | BUG_ON(shp==NULL); | 372 | BUG_ON(shp==NULL); |
290 | if (shp->shm_segsz < size) | 373 | if (shp->shm_segsz < size) |
291 | err = -EINVAL; | 374 | err = -EINVAL; |
292 | else if (ipcperms(&shp->shm_perm, shmflg)) | 375 | else if (ipcperms(&shp->shm_perm, shmflg)) |
293 | err = -EACCES; | 376 | err = -EACCES; |
294 | else { | 377 | else { |
295 | int shmid = shm_buildid(id, shp->shm_perm.seq); | 378 | int shmid = shm_buildid(ns, id, shp->shm_perm.seq); |
296 | err = security_shm_associate(shp, shmflg); | 379 | err = security_shm_associate(shp, shmflg); |
297 | if (!err) | 380 | if (!err) |
298 | err = shmid; | 381 | err = shmid; |
299 | } | 382 | } |
300 | shm_unlock(shp); | 383 | shm_unlock(shp); |
301 | } | 384 | } |
302 | mutex_unlock(&shm_ids.mutex); | 385 | mutex_unlock(&shm_ids(ns).mutex); |
303 | 386 | ||
304 | return err; | 387 | return err; |
305 | } | 388 | } |
@@ -395,18 +478,19 @@ static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminf | |||
395 | } | 478 | } |
396 | } | 479 | } |
397 | 480 | ||
398 | static void shm_get_stat(unsigned long *rss, unsigned long *swp) | 481 | static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, |
482 | unsigned long *swp) | ||
399 | { | 483 | { |
400 | int i; | 484 | int i; |
401 | 485 | ||
402 | *rss = 0; | 486 | *rss = 0; |
403 | *swp = 0; | 487 | *swp = 0; |
404 | 488 | ||
405 | for (i = 0; i <= shm_ids.max_id; i++) { | 489 | for (i = 0; i <= shm_ids(ns).max_id; i++) { |
406 | struct shmid_kernel *shp; | 490 | struct shmid_kernel *shp; |
407 | struct inode *inode; | 491 | struct inode *inode; |
408 | 492 | ||
409 | shp = shm_get(i); | 493 | shp = shm_get(ns, i); |
410 | if(!shp) | 494 | if(!shp) |
411 | continue; | 495 | continue; |
412 | 496 | ||
@@ -430,6 +514,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
430 | struct shm_setbuf setbuf; | 514 | struct shm_setbuf setbuf; |
431 | struct shmid_kernel *shp; | 515 | struct shmid_kernel *shp; |
432 | int err, version; | 516 | int err, version; |
517 | struct ipc_namespace *ns; | ||
433 | 518 | ||
434 | if (cmd < 0 || shmid < 0) { | 519 | if (cmd < 0 || shmid < 0) { |
435 | err = -EINVAL; | 520 | err = -EINVAL; |
@@ -437,6 +522,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
437 | } | 522 | } |
438 | 523 | ||
439 | version = ipc_parse_version(&cmd); | 524 | version = ipc_parse_version(&cmd); |
525 | ns = current->nsproxy->ipc_ns; | ||
440 | 526 | ||
441 | switch (cmd) { /* replace with proc interface ? */ | 527 | switch (cmd) { /* replace with proc interface ? */ |
442 | case IPC_INFO: | 528 | case IPC_INFO: |
@@ -448,15 +534,15 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
448 | return err; | 534 | return err; |
449 | 535 | ||
450 | memset(&shminfo,0,sizeof(shminfo)); | 536 | memset(&shminfo,0,sizeof(shminfo)); |
451 | shminfo.shmmni = shminfo.shmseg = shm_ctlmni; | 537 | shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; |
452 | shminfo.shmmax = shm_ctlmax; | 538 | shminfo.shmmax = ns->shm_ctlmax; |
453 | shminfo.shmall = shm_ctlall; | 539 | shminfo.shmall = ns->shm_ctlall; |
454 | 540 | ||
455 | shminfo.shmmin = SHMMIN; | 541 | shminfo.shmmin = SHMMIN; |
456 | if(copy_shminfo_to_user (buf, &shminfo, version)) | 542 | if(copy_shminfo_to_user (buf, &shminfo, version)) |
457 | return -EFAULT; | 543 | return -EFAULT; |
458 | /* reading a integer is always atomic */ | 544 | /* reading a integer is always atomic */ |
459 | err= shm_ids.max_id; | 545 | err= shm_ids(ns).max_id; |
460 | if(err<0) | 546 | if(err<0) |
461 | err = 0; | 547 | err = 0; |
462 | goto out; | 548 | goto out; |
@@ -470,14 +556,14 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
470 | return err; | 556 | return err; |
471 | 557 | ||
472 | memset(&shm_info,0,sizeof(shm_info)); | 558 | memset(&shm_info,0,sizeof(shm_info)); |
473 | mutex_lock(&shm_ids.mutex); | 559 | mutex_lock(&shm_ids(ns).mutex); |
474 | shm_info.used_ids = shm_ids.in_use; | 560 | shm_info.used_ids = shm_ids(ns).in_use; |
475 | shm_get_stat (&shm_info.shm_rss, &shm_info.shm_swp); | 561 | shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp); |
476 | shm_info.shm_tot = shm_tot; | 562 | shm_info.shm_tot = ns->shm_tot; |
477 | shm_info.swap_attempts = 0; | 563 | shm_info.swap_attempts = 0; |
478 | shm_info.swap_successes = 0; | 564 | shm_info.swap_successes = 0; |
479 | err = shm_ids.max_id; | 565 | err = shm_ids(ns).max_id; |
480 | mutex_unlock(&shm_ids.mutex); | 566 | mutex_unlock(&shm_ids(ns).mutex); |
481 | if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { | 567 | if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { |
482 | err = -EFAULT; | 568 | err = -EFAULT; |
483 | goto out; | 569 | goto out; |
@@ -492,17 +578,17 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
492 | struct shmid64_ds tbuf; | 578 | struct shmid64_ds tbuf; |
493 | int result; | 579 | int result; |
494 | memset(&tbuf, 0, sizeof(tbuf)); | 580 | memset(&tbuf, 0, sizeof(tbuf)); |
495 | shp = shm_lock(shmid); | 581 | shp = shm_lock(ns, shmid); |
496 | if(shp==NULL) { | 582 | if(shp==NULL) { |
497 | err = -EINVAL; | 583 | err = -EINVAL; |
498 | goto out; | 584 | goto out; |
499 | } else if(cmd==SHM_STAT) { | 585 | } else if(cmd==SHM_STAT) { |
500 | err = -EINVAL; | 586 | err = -EINVAL; |
501 | if (shmid > shm_ids.max_id) | 587 | if (shmid > shm_ids(ns).max_id) |
502 | goto out_unlock; | 588 | goto out_unlock; |
503 | result = shm_buildid(shmid, shp->shm_perm.seq); | 589 | result = shm_buildid(ns, shmid, shp->shm_perm.seq); |
504 | } else { | 590 | } else { |
505 | err = shm_checkid(shp,shmid); | 591 | err = shm_checkid(ns, shp,shmid); |
506 | if(err) | 592 | if(err) |
507 | goto out_unlock; | 593 | goto out_unlock; |
508 | result = 0; | 594 | result = 0; |
@@ -534,12 +620,12 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
534 | case SHM_LOCK: | 620 | case SHM_LOCK: |
535 | case SHM_UNLOCK: | 621 | case SHM_UNLOCK: |
536 | { | 622 | { |
537 | shp = shm_lock(shmid); | 623 | shp = shm_lock(ns, shmid); |
538 | if(shp==NULL) { | 624 | if(shp==NULL) { |
539 | err = -EINVAL; | 625 | err = -EINVAL; |
540 | goto out; | 626 | goto out; |
541 | } | 627 | } |
542 | err = shm_checkid(shp,shmid); | 628 | err = shm_checkid(ns, shp,shmid); |
543 | if(err) | 629 | if(err) |
544 | goto out_unlock; | 630 | goto out_unlock; |
545 | 631 | ||
@@ -590,12 +676,12 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
590 | * Instead we set a destroyed flag, and then blow | 676 | * Instead we set a destroyed flag, and then blow |
591 | * the name away when the usage hits zero. | 677 | * the name away when the usage hits zero. |
592 | */ | 678 | */ |
593 | mutex_lock(&shm_ids.mutex); | 679 | mutex_lock(&shm_ids(ns).mutex); |
594 | shp = shm_lock(shmid); | 680 | shp = shm_lock(ns, shmid); |
595 | err = -EINVAL; | 681 | err = -EINVAL; |
596 | if (shp == NULL) | 682 | if (shp == NULL) |
597 | goto out_up; | 683 | goto out_up; |
598 | err = shm_checkid(shp, shmid); | 684 | err = shm_checkid(ns, shp, shmid); |
599 | if(err) | 685 | if(err) |
600 | goto out_unlock_up; | 686 | goto out_unlock_up; |
601 | 687 | ||
@@ -614,14 +700,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
614 | if (err) | 700 | if (err) |
615 | goto out_unlock_up; | 701 | goto out_unlock_up; |
616 | 702 | ||
617 | if (shp->shm_nattch){ | 703 | do_shm_rmid(ns, shp); |
618 | shp->shm_perm.mode |= SHM_DEST; | 704 | mutex_unlock(&shm_ids(ns).mutex); |
619 | /* Do not find it any more */ | ||
620 | shp->shm_perm.key = IPC_PRIVATE; | ||
621 | shm_unlock(shp); | ||
622 | } else | ||
623 | shm_destroy (shp); | ||
624 | mutex_unlock(&shm_ids.mutex); | ||
625 | goto out; | 705 | goto out; |
626 | } | 706 | } |
627 | 707 | ||
@@ -631,12 +711,12 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
631 | err = -EFAULT; | 711 | err = -EFAULT; |
632 | goto out; | 712 | goto out; |
633 | } | 713 | } |
634 | mutex_lock(&shm_ids.mutex); | 714 | mutex_lock(&shm_ids(ns).mutex); |
635 | shp = shm_lock(shmid); | 715 | shp = shm_lock(ns, shmid); |
636 | err=-EINVAL; | 716 | err=-EINVAL; |
637 | if(shp==NULL) | 717 | if(shp==NULL) |
638 | goto out_up; | 718 | goto out_up; |
639 | err = shm_checkid(shp,shmid); | 719 | err = shm_checkid(ns, shp,shmid); |
640 | if(err) | 720 | if(err) |
641 | goto out_unlock_up; | 721 | goto out_unlock_up; |
642 | err = audit_ipc_obj(&(shp->shm_perm)); | 722 | err = audit_ipc_obj(&(shp->shm_perm)); |
@@ -673,7 +753,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
673 | out_unlock_up: | 753 | out_unlock_up: |
674 | shm_unlock(shp); | 754 | shm_unlock(shp); |
675 | out_up: | 755 | out_up: |
676 | mutex_unlock(&shm_ids.mutex); | 756 | mutex_unlock(&shm_ids(ns).mutex); |
677 | goto out; | 757 | goto out; |
678 | out_unlock: | 758 | out_unlock: |
679 | shm_unlock(shp); | 759 | shm_unlock(shp); |
@@ -699,6 +779,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
699 | unsigned long prot; | 779 | unsigned long prot; |
700 | int acc_mode; | 780 | int acc_mode; |
701 | void *user_addr; | 781 | void *user_addr; |
782 | struct ipc_namespace *ns; | ||
702 | 783 | ||
703 | if (shmid < 0) { | 784 | if (shmid < 0) { |
704 | err = -EINVAL; | 785 | err = -EINVAL; |
@@ -737,12 +818,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
737 | * We cannot rely on the fs check since SYSV IPC does have an | 818 | * We cannot rely on the fs check since SYSV IPC does have an |
738 | * additional creator id... | 819 | * additional creator id... |
739 | */ | 820 | */ |
740 | shp = shm_lock(shmid); | 821 | ns = current->nsproxy->ipc_ns; |
822 | shp = shm_lock(ns, shmid); | ||
741 | if(shp == NULL) { | 823 | if(shp == NULL) { |
742 | err = -EINVAL; | 824 | err = -EINVAL; |
743 | goto out; | 825 | goto out; |
744 | } | 826 | } |
745 | err = shm_checkid(shp,shmid); | 827 | err = shm_checkid(ns, shp,shmid); |
746 | if (err) { | 828 | if (err) { |
747 | shm_unlock(shp); | 829 | shm_unlock(shp); |
748 | goto out; | 830 | goto out; |
@@ -783,16 +865,16 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
783 | invalid: | 865 | invalid: |
784 | up_write(¤t->mm->mmap_sem); | 866 | up_write(¤t->mm->mmap_sem); |
785 | 867 | ||
786 | mutex_lock(&shm_ids.mutex); | 868 | mutex_lock(&shm_ids(ns).mutex); |
787 | shp = shm_lock(shmid); | 869 | shp = shm_lock(ns, shmid); |
788 | BUG_ON(!shp); | 870 | BUG_ON(!shp); |
789 | shp->shm_nattch--; | 871 | shp->shm_nattch--; |
790 | if(shp->shm_nattch == 0 && | 872 | if(shp->shm_nattch == 0 && |
791 | shp->shm_perm.mode & SHM_DEST) | 873 | shp->shm_perm.mode & SHM_DEST) |
792 | shm_destroy (shp); | 874 | shm_destroy(ns, shp); |
793 | else | 875 | else |
794 | shm_unlock(shp); | 876 | shm_unlock(shp); |
795 | mutex_unlock(&shm_ids.mutex); | 877 | mutex_unlock(&shm_ids(ns).mutex); |
796 | 878 | ||
797 | *raddr = (unsigned long) user_addr; | 879 | *raddr = (unsigned long) user_addr; |
798 | err = 0; | 880 | err = 0; |