aboutsummaryrefslogtreecommitdiffstats
path: root/security/device_cgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/device_cgroup.c')
-rw-r--r--security/device_cgroup.c44
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
52static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
53{
54 return container_of(s, struct dev_cgroup, css);
55}
56
52static inline struct dev_cgroup *cgroup_to_devcgroup(struct cgroup *cgroup) 57static 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
58struct cgroup_subsys devices_subsys; 62struct cgroup_subsys devices_subsys;
@@ -102,7 +106,7 @@ free_and_exit:
102static int dev_whitelist_add(struct dev_cgroup *dev_cgroup, 106static 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
210static void set_access(char *acc, short access) 228static 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
242static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, 260static 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
503int devcgroup_inode_permission(struct inode *inode, int mask) 523int 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
544int devcgroup_inode_mknod(int mode, dev_t dev) 563int 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