x86/efi: Enforce CONFIG_RELOCATABLE for EFI boot stub
[linux/fpc-iii.git] / security / device_cgroup.c
blobe34818192c8d9792a7069b861856b42b052c26cc
1 /*
2 * device_cgroup.c - device cgroup subsystem
4 * Copyright 2007 IBM Corp
5 */
7 #include <linux/device_cgroup.h>
8 #include <linux/cgroup.h>
9 #include <linux/ctype.h>
10 #include <linux/list.h>
11 #include <linux/uaccess.h>
12 #include <linux/seq_file.h>
13 #include <linux/slab.h>
14 #include <linux/rcupdate.h>
15 #include <linux/mutex.h>
17 #define ACC_MKNOD 1
18 #define ACC_READ 2
19 #define ACC_WRITE 4
20 #define ACC_MASK (ACC_MKNOD | ACC_READ | ACC_WRITE)
22 #define DEV_BLOCK 1
23 #define DEV_CHAR 2
24 #define DEV_ALL 4 /* this represents all devices */
26 static DEFINE_MUTEX(devcgroup_mutex);
28 enum devcg_behavior {
29 DEVCG_DEFAULT_NONE,
30 DEVCG_DEFAULT_ALLOW,
31 DEVCG_DEFAULT_DENY,
35 * exception list locking rules:
36 * hold devcgroup_mutex for update/read.
37 * hold rcu_read_lock() for read.
40 struct dev_exception_item {
41 u32 major, minor;
42 short type;
43 short access;
44 struct list_head list;
45 struct rcu_head rcu;
48 struct dev_cgroup {
49 struct cgroup_subsys_state css;
50 struct list_head exceptions;
51 enum devcg_behavior behavior;
54 static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
56 return s ? container_of(s, struct dev_cgroup, css) : NULL;
59 static inline struct dev_cgroup *task_devcgroup(struct task_struct *task)
61 return css_to_devcgroup(task_css(task, devices_subsys_id));
64 struct cgroup_subsys devices_subsys;
66 static int devcgroup_can_attach(struct cgroup_subsys_state *new_css,
67 struct cgroup_taskset *set)
69 struct task_struct *task = cgroup_taskset_first(set);
71 if (current != task && !capable(CAP_SYS_ADMIN))
72 return -EPERM;
73 return 0;
77 * called under devcgroup_mutex
79 static int dev_exceptions_copy(struct list_head *dest, struct list_head *orig)
81 struct dev_exception_item *ex, *tmp, *new;
83 lockdep_assert_held(&devcgroup_mutex);
85 list_for_each_entry(ex, orig, list) {
86 new = kmemdup(ex, sizeof(*ex), GFP_KERNEL);
87 if (!new)
88 goto free_and_exit;
89 list_add_tail(&new->list, dest);
92 return 0;
94 free_and_exit:
95 list_for_each_entry_safe(ex, tmp, dest, list) {
96 list_del(&ex->list);
97 kfree(ex);
99 return -ENOMEM;
103 * called under devcgroup_mutex
105 static int dev_exception_add(struct dev_cgroup *dev_cgroup,
106 struct dev_exception_item *ex)
108 struct dev_exception_item *excopy, *walk;
110 lockdep_assert_held(&devcgroup_mutex);
112 excopy = kmemdup(ex, sizeof(*ex), GFP_KERNEL);
113 if (!excopy)
114 return -ENOMEM;
116 list_for_each_entry(walk, &dev_cgroup->exceptions, list) {
117 if (walk->type != ex->type)
118 continue;
119 if (walk->major != ex->major)
120 continue;
121 if (walk->minor != ex->minor)
122 continue;
124 walk->access |= ex->access;
125 kfree(excopy);
126 excopy = NULL;
129 if (excopy != NULL)
130 list_add_tail_rcu(&excopy->list, &dev_cgroup->exceptions);
131 return 0;
135 * called under devcgroup_mutex
137 static void dev_exception_rm(struct dev_cgroup *dev_cgroup,
138 struct dev_exception_item *ex)
140 struct dev_exception_item *walk, *tmp;
142 lockdep_assert_held(&devcgroup_mutex);
144 list_for_each_entry_safe(walk, tmp, &dev_cgroup->exceptions, list) {
145 if (walk->type != ex->type)
146 continue;
147 if (walk->major != ex->major)
148 continue;
149 if (walk->minor != ex->minor)
150 continue;
152 walk->access &= ~ex->access;
153 if (!walk->access) {
154 list_del_rcu(&walk->list);
155 kfree_rcu(walk, rcu);
160 static void __dev_exception_clean(struct dev_cgroup *dev_cgroup)
162 struct dev_exception_item *ex, *tmp;
164 list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) {
165 list_del_rcu(&ex->list);
166 kfree_rcu(ex, rcu);
171 * dev_exception_clean - frees all entries of the exception list
172 * @dev_cgroup: dev_cgroup with the exception list to be cleaned
174 * called under devcgroup_mutex
176 static void dev_exception_clean(struct dev_cgroup *dev_cgroup)
178 lockdep_assert_held(&devcgroup_mutex);
180 __dev_exception_clean(dev_cgroup);
183 static inline bool is_devcg_online(const struct dev_cgroup *devcg)
185 return (devcg->behavior != DEVCG_DEFAULT_NONE);
189 * devcgroup_online - initializes devcgroup's behavior and exceptions based on
190 * parent's
191 * @css: css getting online
192 * returns 0 in case of success, error code otherwise
194 static int devcgroup_online(struct cgroup_subsys_state *css)
196 struct dev_cgroup *dev_cgroup = css_to_devcgroup(css);
197 struct dev_cgroup *parent_dev_cgroup = css_to_devcgroup(css_parent(css));
198 int ret = 0;
200 mutex_lock(&devcgroup_mutex);
202 if (parent_dev_cgroup == NULL)
203 dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW;
204 else {
205 ret = dev_exceptions_copy(&dev_cgroup->exceptions,
206 &parent_dev_cgroup->exceptions);
207 if (!ret)
208 dev_cgroup->behavior = parent_dev_cgroup->behavior;
210 mutex_unlock(&devcgroup_mutex);
212 return ret;
215 static void devcgroup_offline(struct cgroup_subsys_state *css)
217 struct dev_cgroup *dev_cgroup = css_to_devcgroup(css);
219 mutex_lock(&devcgroup_mutex);
220 dev_cgroup->behavior = DEVCG_DEFAULT_NONE;
221 mutex_unlock(&devcgroup_mutex);
225 * called from kernel/cgroup.c with cgroup_lock() held.
227 static struct cgroup_subsys_state *
228 devcgroup_css_alloc(struct cgroup_subsys_state *parent_css)
230 struct dev_cgroup *dev_cgroup;
232 dev_cgroup = kzalloc(sizeof(*dev_cgroup), GFP_KERNEL);
233 if (!dev_cgroup)
234 return ERR_PTR(-ENOMEM);
235 INIT_LIST_HEAD(&dev_cgroup->exceptions);
236 dev_cgroup->behavior = DEVCG_DEFAULT_NONE;
238 return &dev_cgroup->css;
241 static void devcgroup_css_free(struct cgroup_subsys_state *css)
243 struct dev_cgroup *dev_cgroup = css_to_devcgroup(css);
245 __dev_exception_clean(dev_cgroup);
246 kfree(dev_cgroup);
249 #define DEVCG_ALLOW 1
250 #define DEVCG_DENY 2
251 #define DEVCG_LIST 3
253 #define MAJMINLEN 13
254 #define ACCLEN 4
256 static void set_access(char *acc, short access)
258 int idx = 0;
259 memset(acc, 0, ACCLEN);
260 if (access & ACC_READ)
261 acc[idx++] = 'r';
262 if (access & ACC_WRITE)
263 acc[idx++] = 'w';
264 if (access & ACC_MKNOD)
265 acc[idx++] = 'm';
268 static char type_to_char(short type)
270 if (type == DEV_ALL)
271 return 'a';
272 if (type == DEV_CHAR)
273 return 'c';
274 if (type == DEV_BLOCK)
275 return 'b';
276 return 'X';
279 static void set_majmin(char *str, unsigned m)
281 if (m == ~0)
282 strcpy(str, "*");
283 else
284 sprintf(str, "%u", m);
287 static int devcgroup_seq_read(struct cgroup_subsys_state *css,
288 struct cftype *cft, struct seq_file *m)
290 struct dev_cgroup *devcgroup = css_to_devcgroup(css);
291 struct dev_exception_item *ex;
292 char maj[MAJMINLEN], min[MAJMINLEN], acc[ACCLEN];
294 rcu_read_lock();
296 * To preserve the compatibility:
297 * - Only show the "all devices" when the default policy is to allow
298 * - List the exceptions in case the default policy is to deny
299 * This way, the file remains as a "whitelist of devices"
301 if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
302 set_access(acc, ACC_MASK);
303 set_majmin(maj, ~0);
304 set_majmin(min, ~0);
305 seq_printf(m, "%c %s:%s %s\n", type_to_char(DEV_ALL),
306 maj, min, acc);
307 } else {
308 list_for_each_entry_rcu(ex, &devcgroup->exceptions, list) {
309 set_access(acc, ex->access);
310 set_majmin(maj, ex->major);
311 set_majmin(min, ex->minor);
312 seq_printf(m, "%c %s:%s %s\n", type_to_char(ex->type),
313 maj, min, acc);
316 rcu_read_unlock();
318 return 0;
322 * match_exception - iterates the exception list trying to match a rule
323 * based on type, major, minor and access type. It is
324 * considered a match if an exception is found that
325 * will contain the entire range of provided parameters.
326 * @exceptions: list of exceptions
327 * @type: device type (DEV_BLOCK or DEV_CHAR)
328 * @major: device file major number, ~0 to match all
329 * @minor: device file minor number, ~0 to match all
330 * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD)
332 * returns: true in case it matches an exception completely
334 static bool match_exception(struct list_head *exceptions, short type,
335 u32 major, u32 minor, short access)
337 struct dev_exception_item *ex;
339 list_for_each_entry_rcu(ex, exceptions, list) {
340 if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
341 continue;
342 if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR))
343 continue;
344 if (ex->major != ~0 && ex->major != major)
345 continue;
346 if (ex->minor != ~0 && ex->minor != minor)
347 continue;
348 /* provided access cannot have more than the exception rule */
349 if (access & (~ex->access))
350 continue;
351 return true;
353 return false;
357 * match_exception_partial - iterates the exception list trying to match a rule
358 * based on type, major, minor and access type. It is
359 * considered a match if an exception's range is
360 * found to contain *any* of the devices specified by
361 * provided parameters. This is used to make sure no
362 * extra access is being granted that is forbidden by
363 * any of the exception list.
364 * @exceptions: list of exceptions
365 * @type: device type (DEV_BLOCK or DEV_CHAR)
366 * @major: device file major number, ~0 to match all
367 * @minor: device file minor number, ~0 to match all
368 * @access: permission mask (ACC_READ, ACC_WRITE, ACC_MKNOD)
370 * returns: true in case the provided range mat matches an exception completely
372 static bool match_exception_partial(struct list_head *exceptions, short type,
373 u32 major, u32 minor, short access)
375 struct dev_exception_item *ex;
377 list_for_each_entry_rcu(ex, exceptions, list) {
378 if ((type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
379 continue;
380 if ((type & DEV_CHAR) && !(ex->type & DEV_CHAR))
381 continue;
383 * We must be sure that both the exception and the provided
384 * range aren't masking all devices
386 if (ex->major != ~0 && major != ~0 && ex->major != major)
387 continue;
388 if (ex->minor != ~0 && minor != ~0 && ex->minor != minor)
389 continue;
391 * In order to make sure the provided range isn't matching
392 * an exception, all its access bits shouldn't match the
393 * exception's access bits
395 if (!(access & ex->access))
396 continue;
397 return true;
399 return false;
403 * verify_new_ex - verifies if a new exception is part of what is allowed
404 * by a dev cgroup based on the default policy +
405 * exceptions. This is used to make sure a child cgroup
406 * won't have more privileges than its parent
407 * @dev_cgroup: dev cgroup to be tested against
408 * @refex: new exception
409 * @behavior: behavior of the exception's dev_cgroup
411 static bool verify_new_ex(struct dev_cgroup *dev_cgroup,
412 struct dev_exception_item *refex,
413 enum devcg_behavior behavior)
415 bool match = false;
417 rcu_lockdep_assert(rcu_read_lock_held() ||
418 lockdep_is_held(&devcgroup_mutex),
419 "device_cgroup:verify_new_ex called without proper synchronization");
421 if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) {
422 if (behavior == DEVCG_DEFAULT_ALLOW) {
424 * new exception in the child doesn't matter, only
425 * adding extra restrictions
427 return true;
428 } else {
430 * new exception in the child will add more devices
431 * that can be acessed, so it can't match any of
432 * parent's exceptions, even slightly
434 match = match_exception_partial(&dev_cgroup->exceptions,
435 refex->type,
436 refex->major,
437 refex->minor,
438 refex->access);
440 if (match)
441 return false;
442 return true;
444 } else {
446 * Only behavior == DEVCG_DEFAULT_DENY allowed here, therefore
447 * the new exception will add access to more devices and must
448 * be contained completely in an parent's exception to be
449 * allowed
451 match = match_exception(&dev_cgroup->exceptions, refex->type,
452 refex->major, refex->minor,
453 refex->access);
455 if (match)
456 /* parent has an exception that matches the proposed */
457 return true;
458 else
459 return false;
461 return false;
465 * parent_has_perm:
466 * when adding a new allow rule to a device exception list, the rule
467 * must be allowed in the parent device
469 static int parent_has_perm(struct dev_cgroup *childcg,
470 struct dev_exception_item *ex)
472 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&childcg->css));
474 if (!parent)
475 return 1;
476 return verify_new_ex(parent, ex, childcg->behavior);
480 * parent_allows_removal - verify if it's ok to remove an exception
481 * @childcg: child cgroup from where the exception will be removed
482 * @ex: exception being removed
484 * When removing an exception in cgroups with default ALLOW policy, it must
485 * be checked if removing it will give the child cgroup more access than the
486 * parent.
488 * Return: true if it's ok to remove exception, false otherwise
490 static bool parent_allows_removal(struct dev_cgroup *childcg,
491 struct dev_exception_item *ex)
493 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&childcg->css));
495 if (!parent)
496 return true;
498 /* It's always allowed to remove access to devices */
499 if (childcg->behavior == DEVCG_DEFAULT_DENY)
500 return true;
503 * Make sure you're not removing part or a whole exception existing in
504 * the parent cgroup
506 return !match_exception_partial(&parent->exceptions, ex->type,
507 ex->major, ex->minor, ex->access);
511 * may_allow_all - checks if it's possible to change the behavior to
512 * allow based on parent's rules.
513 * @parent: device cgroup's parent
514 * returns: != 0 in case it's allowed, 0 otherwise
516 static inline int may_allow_all(struct dev_cgroup *parent)
518 if (!parent)
519 return 1;
520 return parent->behavior == DEVCG_DEFAULT_ALLOW;
524 * revalidate_active_exceptions - walks through the active exception list and
525 * revalidates the exceptions based on parent's
526 * behavior and exceptions. The exceptions that
527 * are no longer valid will be removed.
528 * Called with devcgroup_mutex held.
529 * @devcg: cgroup which exceptions will be checked
531 * This is one of the three key functions for hierarchy implementation.
532 * This function is responsible for re-evaluating all the cgroup's active
533 * exceptions due to a parent's exception change.
534 * Refer to Documentation/cgroups/devices.txt for more details.
536 static void revalidate_active_exceptions(struct dev_cgroup *devcg)
538 struct dev_exception_item *ex;
539 struct list_head *this, *tmp;
541 list_for_each_safe(this, tmp, &devcg->exceptions) {
542 ex = container_of(this, struct dev_exception_item, list);
543 if (!parent_has_perm(devcg, ex))
544 dev_exception_rm(devcg, ex);
549 * propagate_exception - propagates a new exception to the children
550 * @devcg_root: device cgroup that added a new exception
551 * @ex: new exception to be propagated
553 * returns: 0 in case of success, != 0 in case of error
555 static int propagate_exception(struct dev_cgroup *devcg_root,
556 struct dev_exception_item *ex)
558 struct cgroup_subsys_state *pos;
559 int rc = 0;
561 rcu_read_lock();
563 css_for_each_descendant_pre(pos, &devcg_root->css) {
564 struct dev_cgroup *devcg = css_to_devcgroup(pos);
567 * Because devcgroup_mutex is held, no devcg will become
568 * online or offline during the tree walk (see on/offline
569 * methods), and online ones are safe to access outside RCU
570 * read lock without bumping refcnt.
572 if (pos == &devcg_root->css || !is_devcg_online(devcg))
573 continue;
575 rcu_read_unlock();
578 * in case both root's behavior and devcg is allow, a new
579 * restriction means adding to the exception list
581 if (devcg_root->behavior == DEVCG_DEFAULT_ALLOW &&
582 devcg->behavior == DEVCG_DEFAULT_ALLOW) {
583 rc = dev_exception_add(devcg, ex);
584 if (rc)
585 break;
586 } else {
588 * in the other possible cases:
589 * root's behavior: allow, devcg's: deny
590 * root's behavior: deny, devcg's: deny
591 * the exception will be removed
593 dev_exception_rm(devcg, ex);
595 revalidate_active_exceptions(devcg);
597 rcu_read_lock();
600 rcu_read_unlock();
601 return rc;
604 static inline bool has_children(struct dev_cgroup *devcgroup)
606 struct cgroup *cgrp = devcgroup->css.cgroup;
608 return !list_empty(&cgrp->children);
612 * Modify the exception list using allow/deny rules.
613 * CAP_SYS_ADMIN is needed for this. It's at least separate from CAP_MKNOD
614 * so we can give a container CAP_MKNOD to let it create devices but not
615 * modify the exception list.
616 * It seems likely we'll want to add a CAP_CONTAINER capability to allow
617 * us to also grant CAP_SYS_ADMIN to containers without giving away the
618 * device exception list controls, but for now we'll stick with CAP_SYS_ADMIN
620 * Taking rules away is always allowed (given CAP_SYS_ADMIN). Granting
621 * new access is only allowed if you're in the top-level cgroup, or your
622 * parent cgroup has the access you're asking for.
624 static int devcgroup_update_access(struct dev_cgroup *devcgroup,
625 int filetype, const char *buffer)
627 const char *b;
628 char temp[12]; /* 11 + 1 characters needed for a u32 */
629 int count, rc = 0;
630 struct dev_exception_item ex;
631 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&devcgroup->css));
633 if (!capable(CAP_SYS_ADMIN))
634 return -EPERM;
636 memset(&ex, 0, sizeof(ex));
637 b = buffer;
639 switch (*b) {
640 case 'a':
641 switch (filetype) {
642 case DEVCG_ALLOW:
643 if (has_children(devcgroup))
644 return -EINVAL;
646 if (!may_allow_all(parent))
647 return -EPERM;
648 dev_exception_clean(devcgroup);
649 devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
650 if (!parent)
651 break;
653 rc = dev_exceptions_copy(&devcgroup->exceptions,
654 &parent->exceptions);
655 if (rc)
656 return rc;
657 break;
658 case DEVCG_DENY:
659 if (has_children(devcgroup))
660 return -EINVAL;
662 dev_exception_clean(devcgroup);
663 devcgroup->behavior = DEVCG_DEFAULT_DENY;
664 break;
665 default:
666 return -EINVAL;
668 return 0;
669 case 'b':
670 ex.type = DEV_BLOCK;
671 break;
672 case 'c':
673 ex.type = DEV_CHAR;
674 break;
675 default:
676 return -EINVAL;
678 b++;
679 if (!isspace(*b))
680 return -EINVAL;
681 b++;
682 if (*b == '*') {
683 ex.major = ~0;
684 b++;
685 } else if (isdigit(*b)) {
686 memset(temp, 0, sizeof(temp));
687 for (count = 0; count < sizeof(temp) - 1; count++) {
688 temp[count] = *b;
689 b++;
690 if (!isdigit(*b))
691 break;
693 rc = kstrtou32(temp, 10, &ex.major);
694 if (rc)
695 return -EINVAL;
696 } else {
697 return -EINVAL;
699 if (*b != ':')
700 return -EINVAL;
701 b++;
703 /* read minor */
704 if (*b == '*') {
705 ex.minor = ~0;
706 b++;
707 } else if (isdigit(*b)) {
708 memset(temp, 0, sizeof(temp));
709 for (count = 0; count < sizeof(temp) - 1; count++) {
710 temp[count] = *b;
711 b++;
712 if (!isdigit(*b))
713 break;
715 rc = kstrtou32(temp, 10, &ex.minor);
716 if (rc)
717 return -EINVAL;
718 } else {
719 return -EINVAL;
721 if (!isspace(*b))
722 return -EINVAL;
723 for (b++, count = 0; count < 3; count++, b++) {
724 switch (*b) {
725 case 'r':
726 ex.access |= ACC_READ;
727 break;
728 case 'w':
729 ex.access |= ACC_WRITE;
730 break;
731 case 'm':
732 ex.access |= ACC_MKNOD;
733 break;
734 case '\n':
735 case '\0':
736 count = 3;
737 break;
738 default:
739 return -EINVAL;
743 switch (filetype) {
744 case DEVCG_ALLOW:
746 * If the default policy is to allow by default, try to remove
747 * an matching exception instead. And be silent about it: we
748 * don't want to break compatibility
750 if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
751 /* Check if the parent allows removing it first */
752 if (!parent_allows_removal(devcgroup, &ex))
753 return -EPERM;
754 dev_exception_rm(devcgroup, &ex);
755 break;
758 if (!parent_has_perm(devcgroup, &ex))
759 return -EPERM;
760 rc = dev_exception_add(devcgroup, &ex);
761 break;
762 case DEVCG_DENY:
764 * If the default policy is to deny by default, try to remove
765 * an matching exception instead. And be silent about it: we
766 * don't want to break compatibility
768 if (devcgroup->behavior == DEVCG_DEFAULT_DENY)
769 dev_exception_rm(devcgroup, &ex);
770 else
771 rc = dev_exception_add(devcgroup, &ex);
773 if (rc)
774 break;
775 /* we only propagate new restrictions */
776 rc = propagate_exception(devcgroup, &ex);
777 break;
778 default:
779 rc = -EINVAL;
781 return rc;
784 static int devcgroup_access_write(struct cgroup_subsys_state *css,
785 struct cftype *cft, const char *buffer)
787 int retval;
789 mutex_lock(&devcgroup_mutex);
790 retval = devcgroup_update_access(css_to_devcgroup(css),
791 cft->private, buffer);
792 mutex_unlock(&devcgroup_mutex);
793 return retval;
796 static struct cftype dev_cgroup_files[] = {
798 .name = "allow",
799 .write_string = devcgroup_access_write,
800 .private = DEVCG_ALLOW,
803 .name = "deny",
804 .write_string = devcgroup_access_write,
805 .private = DEVCG_DENY,
808 .name = "list",
809 .read_seq_string = devcgroup_seq_read,
810 .private = DEVCG_LIST,
812 { } /* terminate */
815 struct cgroup_subsys devices_subsys = {
816 .name = "devices",
817 .can_attach = devcgroup_can_attach,
818 .css_alloc = devcgroup_css_alloc,
819 .css_free = devcgroup_css_free,
820 .css_online = devcgroup_online,
821 .css_offline = devcgroup_offline,
822 .subsys_id = devices_subsys_id,
823 .base_cftypes = dev_cgroup_files,
827 * __devcgroup_check_permission - checks if an inode operation is permitted
828 * @dev_cgroup: the dev cgroup to be tested against
829 * @type: device type
830 * @major: device major number
831 * @minor: device minor number
832 * @access: combination of ACC_WRITE, ACC_READ and ACC_MKNOD
834 * returns 0 on success, -EPERM case the operation is not permitted
836 static int __devcgroup_check_permission(short type, u32 major, u32 minor,
837 short access)
839 struct dev_cgroup *dev_cgroup;
840 bool rc;
842 rcu_read_lock();
843 dev_cgroup = task_devcgroup(current);
844 if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW)
845 /* Can't match any of the exceptions, even partially */
846 rc = !match_exception_partial(&dev_cgroup->exceptions,
847 type, major, minor, access);
848 else
849 /* Need to match completely one exception to be allowed */
850 rc = match_exception(&dev_cgroup->exceptions, type, major,
851 minor, access);
852 rcu_read_unlock();
854 if (!rc)
855 return -EPERM;
857 return 0;
860 int __devcgroup_inode_permission(struct inode *inode, int mask)
862 short type, access = 0;
864 if (S_ISBLK(inode->i_mode))
865 type = DEV_BLOCK;
866 if (S_ISCHR(inode->i_mode))
867 type = DEV_CHAR;
868 if (mask & MAY_WRITE)
869 access |= ACC_WRITE;
870 if (mask & MAY_READ)
871 access |= ACC_READ;
873 return __devcgroup_check_permission(type, imajor(inode), iminor(inode),
874 access);
877 int devcgroup_inode_mknod(int mode, dev_t dev)
879 short type;
881 if (!S_ISBLK(mode) && !S_ISCHR(mode))
882 return 0;
884 if (S_ISBLK(mode))
885 type = DEV_BLOCK;
886 else
887 type = DEV_CHAR;
889 return __devcgroup_check_permission(type, MAJOR(dev), MINOR(dev),
890 ACC_MKNOD);