aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/namespace.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/namespace.c')
-rw-r--r--ipc/namespace.c53
1 files changed, 49 insertions, 4 deletions
diff --git a/ipc/namespace.c b/ipc/namespace.c
index a1094ff0befa..ce0a647869b1 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -11,10 +11,13 @@
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/fs.h> 12#include <linux/fs.h>
13#include <linux/mount.h> 13#include <linux/mount.h>
14#include <linux/user_namespace.h>
15#include <linux/proc_fs.h>
14 16
15#include "util.h" 17#include "util.h"
16 18
17static struct ipc_namespace *create_ipc_ns(void) 19static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk,
20 struct ipc_namespace *old_ns)
18{ 21{
19 struct ipc_namespace *ns; 22 struct ipc_namespace *ns;
20 int err; 23 int err;
@@ -43,14 +46,19 @@ static struct ipc_namespace *create_ipc_ns(void)
43 ipcns_notify(IPCNS_CREATED); 46 ipcns_notify(IPCNS_CREATED);
44 register_ipcns_notifier(ns); 47 register_ipcns_notifier(ns);
45 48
49 ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns);
50
46 return ns; 51 return ns;
47} 52}
48 53
49struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) 54struct ipc_namespace *copy_ipcs(unsigned long flags,
55 struct task_struct *tsk)
50{ 56{
57 struct ipc_namespace *ns = tsk->nsproxy->ipc_ns;
58
51 if (!(flags & CLONE_NEWIPC)) 59 if (!(flags & CLONE_NEWIPC))
52 return get_ipc_ns(ns); 60 return get_ipc_ns(ns);
53 return create_ipc_ns(); 61 return create_ipc_ns(tsk, ns);
54} 62}
55 63
56/* 64/*
@@ -97,7 +105,6 @@ static void free_ipc_ns(struct ipc_namespace *ns)
97 sem_exit_ns(ns); 105 sem_exit_ns(ns);
98 msg_exit_ns(ns); 106 msg_exit_ns(ns);
99 shm_exit_ns(ns); 107 shm_exit_ns(ns);
100 kfree(ns);
101 atomic_dec(&nr_ipc_ns); 108 atomic_dec(&nr_ipc_ns);
102 109
103 /* 110 /*
@@ -105,6 +112,8 @@ static void free_ipc_ns(struct ipc_namespace *ns)
105 * order to have a correct value when recomputing msgmni. 112 * order to have a correct value when recomputing msgmni.
106 */ 113 */
107 ipcns_notify(IPCNS_REMOVED); 114 ipcns_notify(IPCNS_REMOVED);
115 put_user_ns(ns->user_ns);
116 kfree(ns);
108} 117}
109 118
110/* 119/*
@@ -132,3 +141,39 @@ void put_ipc_ns(struct ipc_namespace *ns)
132 free_ipc_ns(ns); 141 free_ipc_ns(ns);
133 } 142 }
134} 143}
144
145static void *ipcns_get(struct task_struct *task)
146{
147 struct ipc_namespace *ns = NULL;
148 struct nsproxy *nsproxy;
149
150 rcu_read_lock();
151 nsproxy = task_nsproxy(task);
152 if (nsproxy)
153 ns = get_ipc_ns(nsproxy->ipc_ns);
154 rcu_read_unlock();
155
156 return ns;
157}
158
159static void ipcns_put(void *ns)
160{
161 return put_ipc_ns(ns);
162}
163
164static int ipcns_install(struct nsproxy *nsproxy, void *ns)
165{
166 /* Ditch state from the old ipc namespace */
167 exit_sem(current);
168 put_ipc_ns(nsproxy->ipc_ns);
169 nsproxy->ipc_ns = get_ipc_ns(ns);
170 return 0;
171}
172
173const struct proc_ns_operations ipcns_operations = {
174 .name = "ipc",
175 .type = CLONE_NEWIPC,
176 .get = ipcns_get,
177 .put = ipcns_put,
178 .install = ipcns_install,
179};