9 #include <linux/ctype.h>
10 #include <linux/list.h>
13 #include <linux/slab.h>
20 #define ACC_MASK (ACC_MKNOD | ACC_READ | ACC_WRITE)
43 struct cgroup_subsys_state
css;
51 static inline struct dev_cgroup *css_to_devcgroup(
struct cgroup_subsys_state *
s)
56 static inline struct dev_cgroup *cgroup_to_devcgroup(
struct cgroup *cgroup)
58 return css_to_devcgroup(cgroup_subsys_state(cgroup, devices_subsys_id));
63 return css_to_devcgroup(task_subsys_state(task, devices_subsys_id));
68 static int devcgroup_can_attach(
struct cgroup *new_cgrp,
135 static void dev_exception_rm(
struct dev_cgroup *dev_cgroup,
150 list_del_rcu(&walk->
list);
162 static void dev_exception_clean(
struct dev_cgroup *dev_cgroup)
167 list_del_rcu(&ex->
list);
175 static struct cgroup_subsys_state *devcgroup_create(
struct cgroup *cgroup)
177 struct dev_cgroup *dev_cgroup, *parent_dev_cgroup;
178 struct cgroup *parent_cgroup;
181 dev_cgroup = kzalloc(
sizeof(*dev_cgroup),
GFP_KERNEL);
185 parent_cgroup = cgroup->parent;
187 if (parent_cgroup ==
NULL)
188 dev_cgroup->
behavior = DEVCG_DEFAULT_ALLOW;
190 parent_dev_cgroup = cgroup_to_devcgroup(parent_cgroup);
192 ret = dev_exceptions_copy(&dev_cgroup->
exceptions,
202 return &dev_cgroup->
css;
205 static void devcgroup_destroy(
struct cgroup *cgroup)
207 struct dev_cgroup *dev_cgroup;
209 dev_cgroup = cgroup_to_devcgroup(cgroup);
210 dev_exception_clean(dev_cgroup);
214 #define DEVCG_ALLOW 1
221 static void set_access(
char *acc,
short access)
233 static char type_to_char(
short type)
244 static void set_majmin(
char *
str,
unsigned m)
252 static int devcgroup_seq_read(
struct cgroup *cgroup,
struct cftype *cft,
255 struct dev_cgroup *devcgroup = cgroup_to_devcgroup(cgroup);
266 if (devcgroup->
behavior == DEVCG_DEFAULT_ALLOW) {
274 set_access(acc, ex->
access);
275 set_majmin(maj, ex->
major);
276 set_majmin(min, ex->
minor);
295 static int may_access(
struct dev_cgroup *dev_cgroup,
325 if ((dev_cgroup->
behavior == DEVCG_DEFAULT_DENY) == match)
335 static int parent_has_perm(
struct dev_cgroup *childcg,
338 struct cgroup *pcg = childcg->
css.cgroup->parent;
339 struct dev_cgroup *
parent;
343 parent = cgroup_to_devcgroup(pcg);
344 return may_access(parent, ex);
353 static inline int may_allow_all(
struct dev_cgroup *parent)
373 static int devcgroup_update_access(
struct dev_cgroup *devcgroup,
374 int filetype,
const char *
buffer)
380 struct cgroup *
p = devcgroup->
css.cgroup;
381 struct dev_cgroup *parent =
NULL;
387 parent = cgroup_to_devcgroup(p->parent);
389 memset(&ex, 0,
sizeof(ex));
396 if (!may_allow_all(parent))
398 dev_exception_clean(devcgroup);
403 rc = dev_exceptions_copy(&devcgroup->
exceptions,
409 dev_exception_clean(devcgroup);
433 memset(temp, 0,
sizeof(temp));
434 for (count = 0; count <
sizeof(
temp) - 1; count++) {
440 rc = kstrtou32(temp, 10, &ex.
major);
455 memset(temp, 0,
sizeof(temp));
456 for (count = 0; count <
sizeof(
temp) - 1; count++) {
462 rc = kstrtou32(temp, 10, &ex.
minor);
470 for (b++, count = 0; count < 3; count++, b++) {
492 if (!parent_has_perm(devcgroup, &ex))
500 dev_exception_rm(devcgroup, &ex);
503 return dev_exception_add(devcgroup, &ex);
511 dev_exception_rm(devcgroup, &ex);
514 return dev_exception_add(devcgroup, &ex);
521 static int devcgroup_access_write(
struct cgroup *cgrp,
struct cftype *cft,
527 retval = devcgroup_update_access(cgroup_to_devcgroup(cgrp),
528 cft->private, buffer);
533 static struct cftype dev_cgroup_files[] = {
536 .write_string = devcgroup_access_write,
541 .write_string = devcgroup_access_write,
546 .read_seq_string = devcgroup_seq_read,
554 .can_attach = devcgroup_can_attach,
555 .create = devcgroup_create,
556 .destroy = devcgroup_destroy,
557 .subsys_id = devices_subsys_id,
558 .base_cftypes = dev_cgroup_files,
567 .broken_hierarchy =
true,
580 static int __devcgroup_check_permission(
short type,
u32 major,
u32 minor,
583 struct dev_cgroup *dev_cgroup;
587 memset(&ex, 0,
sizeof(ex));
594 dev_cgroup = task_devcgroup(
current);
595 rc = may_access(dev_cgroup, &ex);
606 short type, access = 0;
617 return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
633 return __devcgroup_check_permission(type,
MAJOR(dev),
MINOR(dev),