aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/util.c')
-rw-r--r--ipc/util.c122
1 files changed, 57 insertions, 65 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 76c1f3461e22..fd1b50da9db8 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -33,6 +33,7 @@
33#include <linux/audit.h> 33#include <linux/audit.h>
34#include <linux/nsproxy.h> 34#include <linux/nsproxy.h>
35#include <linux/rwsem.h> 35#include <linux/rwsem.h>
36#include <linux/ipc_namespace.h>
36 37
37#include <asm/unistd.h> 38#include <asm/unistd.h>
38 39
@@ -51,66 +52,6 @@ struct ipc_namespace init_ipc_ns = {
51 }, 52 },
52}; 53};
53 54
54static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
55{
56 int err;
57 struct ipc_namespace *ns;
58
59 err = -ENOMEM;
60 ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
61 if (ns == NULL)
62 goto err_mem;
63
64 err = sem_init_ns(ns);
65 if (err)
66 goto err_sem;
67 err = msg_init_ns(ns);
68 if (err)
69 goto err_msg;
70 err = shm_init_ns(ns);
71 if (err)
72 goto err_shm;
73
74 kref_init(&ns->kref);
75 return ns;
76
77err_shm:
78 msg_exit_ns(ns);
79err_msg:
80 sem_exit_ns(ns);
81err_sem:
82 kfree(ns);
83err_mem:
84 return ERR_PTR(err);
85}
86
87struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
88{
89 struct ipc_namespace *new_ns;
90
91 BUG_ON(!ns);
92 get_ipc_ns(ns);
93
94 if (!(flags & CLONE_NEWIPC))
95 return ns;
96
97 new_ns = clone_ipc_ns(ns);
98
99 put_ipc_ns(ns);
100 return new_ns;
101}
102
103void free_ipc_ns(struct kref *kref)
104{
105 struct ipc_namespace *ns;
106
107 ns = container_of(kref, struct ipc_namespace, kref);
108 sem_exit_ns(ns);
109 msg_exit_ns(ns);
110 shm_exit_ns(ns);
111 kfree(ns);
112}
113
114/** 55/**
115 * ipc_init - initialise IPC subsystem 56 * ipc_init - initialise IPC subsystem
116 * 57 *
@@ -307,7 +248,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
307 * This routine is called by sys_msgget, sys_semget() and sys_shmget() 248 * This routine is called by sys_msgget, sys_semget() and sys_shmget()
308 * when the key is IPC_PRIVATE. 249 * when the key is IPC_PRIVATE.
309 */ 250 */
310int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, 251static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
311 struct ipc_ops *ops, struct ipc_params *params) 252 struct ipc_ops *ops, struct ipc_params *params)
312{ 253{
313 int err; 254 int err;
@@ -371,7 +312,7 @@ static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops,
371 * 312 *
372 * On success, the ipc id is returned. 313 * On success, the ipc id is returned.
373 */ 314 */
374int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, 315static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
375 struct ipc_ops *ops, struct ipc_params *params) 316 struct ipc_ops *ops, struct ipc_params *params)
376{ 317{
377 struct kern_ipc_perm *ipcp; 318 struct kern_ipc_perm *ipcp;
@@ -769,6 +710,57 @@ struct kern_ipc_perm *ipc_lock_down(struct ipc_ids *ids, int id)
769 return out; 710 return out;
770} 711}
771 712
713struct kern_ipc_perm *ipc_lock_check_down(struct ipc_ids *ids, int id)
714{
715 struct kern_ipc_perm *out;
716
717 out = ipc_lock_down(ids, id);
718 if (IS_ERR(out))
719 return out;
720
721 if (ipc_checkid(out, id)) {
722 ipc_unlock(out);
723 return ERR_PTR(-EIDRM);
724 }
725
726 return out;
727}
728
729struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id)
730{
731 struct kern_ipc_perm *out;
732
733 out = ipc_lock(ids, id);
734 if (IS_ERR(out))
735 return out;
736
737 if (ipc_checkid(out, id)) {
738 ipc_unlock(out);
739 return ERR_PTR(-EIDRM);
740 }
741
742 return out;
743}
744
745/**
746 * ipcget - Common sys_*get() code
747 * @ns : namsepace
748 * @ids : IPC identifier set
749 * @ops : operations to be called on ipc object creation, permission checks
750 * and further checks
751 * @params : the parameters needed by the previous operations.
752 *
753 * Common routine called by sys_msgget(), sys_semget() and sys_shmget().
754 */
755int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
756 struct ipc_ops *ops, struct ipc_params *params)
757{
758 if (params->key == IPC_PRIVATE)
759 return ipcget_new(ns, ids, ops, params);
760 else
761 return ipcget_public(ns, ids, ops, params);
762}
763
772#ifdef __ARCH_WANT_IPC_PARSE_VERSION 764#ifdef __ARCH_WANT_IPC_PARSE_VERSION
773 765
774 766
@@ -841,7 +833,7 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
841 if (ipc && ipc != SEQ_START_TOKEN) 833 if (ipc && ipc != SEQ_START_TOKEN)
842 ipc_unlock(ipc); 834 ipc_unlock(ipc);
843 835
844 return sysvipc_find_ipc(iter->ns->ids[iface->ids], *pos, pos); 836 return sysvipc_find_ipc(&iter->ns->ids[iface->ids], *pos, pos);
845} 837}
846 838
847/* 839/*
@@ -854,7 +846,7 @@ static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
854 struct ipc_proc_iface *iface = iter->iface; 846 struct ipc_proc_iface *iface = iter->iface;
855 struct ipc_ids *ids; 847 struct ipc_ids *ids;
856 848
857 ids = iter->ns->ids[iface->ids]; 849 ids = &iter->ns->ids[iface->ids];
858 850
859 /* 851 /*
860 * Take the lock - this will be released by the corresponding 852 * Take the lock - this will be released by the corresponding
@@ -885,7 +877,7 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it)
885 if (ipc && ipc != SEQ_START_TOKEN) 877 if (ipc && ipc != SEQ_START_TOKEN)
886 ipc_unlock(ipc); 878 ipc_unlock(ipc);
887 879
888 ids = iter->ns->ids[iface->ids]; 880 ids = &iter->ns->ids[iface->ids];
889 /* Release the lock we took in start() */ 881 /* Release the lock we took in start() */
890 up_read(&ids->rw_mutex); 882 up_read(&ids->rw_mutex);
891} 883}