]>
Commit | Line | Data |
---|---|---|
858d72ea SH |
1 | /* |
2 | * ns_cgroup.c - namespace cgroup subsystem | |
3 | * | |
4 | * Copyright 2006, 2007 IBM Corp | |
5 | */ | |
6 | ||
7 | #include <linux/module.h> | |
8 | #include <linux/cgroup.h> | |
9 | #include <linux/fs.h> | |
e885dcde | 10 | #include <linux/proc_fs.h> |
1aeb272c | 11 | #include <linux/slab.h> |
3ff31d0c | 12 | #include <linux/nsproxy.h> |
858d72ea SH |
13 | |
14 | struct ns_cgroup { | |
15 | struct cgroup_subsys_state css; | |
858d72ea SH |
16 | }; |
17 | ||
18 | struct cgroup_subsys ns_subsys; | |
19 | ||
20 | static inline struct ns_cgroup *cgroup_to_ns( | |
21 | struct cgroup *cgroup) | |
22 | { | |
23 | return container_of(cgroup_subsys_state(cgroup, ns_subsys_id), | |
24 | struct ns_cgroup, css); | |
25 | } | |
26 | ||
e885dcde | 27 | int ns_cgroup_clone(struct task_struct *task, struct pid *pid) |
858d72ea | 28 | { |
e885dcde SH |
29 | char name[PROC_NUMBUF]; |
30 | ||
31 | snprintf(name, PROC_NUMBUF, "%d", pid_vnr(pid)); | |
32 | return cgroup_clone(task, &ns_subsys, name); | |
858d72ea SH |
33 | } |
34 | ||
35 | /* | |
36 | * Rules: | |
313e924c | 37 | * 1. you can only enter a cgroup which is a descendant of your current |
858d72ea SH |
38 | * cgroup |
39 | * 2. you can only place another process into a cgroup if | |
40 | * a. you have CAP_SYS_ADMIN | |
41 | * b. your cgroup is an ancestor of task's destination cgroup | |
42 | * (hence either you are in the same cgroup as task, or in an | |
43 | * ancestor cgroup thereof) | |
44 | */ | |
45 | static int ns_can_attach(struct cgroup_subsys *ss, | |
46 | struct cgroup *new_cgroup, struct task_struct *task) | |
47 | { | |
858d72ea SH |
48 | if (current != task) { |
49 | if (!capable(CAP_SYS_ADMIN)) | |
50 | return -EPERM; | |
51 | ||
313e924c | 52 | if (!cgroup_is_descendant(new_cgroup, current)) |
858d72ea SH |
53 | return -EPERM; |
54 | } | |
55 | ||
313e924c | 56 | if (!cgroup_is_descendant(new_cgroup, task)) |
858d72ea SH |
57 | return -EPERM; |
58 | ||
59 | return 0; | |
60 | } | |
61 | ||
62 | /* | |
63 | * Rules: you can only create a cgroup if | |
64 | * 1. you are capable(CAP_SYS_ADMIN) | |
65 | * 2. the target cgroup is a descendant of your own cgroup | |
66 | */ | |
67 | static struct cgroup_subsys_state *ns_create(struct cgroup_subsys *ss, | |
68 | struct cgroup *cgroup) | |
69 | { | |
70 | struct ns_cgroup *ns_cgroup; | |
71 | ||
72 | if (!capable(CAP_SYS_ADMIN)) | |
73 | return ERR_PTR(-EPERM); | |
313e924c | 74 | if (!cgroup_is_descendant(cgroup, current)) |
858d72ea SH |
75 | return ERR_PTR(-EPERM); |
76 | ||
77 | ns_cgroup = kzalloc(sizeof(*ns_cgroup), GFP_KERNEL); | |
78 | if (!ns_cgroup) | |
79 | return ERR_PTR(-ENOMEM); | |
858d72ea SH |
80 | return &ns_cgroup->css; |
81 | } | |
82 | ||
83 | static void ns_destroy(struct cgroup_subsys *ss, | |
84 | struct cgroup *cgroup) | |
85 | { | |
86 | struct ns_cgroup *ns_cgroup; | |
87 | ||
88 | ns_cgroup = cgroup_to_ns(cgroup); | |
89 | kfree(ns_cgroup); | |
90 | } | |
91 | ||
92 | struct cgroup_subsys ns_subsys = { | |
93 | .name = "ns", | |
94 | .can_attach = ns_can_attach, | |
95 | .create = ns_create, | |
96 | .destroy = ns_destroy, | |
97 | .subsys_id = ns_subsys_id, | |
98 | }; |