Blame view

kernel/pid_namespace.c 5.39 KB
74bd59bb3   Pavel Emelyanov   namespaces: clean...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  /*
   * Pid namespaces
   *
   * Authors:
   *    (C) 2007 Pavel Emelyanov <xemul@openvz.org>, OpenVZ, SWsoft Inc.
   *    (C) 2007 Sukadev Bhattiprolu <sukadev@us.ibm.com>, IBM
   *     Many thanks to Oleg Nesterov for comments and help
   *
   */
  
  #include <linux/pid.h>
  #include <linux/pid_namespace.h>
  #include <linux/syscalls.h>
  #include <linux/err.h>
0b6b030fc   Pavel Emelyanov   bsdacct: switch f...
15
  #include <linux/acct.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
16
  #include <linux/slab.h>
4308eebbe   Eric W. Biederman   pidns: call pid_n...
17
  #include <linux/proc_fs.h>
74bd59bb3   Pavel Emelyanov   namespaces: clean...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  
  #define BITS_PER_PAGE		(PAGE_SIZE*8)
  
  struct pid_cache {
  	int nr_ids;
  	char name[16];
  	struct kmem_cache *cachep;
  	struct list_head list;
  };
  
  static LIST_HEAD(pid_caches_lh);
  static DEFINE_MUTEX(pid_caches_mutex);
  static struct kmem_cache *pid_ns_cachep;
  
  /*
   * creates the kmem cache to allocate pids from.
   * @nr_ids: the number of numerical ids this pid will have to carry
   */
  
  static struct kmem_cache *create_pid_cachep(int nr_ids)
  {
  	struct pid_cache *pcache;
  	struct kmem_cache *cachep;
  
  	mutex_lock(&pid_caches_mutex);
  	list_for_each_entry(pcache, &pid_caches_lh, list)
  		if (pcache->nr_ids == nr_ids)
  			goto out;
  
  	pcache = kmalloc(sizeof(struct pid_cache), GFP_KERNEL);
  	if (pcache == NULL)
  		goto err_alloc;
  
  	snprintf(pcache->name, sizeof(pcache->name), "pid_%d", nr_ids);
  	cachep = kmem_cache_create(pcache->name,
  			sizeof(struct pid) + (nr_ids - 1) * sizeof(struct upid),
  			0, SLAB_HWCACHE_ALIGN, NULL);
  	if (cachep == NULL)
  		goto err_cachep;
  
  	pcache->nr_ids = nr_ids;
  	pcache->cachep = cachep;
  	list_add(&pcache->list, &pid_caches_lh);
  out:
  	mutex_unlock(&pid_caches_mutex);
  	return pcache->cachep;
  
  err_cachep:
  	kfree(pcache);
  err_alloc:
  	mutex_unlock(&pid_caches_mutex);
  	return NULL;
  }
ed469a63c   Alexey Dobriyan   pidns: make creat...
71
  static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
74bd59bb3   Pavel Emelyanov   namespaces: clean...
72
73
  {
  	struct pid_namespace *ns;
ed469a63c   Alexey Dobriyan   pidns: make creat...
74
  	unsigned int level = parent_pid_ns->level + 1;
4308eebbe   Eric W. Biederman   pidns: call pid_n...
75
  	int i, err = -ENOMEM;
74bd59bb3   Pavel Emelyanov   namespaces: clean...
76

84406c153   Pavel Emelyanov   pidns: use kzallo...
77
  	ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
78
79
80
81
82
83
84
85
86
87
88
89
  	if (ns == NULL)
  		goto out;
  
  	ns->pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL);
  	if (!ns->pidmap[0].page)
  		goto out_free;
  
  	ns->pid_cachep = create_pid_cachep(level + 1);
  	if (ns->pid_cachep == NULL)
  		goto out_free_map;
  
  	kref_init(&ns->kref);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
90
  	ns->level = level;
ed469a63c   Alexey Dobriyan   pidns: make creat...
91
  	ns->parent = get_pid_ns(parent_pid_ns);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
92
93
94
  
  	set_bit(0, ns->pidmap[0].page);
  	atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
84406c153   Pavel Emelyanov   pidns: use kzallo...
95
  	for (i = 1; i < PIDMAP_ENTRIES; i++)
74bd59bb3   Pavel Emelyanov   namespaces: clean...
96
  		atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
97

4308eebbe   Eric W. Biederman   pidns: call pid_n...
98
99
100
  	err = pid_ns_prepare_proc(ns);
  	if (err)
  		goto out_put_parent_pid_ns;
74bd59bb3   Pavel Emelyanov   namespaces: clean...
101
  	return ns;
4308eebbe   Eric W. Biederman   pidns: call pid_n...
102
103
  out_put_parent_pid_ns:
  	put_pid_ns(parent_pid_ns);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
104
105
106
107
108
  out_free_map:
  	kfree(ns->pidmap[0].page);
  out_free:
  	kmem_cache_free(pid_ns_cachep, ns);
  out:
4308eebbe   Eric W. Biederman   pidns: call pid_n...
109
  	return ERR_PTR(err);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
110
111
112
113
114
115
116
117
118
119
120
121
122
  }
  
  static void destroy_pid_namespace(struct pid_namespace *ns)
  {
  	int i;
  
  	for (i = 0; i < PIDMAP_ENTRIES; i++)
  		kfree(ns->pidmap[i].page);
  	kmem_cache_free(pid_ns_cachep, ns);
  }
  
  struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
  {
74bd59bb3   Pavel Emelyanov   namespaces: clean...
123
  	if (!(flags & CLONE_NEWPID))
dca4a9796   Alexey Dobriyan   pidns: rewrite co...
124
  		return get_pid_ns(old_ns);
e5a473869   Sukadev Bhattiprolu   pidns: deny CLONE...
125
  	if (flags & (CLONE_THREAD|CLONE_PARENT))
dca4a9796   Alexey Dobriyan   pidns: rewrite co...
126
127
  		return ERR_PTR(-EINVAL);
  	return create_pid_namespace(old_ns);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
  }
  
  void free_pid_ns(struct kref *kref)
  {
  	struct pid_namespace *ns, *parent;
  
  	ns = container_of(kref, struct pid_namespace, kref);
  
  	parent = ns->parent;
  	destroy_pid_namespace(ns);
  
  	if (parent != NULL)
  		put_pid_ns(parent);
  }
  
  void zap_pid_ns_processes(struct pid_namespace *pid_ns)
  {
  	int nr;
  	int rc;
e4da026f9   Sukadev Bhattiprolu   signals: zap_pid_...
147
  	struct task_struct *task;
74bd59bb3   Pavel Emelyanov   namespaces: clean...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
  
  	/*
  	 * The last thread in the cgroup-init thread group is terminating.
  	 * Find remaining pid_ts in the namespace, signal and wait for them
  	 * to exit.
  	 *
  	 * Note:  This signals each threads in the namespace - even those that
  	 * 	  belong to the same thread group, To avoid this, we would have
  	 * 	  to walk the entire tasklist looking a processes in this
  	 * 	  namespace, but that could be unnecessarily expensive if the
  	 * 	  pid namespace has just a few processes. Or we need to
  	 * 	  maintain a tasklist for each pid namespace.
  	 *
  	 */
  	read_lock(&tasklist_lock);
  	nr = next_pidmap(pid_ns, 1);
  	while (nr > 0) {
e4da026f9   Sukadev Bhattiprolu   signals: zap_pid_...
165
166
167
  		rcu_read_lock();
  
  		/*
13aa9a6b0   Oleg Nesterov   pid_ns: zap_pid_n...
168
169
  		 * Any nested-container's init processes won't ignore the
  		 * SEND_SIG_NOINFO signal, see send_signal()->si_fromuser().
e4da026f9   Sukadev Bhattiprolu   signals: zap_pid_...
170
171
172
  		 */
  		task = pid_task(find_vpid(nr), PIDTYPE_PID);
  		if (task)
13aa9a6b0   Oleg Nesterov   pid_ns: zap_pid_n...
173
  			send_sig_info(SIGKILL, SEND_SIG_NOINFO, task);
e4da026f9   Sukadev Bhattiprolu   signals: zap_pid_...
174
175
  
  		rcu_read_unlock();
74bd59bb3   Pavel Emelyanov   namespaces: clean...
176
177
178
179
180
181
182
183
  		nr = next_pidmap(pid_ns, nr);
  	}
  	read_unlock(&tasklist_lock);
  
  	do {
  		clear_thread_flag(TIF_SIGPENDING);
  		rc = sys_wait4(-1, NULL, __WALL, NULL);
  	} while (rc != -ECHILD);
0b6b030fc   Pavel Emelyanov   bsdacct: switch f...
184
  	acct_exit_ns(pid_ns);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
185
186
  	return;
  }
b8f566b04   Pavel Emelyanov   sysctl: add the k...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
  static int pid_ns_ctl_handler(struct ctl_table *table, int write,
  		void __user *buffer, size_t *lenp, loff_t *ppos)
  {
  	struct ctl_table tmp = *table;
  
  	if (write && !capable(CAP_SYS_ADMIN))
  		return -EPERM;
  
  	/*
  	 * Writing directly to ns' last_pid field is OK, since this field
  	 * is volatile in a living namespace anyway and a code writing to
  	 * it should synchronize its usage with external means.
  	 */
  
  	tmp.data = &current->nsproxy->pid_ns->last_pid;
  	return proc_dointvec(&tmp, write, buffer, lenp, ppos);
  }
  
  static struct ctl_table pid_ns_ctl_table[] = {
  	{
  		.procname = "ns_last_pid",
  		.maxlen = sizeof(int),
  		.mode = 0666, /* permissions are checked in the handler */
  		.proc_handler = pid_ns_ctl_handler,
  	},
  	{ }
  };
  
  static struct ctl_path kern_path[] = { { .procname = "kernel", }, { } };
74bd59bb3   Pavel Emelyanov   namespaces: clean...
216
217
218
  static __init int pid_namespaces_init(void)
  {
  	pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
b8f566b04   Pavel Emelyanov   sysctl: add the k...
219
  	register_sysctl_paths(kern_path, pid_ns_ctl_table);
74bd59bb3   Pavel Emelyanov   namespaces: clean...
220
221
222
223
  	return 0;
  }
  
  __initcall(pid_namespaces_init);