diff options
Diffstat (limited to 'security/device_cgroup.c')
-rw-r--r-- | security/device_cgroup.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 3aacd0fe7179..5fda7df19723 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
12 | #include <linux/seq_file.h> | 12 | #include <linux/seq_file.h> |
13 | #include <linux/rcupdate.h> | 13 | #include <linux/rcupdate.h> |
14 | #include <linux/mutex.h> | ||
14 | 15 | ||
15 | #define ACC_MKNOD 1 | 16 | #define ACC_MKNOD 1 |
16 | #define ACC_READ 2 | 17 | #define ACC_READ 2 |
@@ -21,9 +22,11 @@ | |||
21 | #define DEV_CHAR 2 | 22 | #define DEV_CHAR 2 |
22 | #define DEV_ALL 4 /* this represents all devices */ | 23 | #define DEV_ALL 4 /* this represents all devices */ |
23 | 24 | ||
25 | static DEFINE_MUTEX(devcgroup_mutex); | ||
26 | |||
24 | /* | 27 | /* |
25 | * whitelist locking rules: | 28 | * whitelist locking rules: |
26 | * hold cgroup_lock() for update/read. | 29 | * hold devcgroup_mutex for update/read. |
27 | * hold rcu_read_lock() for read. | 30 | * hold rcu_read_lock() for read. |
28 | */ | 31 | */ |
29 | 32 | ||
@@ -67,7 +70,7 @@ static int devcgroup_can_attach(struct cgroup_subsys *ss, | |||
67 | } | 70 | } |
68 | 71 | ||
69 | /* | 72 | /* |
70 | * called under cgroup_lock() | 73 | * called under devcgroup_mutex |
71 | */ | 74 | */ |
72 | static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig) | 75 | static int dev_whitelist_copy(struct list_head *dest, struct list_head *orig) |
73 | { | 76 | { |
@@ -92,7 +95,7 @@ free_and_exit: | |||
92 | 95 | ||
93 | /* Stupid prototype - don't bother combining existing entries */ | 96 | /* Stupid prototype - don't bother combining existing entries */ |
94 | /* | 97 | /* |
95 | * called under cgroup_lock() | 98 | * called under devcgroup_mutex |
96 | */ | 99 | */ |
97 | static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, | 100 | static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, |
98 | struct dev_whitelist_item *wh) | 101 | struct dev_whitelist_item *wh) |
@@ -130,7 +133,7 @@ static void whitelist_item_free(struct rcu_head *rcu) | |||
130 | } | 133 | } |
131 | 134 | ||
132 | /* | 135 | /* |
133 | * called under cgroup_lock() | 136 | * called under devcgroup_mutex |
134 | */ | 137 | */ |
135 | static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup, | 138 | static void dev_whitelist_rm(struct dev_cgroup *dev_cgroup, |
136 | struct dev_whitelist_item *wh) | 139 | struct dev_whitelist_item *wh) |
@@ -185,8 +188,10 @@ static struct cgroup_subsys_state *devcgroup_create(struct cgroup_subsys *ss, | |||
185 | list_add(&wh->list, &dev_cgroup->whitelist); | 188 | list_add(&wh->list, &dev_cgroup->whitelist); |
186 | } else { | 189 | } else { |
187 | parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); | 190 | parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup); |
191 | mutex_lock(&devcgroup_mutex); | ||
188 | ret = dev_whitelist_copy(&dev_cgroup->whitelist, | 192 | ret = dev_whitelist_copy(&dev_cgroup->whitelist, |
189 | &parent_dev_cgroup->whitelist); | 193 | &parent_dev_cgroup->whitelist); |
194 | mutex_unlock(&devcgroup_mutex); | ||
190 | if (ret) { | 195 | if (ret) { |
191 | kfree(dev_cgroup); | 196 | kfree(dev_cgroup); |
192 | return ERR_PTR(ret); | 197 | return ERR_PTR(ret); |
@@ -273,7 +278,7 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, | |||
273 | * does the access granted to dev_cgroup c contain the access | 278 | * does the access granted to dev_cgroup c contain the access |
274 | * requested in whitelist item refwh. | 279 | * requested in whitelist item refwh. |
275 | * return 1 if yes, 0 if no. | 280 | * return 1 if yes, 0 if no. |
276 | * call with c->lock held | 281 | * call with devcgroup_mutex held |
277 | */ | 282 | */ |
278 | static int may_access_whitelist(struct dev_cgroup *c, | 283 | static int may_access_whitelist(struct dev_cgroup *c, |
279 | struct dev_whitelist_item *refwh) | 284 | struct dev_whitelist_item *refwh) |
@@ -426,11 +431,11 @@ static int devcgroup_access_write(struct cgroup *cgrp, struct cftype *cft, | |||
426 | const char *buffer) | 431 | const char *buffer) |
427 | { | 432 | { |
428 | int retval; | 433 | int retval; |
429 | if (!cgroup_lock_live_group(cgrp)) | 434 | |
430 | return -ENODEV; | 435 | mutex_lock(&devcgroup_mutex); |
431 | retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp), | 436 | retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp), |
432 | cft->private, buffer); | 437 | cft->private, buffer); |
433 | cgroup_unlock(); | 438 | mutex_unlock(&devcgroup_mutex); |
434 | return retval; | 439 | return retval; |
435 | } | 440 | } |
436 | 441 | ||