diff options
Diffstat (limited to 'ipc/shm.c')
-rw-r--r-- | ipc/shm.c | 22 |
1 files changed, 11 insertions, 11 deletions
@@ -178,6 +178,7 @@ static void shm_rcu_free(struct rcu_head *head) | |||
178 | 178 | ||
179 | static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) | 179 | static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) |
180 | { | 180 | { |
181 | list_del(&s->shm_clist); | ||
181 | ipc_rmid(&shm_ids(ns), &s->shm_perm); | 182 | ipc_rmid(&shm_ids(ns), &s->shm_perm); |
182 | } | 183 | } |
183 | 184 | ||
@@ -268,14 +269,10 @@ static void shm_close(struct vm_area_struct *vma) | |||
268 | } | 269 | } |
269 | 270 | ||
270 | /* Called with ns->shm_ids(ns).rwsem locked */ | 271 | /* Called with ns->shm_ids(ns).rwsem locked */ |
271 | static int shm_try_destroy_current(int id, void *p, void *data) | 272 | static void shm_mark_orphan(struct shmid_kernel *shp, struct ipc_namespace *ns) |
272 | { | 273 | { |
273 | struct ipc_namespace *ns = data; | 274 | if (WARN_ON(shp->shm_creator != current)) /* Remove me when it works */ |
274 | struct kern_ipc_perm *ipcp = p; | 275 | return; |
275 | struct shmid_kernel *shp = container_of(ipcp, struct shmid_kernel, shm_perm); | ||
276 | |||
277 | if (shp->shm_creator != current) | ||
278 | return 0; | ||
279 | 276 | ||
280 | /* | 277 | /* |
281 | * Mark it as orphaned to destroy the segment when | 278 | * Mark it as orphaned to destroy the segment when |
@@ -289,13 +286,12 @@ static int shm_try_destroy_current(int id, void *p, void *data) | |||
289 | * is not set, it shouldn't be deleted here. | 286 | * is not set, it shouldn't be deleted here. |
290 | */ | 287 | */ |
291 | if (!ns->shm_rmid_forced) | 288 | if (!ns->shm_rmid_forced) |
292 | return 0; | 289 | return; |
293 | 290 | ||
294 | if (shm_may_destroy(ns, shp)) { | 291 | if (shm_may_destroy(ns, shp)) { |
295 | shm_lock_by_ptr(shp); | 292 | shm_lock_by_ptr(shp); |
296 | shm_destroy(ns, shp); | 293 | shm_destroy(ns, shp); |
297 | } | 294 | } |
298 | return 0; | ||
299 | } | 295 | } |
300 | 296 | ||
301 | /* Called with ns->shm_ids(ns).rwsem locked */ | 297 | /* Called with ns->shm_ids(ns).rwsem locked */ |
@@ -333,14 +329,17 @@ void shm_destroy_orphaned(struct ipc_namespace *ns) | |||
333 | void exit_shm(struct task_struct *task) | 329 | void exit_shm(struct task_struct *task) |
334 | { | 330 | { |
335 | struct ipc_namespace *ns = task->nsproxy->ipc_ns; | 331 | struct ipc_namespace *ns = task->nsproxy->ipc_ns; |
332 | struct shmid_kernel *shp, *n; | ||
336 | 333 | ||
337 | if (shm_ids(ns).in_use == 0) | 334 | if (shm_ids(ns).in_use == 0) |
338 | return; | 335 | return; |
339 | 336 | ||
340 | /* Destroy all already created segments, but not mapped yet */ | 337 | /* Destroy all already created segments, but not mapped yet */ |
341 | down_write(&shm_ids(ns).rwsem); | 338 | down_write(&shm_ids(ns).rwsem); |
342 | if (shm_ids(ns).in_use) | 339 | list_for_each_entry_safe(shp, n, &task->sysvshm.shm_clist, shm_clist) |
343 | idr_for_each(&shm_ids(ns).ipcs_idr, &shm_try_destroy_current, ns); | 340 | shm_mark_orphan(shp, ns); |
341 | /* remove the list head from any segments still attached */ | ||
342 | list_del(&task->sysvshm.shm_clist); | ||
344 | up_write(&shm_ids(ns).rwsem); | 343 | up_write(&shm_ids(ns).rwsem); |
345 | } | 344 | } |
346 | 345 | ||
@@ -561,6 +560,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
561 | shp->shm_nattch = 0; | 560 | shp->shm_nattch = 0; |
562 | shp->shm_file = file; | 561 | shp->shm_file = file; |
563 | shp->shm_creator = current; | 562 | shp->shm_creator = current; |
563 | list_add(&shp->shm_clist, ¤t->sysvshm.shm_clist); | ||
564 | 564 | ||
565 | /* | 565 | /* |
566 | * shmid gets reported as "inode#" in /proc/pid/maps. | 566 | * shmid gets reported as "inode#" in /proc/pid/maps. |