aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/util.c')
-rw-r--r--ipc/util.c101
1 files changed, 100 insertions, 1 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 2a205875d277..03b88798f71f 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -197,7 +197,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
197 * If key is found ipc contains its ipc structure 197 * If key is found ipc contains its ipc structure
198 */ 198 */
199 199
200struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) 200static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
201{ 201{
202 struct kern_ipc_perm *ipc; 202 struct kern_ipc_perm *ipc;
203 int next_id; 203 int next_id;
@@ -301,6 +301,105 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
301} 301}
302 302
303/** 303/**
304 * ipcget_new - create a new ipc object
305 * @ns: namespace
306 * @ids: identifer set
307 * @ops: the actual creation routine to call
308 * @params: its parameters
309 *
310 * This routine is called sys_msgget, sys_semget() and sys_shmget() when
311 * the key is IPC_PRIVATE
312 */
313int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
314 struct ipc_ops *ops, struct ipc_params *params)
315{
316 int err;
317
318 err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);
319
320 if (!err)
321 return -ENOMEM;
322
323 mutex_lock(&ids->mutex);
324 err = ops->getnew(ns, params);
325 mutex_unlock(&ids->mutex);
326
327 return err;
328}
329
330/**
331 * ipc_check_perms - check security and permissions for an IPC
332 * @ipcp: ipc permission set
333 * @ids: identifer set
334 * @ops: the actual security routine to call
335 * @params: its parameters
336 */
337static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops,
338 struct ipc_params *params)
339{
340 int err;
341
342 if (ipcperms(ipcp, params->flg))
343 err = -EACCES;
344 else {
345 err = ops->associate(ipcp, params->flg);
346 if (!err)
347 err = ipcp->id;
348 }
349
350 return err;
351}
352
353/**
354 * ipcget_public - get an ipc object or create a new one
355 * @ns: namespace
356 * @ids: identifer set
357 * @ops: the actual creation routine to call
358 * @params: its parameters
359 *
360 * This routine is called sys_msgget, sys_semget() and sys_shmget() when
361 * the key is not IPC_PRIVATE
362 */
363int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
364 struct ipc_ops *ops, struct ipc_params *params)
365{
366 struct kern_ipc_perm *ipcp;
367 int flg = params->flg;
368 int err;
369
370 err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);
371
372 mutex_lock(&ids->mutex);
373 ipcp = ipc_findkey(ids, params->key);
374 if (ipcp == NULL) {
375 /* key not used */
376 if (!(flg & IPC_CREAT))
377 err = -ENOENT;
378 else if (!err)
379 err = -ENOMEM;
380 else
381 err = ops->getnew(ns, params);
382 } else {
383 /* ipc object has been locked by ipc_findkey() */
384
385 if (flg & IPC_CREAT && flg & IPC_EXCL)
386 err = -EEXIST;
387 else {
388 err = 0;
389 if (ops->more_checks)
390 err = ops->more_checks(ipcp, params);
391 if (!err)
392 err = ipc_check_perms(ipcp, ops, params);
393 }
394 ipc_unlock(ipcp);
395 }
396 mutex_unlock(&ids->mutex);
397
398 return err;
399}
400
401
402/**
304 * ipc_rmid - remove an IPC identifier 403 * ipc_rmid - remove an IPC identifier
305 * @ids: identifier set 404 * @ids: identifier set
306 * @id: ipc perm structure containing the identifier to remove 405 * @id: ipc perm structure containing the identifier to remove