diff options
Diffstat (limited to 'security/device_cgroup.c')
-rw-r--r-- | security/device_cgroup.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 4ea583689eec..ddd92cec78ed 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -49,10 +49,14 @@ struct dev_cgroup { | |||
49 | spinlock_t lock; | 49 | spinlock_t lock; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) | ||
53 | { | ||
54 | return container_of(s, struct dev_cgroup, css); | ||
55 | } | ||
56 | |||
52 | static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup) | 57 | static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup) |
53 | { | 58 | { |
54 | return container_of(cgroup_subsys_state(cgroup, devices_subsys_id), | 59 | return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id)); |
55 | struct dev_cgroup, css); | ||
56 | } | 60 | } |
57 | 61 | ||
58 | struct cgroup_subsys devices_subsys; | 62 | struct cgroup_subsys devices_subsys; |
@@ -102,7 +106,7 @@ free_and_exit: | |||
102 | static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, | 106 | static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, |
103 | struct dev_whitelist_item *wh) | 107 | struct dev_whitelist_item *wh) |
104 | { | 108 | { |
105 | struct dev_whitelist_item *whcopy; | 109 | struct dev_whitelist_item *whcopy, *walk; |
106 | 110 | ||
107 | whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL); | 111 | whcopy = kmalloc(sizeof(*whcopy), GFP_KERNEL); |
108 | if (!whcopy) | 112 | if (!whcopy) |
@@ -110,7 +114,21 @@ static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, | |||
110 | 114 | ||
111 | memcpy(whcopy, wh, sizeof(*whcopy)); | 115 | memcpy(whcopy, wh, sizeof(*whcopy)); |
112 | spin_lock(&dev_cgroup->lock); | 116 | spin_lock(&dev_cgroup->lock); |
113 | list_add_tail(&whcopy->list, &dev_cgroup->whitelist); | 117 | list_for_each_entry(walk, &dev_cgroup->whitelist, list) { |
118 | if (walk->type != wh->type) | ||
119 | continue; | ||
120 | if (walk->major != wh->major) | ||
121 | continue; | ||
122 | if (walk->minor != wh->minor) | ||
123 | continue; | ||
124 | |||
125 | walk->access |= wh->access; | ||
126 | kfree(whcopy); | ||
127 | whcopy = NULL; | ||
128 | } | ||
129 | |||
130 | if (whcopy != NULL) | ||
131 | list_add_tail(&whcopy->list, &dev_cgroup->whitelist); | ||
114 | spin_unlock(&dev_cgroup->lock); | 132 | spin_unlock(&dev_cgroup->lock); |
115 | return 0; | 133 | return 0; |
116 | } | 134 | } |
@@ -204,7 +222,7 @@ static void devcgroup_destroy(struct cgroup_subsys *ss, | |||
204 | #define DEVCG_DENY 2 | 222 | #define DEVCG_DENY 2 |
205 | #define DEVCG_LIST 3 | 223 | #define DEVCG_LIST 3 |
206 | 224 | ||
207 | #define MAJMINLEN 10 | 225 | #define MAJMINLEN 13 |
208 | #define ACCLEN 4 | 226 | #define ACCLEN 4 |
209 | 227 | ||
210 | static void set_access(char *acc, short access) | 228 | static void set_access(char *acc, short access) |
@@ -236,7 +254,7 @@ static void set_majmin(char *str, unsigned m) | |||
236 | if (m == ~0) | 254 | if (m == ~0) |
237 | sprintf(str, "*"); | 255 | sprintf(str, "*"); |
238 | else | 256 | else |
239 | snprintf(str, MAJMINLEN, "%d", m); | 257 | snprintf(str, MAJMINLEN, "%u", m); |
240 | } | 258 | } |
241 | 259 | ||
242 | static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, | 260 | static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, |
@@ -282,7 +300,7 @@ static int may_access_whitelist(struct dev_cgroup *c, | |||
282 | continue; | 300 | continue; |
283 | if (whitem->minor != ~0 && whitem->minor != refwh->minor) | 301 | if (whitem->minor != ~0 && whitem->minor != refwh->minor) |
284 | continue; | 302 | continue; |
285 | if (refwh->access & (~(whitem->access | ACC_MASK))) | 303 | if (refwh->access & (~whitem->access)) |
286 | continue; | 304 | continue; |
287 | return 1; | 305 | return 1; |
288 | } | 306 | } |
@@ -364,6 +382,8 @@ static ssize_t devcgroup_access_write(struct cgroup *cgroup, struct cftype *cft, | |||
364 | case 'a': | 382 | case 'a': |
365 | wh.type = DEV_ALL; | 383 | wh.type = DEV_ALL; |
366 | wh.access = ACC_MASK; | 384 | wh.access = ACC_MASK; |
385 | wh.major = ~0; | ||
386 | wh.minor = ~0; | ||
367 | goto handle; | 387 | goto handle; |
368 | case 'b': | 388 | case 'b': |
369 | wh.type = DEV_BLOCK; | 389 | wh.type = DEV_BLOCK; |
@@ -502,7 +522,6 @@ struct cgroup_subsys devices_subsys = { | |||
502 | 522 | ||
503 | int devcgroup_inode_permission(struct inode *inode, int mask) | 523 | int devcgroup_inode_permission(struct inode *inode, int mask) |
504 | { | 524 | { |
505 | struct cgroup *cgroup; | ||
506 | struct dev_cgroup *dev_cgroup; | 525 | struct dev_cgroup *dev_cgroup; |
507 | struct dev_whitelist_item *wh; | 526 | struct dev_whitelist_item *wh; |
508 | 527 | ||
@@ -511,8 +530,8 @@ int devcgroup_inode_permission(struct inode *inode, int mask) | |||
511 | return 0; | 530 | return 0; |
512 | if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) | 531 | if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode)) |
513 | return 0; | 532 | return 0; |
514 | cgroup = task_cgroup(current, devices_subsys.subsys_id); | 533 | dev_cgroup = css_to_devcgroup(task_subsys_state(current, |
515 | dev_cgroup = cgroup_to_devcgroup(cgroup); | 534 | devices_subsys_id)); |
516 | if (!dev_cgroup) | 535 | if (!dev_cgroup) |
517 | return 0; | 536 | return 0; |
518 | 537 | ||
@@ -543,12 +562,11 @@ acc_check: | |||
543 | 562 | ||
544 | int devcgroup_inode_mknod(int mode, dev_t dev) | 563 | int devcgroup_inode_mknod(int mode, dev_t dev) |
545 | { | 564 | { |
546 | struct cgroup *cgroup; | ||
547 | struct dev_cgroup *dev_cgroup; | 565 | struct dev_cgroup *dev_cgroup; |
548 | struct dev_whitelist_item *wh; | 566 | struct dev_whitelist_item *wh; |
549 | 567 | ||
550 | cgroup = task_cgroup(current, devices_subsys.subsys_id); | 568 | dev_cgroup = css_to_devcgroup(task_subsys_state(current, |
551 | dev_cgroup = cgroup_to_devcgroup(cgroup); | 569 | devices_subsys_id)); |
552 | if (!dev_cgroup) | 570 | if (!dev_cgroup) |
553 | return 0; | 571 | return 0; |
554 | 572 | ||