1
2
3
4
5
6#include <linux/ipc.h>
7#include <linux/msg.h>
8#include <linux/ipc_namespace.h>
9#include <linux/rcupdate.h>
10#include <linux/nsproxy.h>
11#include <linux/slab.h>
12
13#include "util.h"
14
15static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
16{
17 struct ipc_namespace *ns;
18
19 ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
20 if (ns == NULL)
21 return ERR_PTR(-ENOMEM);
22
23 atomic_inc(&nr_ipc_ns);
24
25 sem_init_ns(ns);
26 msg_init_ns(ns);
27 shm_init_ns(ns);
28
29
30
31
32
33
34 ipcns_notify(IPCNS_CREATED);
35 register_ipcns_notifier(ns);
36
37 kref_init(&ns->kref);
38 return ns;
39}
40
41struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
42{
43 struct ipc_namespace *new_ns;
44
45 BUG_ON(!ns);
46 get_ipc_ns(ns);
47
48 if (!(flags & CLONE_NEWIPC))
49 return ns;
50
51 new_ns = clone_ipc_ns(ns);
52
53 put_ipc_ns(ns);
54 return new_ns;
55}
56
57
58
59
60
61
62
63
64
65void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
66 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *))
67{
68 struct kern_ipc_perm *perm;
69 int next_id;
70 int total, in_use;
71
72 down_write(&ids->rw_mutex);
73
74 in_use = ids->in_use;
75
76 for (total = 0, next_id = 0; total < in_use; next_id++) {
77 perm = idr_find(&ids->ipcs_idr, next_id);
78 if (perm == NULL)
79 continue;
80 ipc_lock_by_ptr(perm);
81 free(ns, perm);
82 total++;
83 }
84 up_write(&ids->rw_mutex);
85}
86
87void free_ipc_ns(struct kref *kref)
88{
89 struct ipc_namespace *ns;
90
91 ns = container_of(kref, struct ipc_namespace, kref);
92
93
94
95
96
97
98
99
100 unregister_ipcns_notifier(ns);
101 sem_exit_ns(ns);
102 msg_exit_ns(ns);
103 shm_exit_ns(ns);
104 kfree(ns);
105 atomic_dec(&nr_ipc_ns);
106
107
108
109
110
111 ipcns_notify(IPCNS_REMOVED);
112}
113