Lines Matching +full:container +full:- +full:rules
1 // SPDX-License-Identifier: GPL-2.0
3 * device_cgroup.c - device cgroup subsystem
8 #include <linux/bpf-cgroup.h>
30 * exception list locking rules:
72 list_add_tail(&new->list, dest); in dev_exceptions_copy()
79 list_del(&ex->list); in dev_exceptions_copy()
82 return -ENOMEM; in dev_exceptions_copy()
92 list_move_tail(&ex->list, dest); in dev_exceptions_move()
108 return -ENOMEM; in dev_exception_add()
110 list_for_each_entry(walk, &dev_cgroup->exceptions, list) { in dev_exception_add()
111 if (walk->type != ex->type) in dev_exception_add()
113 if (walk->major != ex->major) in dev_exception_add()
115 if (walk->minor != ex->minor) in dev_exception_add()
118 walk->access |= ex->access; in dev_exception_add()
124 list_add_tail_rcu(&excopy->list, &dev_cgroup->exceptions); in dev_exception_add()
138 list_for_each_entry_safe(walk, tmp, &dev_cgroup->exceptions, list) { in dev_exception_rm()
139 if (walk->type != ex->type) in dev_exception_rm()
141 if (walk->major != ex->major) in dev_exception_rm()
143 if (walk->minor != ex->minor) in dev_exception_rm()
146 walk->access &= ~ex->access; in dev_exception_rm()
147 if (!walk->access) { in dev_exception_rm()
148 list_del_rcu(&walk->list); in dev_exception_rm()
158 list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) { in __dev_exception_clean()
159 list_del_rcu(&ex->list); in __dev_exception_clean()
165 * dev_exception_clean - frees all entries of the exception list
179 return (devcg->behavior != DEVCG_DEFAULT_NONE); in is_devcg_online()
183 * devcgroup_online - initializes devcgroup's behavior and exceptions based on
191 struct dev_cgroup *parent_dev_cgroup = css_to_devcgroup(css->parent); in devcgroup_online()
197 dev_cgroup->behavior = DEVCG_DEFAULT_ALLOW; in devcgroup_online()
199 ret = dev_exceptions_copy(&dev_cgroup->exceptions, in devcgroup_online()
200 &parent_dev_cgroup->exceptions); in devcgroup_online()
202 dev_cgroup->behavior = parent_dev_cgroup->behavior; in devcgroup_online()
214 dev_cgroup->behavior = DEVCG_DEFAULT_NONE; in devcgroup_offline()
228 return ERR_PTR(-ENOMEM); in devcgroup_css_alloc()
229 INIT_LIST_HEAD(&dev_cgroup->exceptions); in devcgroup_css_alloc()
230 dev_cgroup->behavior = DEVCG_DEFAULT_NONE; in devcgroup_css_alloc()
232 return &dev_cgroup->css; in devcgroup_css_alloc()
290 * - Only show the "all devices" when the default policy is to allow in devcgroup_seq_show()
291 * - List the exceptions in case the default policy is to deny in devcgroup_seq_show()
294 if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) { in devcgroup_seq_show()
301 list_for_each_entry_rcu(ex, &devcgroup->exceptions, list) { in devcgroup_seq_show()
302 set_access(acc, ex->access); in devcgroup_seq_show()
303 set_majmin(maj, ex->major); in devcgroup_seq_show()
304 set_majmin(min, ex->minor); in devcgroup_seq_show()
305 seq_printf(m, "%c %s:%s %s\n", type_to_char(ex->type), in devcgroup_seq_show()
315 * match_exception - iterates the exception list trying to find a complete match
333 if ((type & DEVCG_DEV_BLOCK) && !(ex->type & DEVCG_DEV_BLOCK)) in match_exception()
335 if ((type & DEVCG_DEV_CHAR) && !(ex->type & DEVCG_DEV_CHAR)) in match_exception()
337 if (ex->major != ~0 && ex->major != major) in match_exception()
339 if (ex->minor != ~0 && ex->minor != minor) in match_exception()
342 if (access & (~ex->access)) in match_exception()
350 * match_exception_partial - iterates the exception list trying to find a partial match
371 if ((type & DEVCG_DEV_BLOCK) && !(ex->type & DEVCG_DEV_BLOCK)) in match_exception_partial()
373 if ((type & DEVCG_DEV_CHAR) && !(ex->type & DEVCG_DEV_CHAR)) in match_exception_partial()
379 if (ex->major != ~0 && major != ~0 && ex->major != major) in match_exception_partial()
381 if (ex->minor != ~0 && minor != ~0 && ex->minor != minor) in match_exception_partial()
388 if (!(access & ex->access)) in match_exception_partial()
396 * verify_new_ex - verifies if a new exception is allowed by parent cgroup's permissions
414 if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) { in verify_new_ex()
427 match = match_exception_partial(&dev_cgroup->exceptions, in verify_new_ex()
428 refex->type, in verify_new_ex()
429 refex->major, in verify_new_ex()
430 refex->minor, in verify_new_ex()
431 refex->access); in verify_new_ex()
444 match = match_exception(&dev_cgroup->exceptions, refex->type, in verify_new_ex()
445 refex->major, refex->minor, in verify_new_ex()
446 refex->access); in verify_new_ex()
465 struct dev_cgroup *parent = css_to_devcgroup(childcg->css.parent); in parent_has_perm()
469 return verify_new_ex(parent, ex, childcg->behavior); in parent_has_perm()
473 * parent_allows_removal - verify if it's ok to remove an exception
486 struct dev_cgroup *parent = css_to_devcgroup(childcg->css.parent); in parent_allows_removal()
492 if (childcg->behavior == DEVCG_DEFAULT_DENY) in parent_allows_removal()
499 return !match_exception_partial(&parent->exceptions, ex->type, in parent_allows_removal()
500 ex->major, ex->minor, ex->access); in parent_allows_removal()
504 * may_allow_all - checks if it's possible to change the behavior to
505 * allow based on parent's rules.
513 return parent->behavior == DEVCG_DEFAULT_ALLOW; in may_allow_all()
517 * revalidate_active_exceptions - walks through the active exception list and
525 * This function is responsible for re-evaluating all the cgroup's active
527 * Refer to Documentation/admin-guide/cgroup-v1/devices.rst for more details.
534 list_for_each_safe(this, tmp, &devcg->exceptions) { in revalidate_active_exceptions()
542 * propagate_exception - propagates a new exception to the children
556 css_for_each_descendant_pre(pos, &devcg_root->css) { in propagate_exception()
565 if (pos == &devcg_root->css || !is_devcg_online(devcg)) in propagate_exception()
574 if (devcg_root->behavior == DEVCG_DEFAULT_ALLOW && in propagate_exception()
575 devcg->behavior == DEVCG_DEFAULT_ALLOW) { in propagate_exception()
598 * Modify the exception list using allow/deny rules.
600 * so we can give a container CAP_MKNOD to let it create devices but not
606 * Taking rules away is always allowed (given CAP_SYS_ADMIN). Granting
607 * new access is only allowed if you're in the top-level cgroup, or your
617 struct dev_cgroup *parent = css_to_devcgroup(devcgroup->css.parent); in devcgroup_update_access()
621 return -EPERM; in devcgroup_update_access()
631 if (css_has_online_children(&devcgroup->css)) in devcgroup_update_access()
632 return -EINVAL; in devcgroup_update_access()
635 return -EPERM; in devcgroup_update_access()
637 devcgroup->behavior = DEVCG_DEFAULT_ALLOW; in devcgroup_update_access()
644 &devcgroup->exceptions); in devcgroup_update_access()
648 rc = dev_exceptions_copy(&devcgroup->exceptions, in devcgroup_update_access()
649 &parent->exceptions); in devcgroup_update_access()
651 dev_exceptions_move(&devcgroup->exceptions, in devcgroup_update_access()
655 devcgroup->behavior = DEVCG_DEFAULT_ALLOW; in devcgroup_update_access()
659 if (css_has_online_children(&devcgroup->css)) in devcgroup_update_access()
660 return -EINVAL; in devcgroup_update_access()
663 devcgroup->behavior = DEVCG_DEFAULT_DENY; in devcgroup_update_access()
666 return -EINVAL; in devcgroup_update_access()
676 return -EINVAL; in devcgroup_update_access()
680 return -EINVAL; in devcgroup_update_access()
687 for (count = 0; count < sizeof(temp) - 1; count++) { in devcgroup_update_access()
695 return -EINVAL; in devcgroup_update_access()
697 return -EINVAL; in devcgroup_update_access()
700 return -EINVAL; in devcgroup_update_access()
709 for (count = 0; count < sizeof(temp) - 1; count++) { in devcgroup_update_access()
717 return -EINVAL; in devcgroup_update_access()
719 return -EINVAL; in devcgroup_update_access()
722 return -EINVAL; in devcgroup_update_access()
739 return -EINVAL; in devcgroup_update_access()
750 if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) { in devcgroup_update_access()
753 return -EPERM; in devcgroup_update_access()
759 return -EPERM; in devcgroup_update_access()
768 if (devcgroup->behavior == DEVCG_DEFAULT_DENY) in devcgroup_update_access()
779 rc = -EINVAL; in devcgroup_update_access()
791 of_cft(of)->private, strstrip(buf)); in devcgroup_access_write()
824 * devcgroup_legacy_check_permission - checks if an inode operation is permitted
830 * returns 0 on success, -EPERM case the operation is not permitted
840 if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) in devcgroup_legacy_check_permission()
842 rc = !match_exception_partial(&dev_cgroup->exceptions, in devcgroup_legacy_check_permission()
846 rc = match_exception(&dev_cgroup->exceptions, type, major, in devcgroup_legacy_check_permission()
851 return -EPERM; in devcgroup_legacy_check_permission()