diff options
Diffstat (limited to 'security/device_cgroup.c')
-rw-r--r-- | security/device_cgroup.c | 38 |
1 files changed, 28 insertions, 10 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 4ea583689eec..fd764a0858d0 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 | } |
@@ -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 | ||