diff options
Diffstat (limited to 'ipc/sem.c')
-rw-r--r-- | ipc/sem.c | 76 |
1 files changed, 29 insertions, 47 deletions
@@ -97,7 +97,7 @@ | |||
97 | 97 | ||
98 | static struct ipc_ids init_sem_ids; | 98 | static struct ipc_ids init_sem_ids; |
99 | 99 | ||
100 | static int newary(struct ipc_namespace *, key_t, int, int); | 100 | static int newary(struct ipc_namespace *, struct ipc_params *); |
101 | static void freeary(struct ipc_namespace *, struct sem_array *); | 101 | static void freeary(struct ipc_namespace *, struct sem_array *); |
102 | #ifdef CONFIG_PROC_FS | 102 | #ifdef CONFIG_PROC_FS |
103 | static int sysvipc_sem_proc_show(struct seq_file *s, void *it); | 103 | static int sysvipc_sem_proc_show(struct seq_file *s, void *it); |
@@ -214,12 +214,15 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) | |||
214 | */ | 214 | */ |
215 | #define IN_WAKEUP 1 | 215 | #define IN_WAKEUP 1 |
216 | 216 | ||
217 | static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg) | 217 | static int newary(struct ipc_namespace *ns, struct ipc_params *params) |
218 | { | 218 | { |
219 | int id; | 219 | int id; |
220 | int retval; | 220 | int retval; |
221 | struct sem_array *sma; | 221 | struct sem_array *sma; |
222 | int size; | 222 | int size; |
223 | key_t key = params->key; | ||
224 | int nsems = params->u.nsems; | ||
225 | int semflg = params->flg; | ||
223 | 226 | ||
224 | if (!nsems) | 227 | if (!nsems) |
225 | return -EINVAL; | 228 | return -EINVAL; |
@@ -263,61 +266,40 @@ static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg) | |||
263 | return sma->sem_perm.id; | 266 | return sma->sem_perm.id; |
264 | } | 267 | } |
265 | 268 | ||
266 | asmlinkage long sys_semget (key_t key, int nsems, int semflg) | 269 | |
270 | static inline int sem_security(void *sma, int semflg) | ||
271 | { | ||
272 | return security_sem_associate((struct sem_array *) sma, semflg); | ||
273 | } | ||
274 | |||
275 | static inline int sem_more_checks(void *sma, struct ipc_params *params) | ||
276 | { | ||
277 | if (params->u.nsems > ((struct sem_array *)sma)->sem_nsems) | ||
278 | return -EINVAL; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | asmlinkage long sys_semget(key_t key, int nsems, int semflg) | ||
267 | { | 284 | { |
268 | int err; | ||
269 | struct sem_array *sma; | ||
270 | struct ipc_namespace *ns; | 285 | struct ipc_namespace *ns; |
286 | struct ipc_ops sem_ops; | ||
287 | struct ipc_params sem_params; | ||
271 | 288 | ||
272 | ns = current->nsproxy->ipc_ns; | 289 | ns = current->nsproxy->ipc_ns; |
273 | 290 | ||
274 | if (nsems < 0 || nsems > ns->sc_semmsl) | 291 | if (nsems < 0 || nsems > ns->sc_semmsl) |
275 | return -EINVAL; | 292 | return -EINVAL; |
276 | 293 | ||
277 | err = idr_pre_get(&sem_ids(ns).ipcs_idr, GFP_KERNEL); | 294 | sem_ops.getnew = newary; |
295 | sem_ops.associate = sem_security; | ||
296 | sem_ops.more_checks = sem_more_checks; | ||
278 | 297 | ||
279 | if (key == IPC_PRIVATE) { | 298 | sem_params.key = key; |
280 | if (!err) | 299 | sem_params.flg = semflg; |
281 | err = -ENOMEM; | 300 | sem_params.u.nsems = nsems; |
282 | else { | ||
283 | mutex_lock(&sem_ids(ns).mutex); | ||
284 | err = newary(ns, key, nsems, semflg); | ||
285 | mutex_unlock(&sem_ids(ns).mutex); | ||
286 | } | ||
287 | } else { | ||
288 | mutex_lock(&sem_ids(ns).mutex); | ||
289 | sma = (struct sem_array *) ipc_findkey(&sem_ids(ns), key); | ||
290 | if (sma == NULL) { | ||
291 | /* key not used */ | ||
292 | if (!(semflg & IPC_CREAT)) | ||
293 | err = -ENOENT; | ||
294 | else if (!err) | ||
295 | err = -ENOMEM; | ||
296 | else | ||
297 | err = newary(ns, key, nsems, semflg); | ||
298 | } else { | ||
299 | /* sma has been locked by ipc_findkey() */ | ||
300 | |||
301 | if (semflg & IPC_CREAT && semflg & IPC_EXCL) | ||
302 | err = -EEXIST; | ||
303 | else { | ||
304 | if (nsems > sma->sem_nsems) | ||
305 | err = -EINVAL; | ||
306 | else if (ipcperms(&sma->sem_perm, semflg)) | ||
307 | err = -EACCES; | ||
308 | else { | ||
309 | err = security_sem_associate(sma, | ||
310 | semflg); | ||
311 | if (!err) | ||
312 | err = sma->sem_perm.id; | ||
313 | } | ||
314 | } | ||
315 | sem_unlock(sma); | ||
316 | } | ||
317 | mutex_unlock(&sem_ids(ns).mutex); | ||
318 | } | ||
319 | 301 | ||
320 | return err; | 302 | return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params); |
321 | } | 303 | } |
322 | 304 | ||
323 | /* Manage the doubly linked list sma->sem_pending as a FIFO: | 305 | /* Manage the doubly linked list sma->sem_pending as a FIFO: |