diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/namespace.c | 63 | ||||
-rw-r--r-- | ipc/shm.c | 3 | ||||
-rw-r--r-- | ipc/util.h | 5 |
3 files changed, 31 insertions, 40 deletions
diff --git a/ipc/namespace.c b/ipc/namespace.c index 4a5e752a9276..a1094ff0befa 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include "util.h" | 15 | #include "util.h" |
16 | 16 | ||
17 | static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) | 17 | static struct ipc_namespace *create_ipc_ns(void) |
18 | { | 18 | { |
19 | struct ipc_namespace *ns; | 19 | struct ipc_namespace *ns; |
20 | int err; | 20 | int err; |
@@ -48,18 +48,9 @@ static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns) | |||
48 | 48 | ||
49 | struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) | 49 | struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) |
50 | { | 50 | { |
51 | struct ipc_namespace *new_ns; | ||
52 | |||
53 | BUG_ON(!ns); | ||
54 | get_ipc_ns(ns); | ||
55 | |||
56 | if (!(flags & CLONE_NEWIPC)) | 51 | if (!(flags & CLONE_NEWIPC)) |
57 | return ns; | 52 | return get_ipc_ns(ns); |
58 | 53 | return create_ipc_ns(); | |
59 | new_ns = clone_ipc_ns(ns); | ||
60 | |||
61 | put_ipc_ns(ns); | ||
62 | return new_ns; | ||
63 | } | 54 | } |
64 | 55 | ||
65 | /* | 56 | /* |
@@ -92,6 +83,30 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, | |||
92 | up_write(&ids->rw_mutex); | 83 | up_write(&ids->rw_mutex); |
93 | } | 84 | } |
94 | 85 | ||
86 | static void free_ipc_ns(struct ipc_namespace *ns) | ||
87 | { | ||
88 | /* | ||
89 | * Unregistering the hotplug notifier at the beginning guarantees | ||
90 | * that the ipc namespace won't be freed while we are inside the | ||
91 | * callback routine. Since the blocking_notifier_chain_XXX routines | ||
92 | * hold a rw lock on the notifier list, unregister_ipcns_notifier() | ||
93 | * won't take the rw lock before blocking_notifier_call_chain() has | ||
94 | * released the rd lock. | ||
95 | */ | ||
96 | unregister_ipcns_notifier(ns); | ||
97 | sem_exit_ns(ns); | ||
98 | msg_exit_ns(ns); | ||
99 | shm_exit_ns(ns); | ||
100 | kfree(ns); | ||
101 | atomic_dec(&nr_ipc_ns); | ||
102 | |||
103 | /* | ||
104 | * Do the ipcns removal notification after decrementing nr_ipc_ns in | ||
105 | * order to have a correct value when recomputing msgmni. | ||
106 | */ | ||
107 | ipcns_notify(IPCNS_REMOVED); | ||
108 | } | ||
109 | |||
95 | /* | 110 | /* |
96 | * put_ipc_ns - drop a reference to an ipc namespace. | 111 | * put_ipc_ns - drop a reference to an ipc namespace. |
97 | * @ns: the namespace to put | 112 | * @ns: the namespace to put |
@@ -117,27 +132,3 @@ void put_ipc_ns(struct ipc_namespace *ns) | |||
117 | free_ipc_ns(ns); | 132 | free_ipc_ns(ns); |
118 | } | 133 | } |
119 | } | 134 | } |
120 | |||
121 | void free_ipc_ns(struct ipc_namespace *ns) | ||
122 | { | ||
123 | /* | ||
124 | * Unregistering the hotplug notifier at the beginning guarantees | ||
125 | * that the ipc namespace won't be freed while we are inside the | ||
126 | * callback routine. Since the blocking_notifier_chain_XXX routines | ||
127 | * hold a rw lock on the notifier list, unregister_ipcns_notifier() | ||
128 | * won't take the rw lock before blocking_notifier_call_chain() has | ||
129 | * released the rd lock. | ||
130 | */ | ||
131 | unregister_ipcns_notifier(ns); | ||
132 | sem_exit_ns(ns); | ||
133 | msg_exit_ns(ns); | ||
134 | shm_exit_ns(ns); | ||
135 | kfree(ns); | ||
136 | atomic_dec(&nr_ipc_ns); | ||
137 | |||
138 | /* | ||
139 | * Do the ipcns removal notification after decrementing nr_ipc_ns in | ||
140 | * order to have a correct value when recomputing msgmni. | ||
141 | */ | ||
142 | ipcns_notify(IPCNS_REMOVED); | ||
143 | } | ||
@@ -384,7 +384,6 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
384 | error = PTR_ERR(file); | 384 | error = PTR_ERR(file); |
385 | if (IS_ERR(file)) | 385 | if (IS_ERR(file)) |
386 | goto no_file; | 386 | goto no_file; |
387 | ima_shm_check(file); | ||
388 | 387 | ||
389 | id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); | 388 | id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); |
390 | if (id < 0) { | 389 | if (id < 0) { |
@@ -891,7 +890,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
891 | file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); | 890 | file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); |
892 | if (!file) | 891 | if (!file) |
893 | goto out_free; | 892 | goto out_free; |
894 | ima_shm_check(file); | 893 | ima_counts_get(file); |
895 | 894 | ||
896 | file->private_data = sfd; | 895 | file->private_data = sfd; |
897 | file->f_mapping = shp->shm_file->f_mapping; | 896 | file->f_mapping = shp->shm_file->f_mapping; |
diff --git a/ipc/util.h b/ipc/util.h index 1187332a89d2..ab3ebf2621b9 100644 --- a/ipc/util.h +++ b/ipc/util.h | |||
@@ -128,7 +128,7 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out); | |||
128 | struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | 128 | struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, |
129 | struct ipc64_perm *perm, int extra_perm); | 129 | struct ipc64_perm *perm, int extra_perm); |
130 | 130 | ||
131 | #if defined(__ia64__) || defined(__x86_64__) || defined(__hppa__) || defined(__XTENSA__) | 131 | #ifndef __ARCH_WANT_IPC_PARSE_VERSION |
132 | /* On IA-64, we always use the "64-bit version" of the IPC structures. */ | 132 | /* On IA-64, we always use the "64-bit version" of the IPC structures. */ |
133 | # define ipc_parse_version(cmd) IPC_64 | 133 | # define ipc_parse_version(cmd) IPC_64 |
134 | #else | 134 | #else |
@@ -171,5 +171,6 @@ static inline void ipc_unlock(struct kern_ipc_perm *perm) | |||
171 | struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id); | 171 | struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id); |
172 | int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, | 172 | int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, |
173 | struct ipc_ops *ops, struct ipc_params *params); | 173 | struct ipc_ops *ops, struct ipc_params *params); |
174 | 174 | void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, | |
175 | void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)); | ||
175 | #endif | 176 | #endif |