]>
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> | |
10 | ||
11 | struct ns_cgroup { | |
12 | struct cgroup_subsys_state css; | |
13 | spinlock_t lock; | |
14 | }; | |
15 | ||
16 | struct cgroup_subsys ns_subsys; | |
17 | ||
18 | static inline struct ns_cgroup *cgroup_to_ns( | |
19 | struct cgroup *cgroup) | |
20 | { | |
21 | return container_of(cgroup_subsys_state(cgroup, ns_subsys_id), | |
22 | struct ns_cgroup, css); | |
23 | } | |
24 | ||
25 | int ns_cgroup_clone(struct task_struct *task) | |
26 | { | |
27 | return cgroup_clone(task, &ns_subsys); | |
28 | } | |
29 | ||
30 | /* | |
31 | * Rules: | |
32 | * 1. you can only enter a cgroup which is a child of your current | |
33 | * cgroup | |
34 | * 2. you can only place another process into a cgroup if | |
35 | * a. you have CAP_SYS_ADMIN | |
36 | * b. your cgroup is an ancestor of task's destination cgroup | |
37 | * (hence either you are in the same cgroup as task, or in an | |
38 | * ancestor cgroup thereof) | |
39 | */ | |
40 | static int ns_can_attach(struct cgroup_subsys *ss, | |
41 | struct cgroup *new_cgroup, struct task_struct *task) | |
42 | { | |
43 | struct cgroup *orig; | |
44 | ||
45 | if (current != task) { | |
46 | if (!capable(CAP_SYS_ADMIN)) | |
47 | return -EPERM; | |
48 | ||
49 | if (!cgroup_is_descendant(new_cgroup)) | |
50 | return -EPERM; | |
51 | } | |
52 | ||
53 | if (atomic_read(&new_cgroup->count) != 0) | |
54 | return -EPERM; | |
55 | ||
56 | orig = task_cgroup(task, ns_subsys_id); | |
57 | if (orig && orig != new_cgroup->parent) | |
58 | return -EPERM; | |
59 | ||
60 | return 0; | |
61 | } | |
62 | ||
63 | /* | |
64 | * Rules: you can only create a cgroup if | |
65 | * 1. you are capable(CAP_SYS_ADMIN) | |
66 | * 2. the target cgroup is a descendant of your own cgroup | |
67 | */ | |
68 | static struct cgroup_subsys_state *ns_create(struct cgroup_subsys *ss, | |
69 | struct cgroup *cgroup) | |
70 | { | |
71 | struct ns_cgroup *ns_cgroup; | |
72 | ||
73 | if (!capable(CAP_SYS_ADMIN)) | |
74 | return ERR_PTR(-EPERM); | |
75 | if (!cgroup_is_descendant(cgroup)) | |
76 | return ERR_PTR(-EPERM); | |
77 | ||
78 | ns_cgroup = kzalloc(sizeof(*ns_cgroup), GFP_KERNEL); | |
79 | if (!ns_cgroup) | |
80 | return ERR_PTR(-ENOMEM); | |
81 | spin_lock_init(&ns_cgroup->lock); | |
82 | return &ns_cgroup->css; | |
83 | } | |
84 | ||
85 | static void ns_destroy(struct cgroup_subsys *ss, | |
86 | struct cgroup *cgroup) | |
87 | { | |
88 | struct ns_cgroup *ns_cgroup; | |
89 | ||
90 | ns_cgroup = cgroup_to_ns(cgroup); | |
91 | kfree(ns_cgroup); | |
92 | } | |
93 | ||
94 | struct cgroup_subsys ns_subsys = { | |
95 | .name = "ns", | |
96 | .can_attach = ns_can_attach, | |
97 | .create = ns_create, | |
98 | .destroy = ns_destroy, | |
99 | .subsys_id = ns_subsys_id, | |
100 | }; |