aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAristeu Rozanski <aris@redhat.com>2014-05-05 11:18:59 -0400
committerTejun Heo <tj@kernel.org>2014-05-05 11:20:12 -0400
commitd2c2b11cfa134f4fbdcc34088824da26a084d8de (patch)
treefc14e38e4a234e85bbbdb213618afcbe131fbebf
parentf5f3cf6f7e49b9529fc00a2c4629fa92cf2755fe (diff)
device_cgroup: check if exception removal is allowed
[PATCH v3 1/2] device_cgroup: check if exception removal is allowed When the device cgroup hierarchy was introduced in bd2953ebbb53 - devcg: propagate local changes down the hierarchy a specific case was overlooked. Consider the hierarchy bellow: A default policy: ALLOW, exceptions will deny access \ B default policy: ALLOW, exceptions will deny access There's no need to verify when an new exception is added to B because in this case exceptions will deny access to further devices, which is always fine. Hierarchy in device cgroup only makes sure B won't have more access than A. But when an exception is removed (by writing devices.allow), it isn't checked if the user is in fact removing an inherited exception from A, thus giving more access to B. Example: # echo 'a' >A/devices.allow # echo 'c 1:3 rw' >A/devices.deny # echo $$ >A/B/tasks # echo >/dev/null -bash: /dev/null: Operation not permitted # echo 'c 1:3 w' >A/B/devices.allow # echo >/dev/null # This shouldn't be allowed and this patch fixes it by making sure to never allow exceptions in this case to be removed if the exception is partially or fully present on the parent. v3: missing '*' in function description v2: improved log message and formatting fixes Cc: cgroups@vger.kernel.org Cc: Li Zefan <lizefan@huawei.com> Cc: stable@vger.kernel.org Signed-off-by: Aristeu Rozanski <arozansk@redhat.com> Acked-by: Serge Hallyn <serge.hallyn@canonical.com> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--security/device_cgroup.c41
1 files changed, 38 insertions, 3 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 6b1266dd92bb..9134dbf70d3e 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -463,6 +463,37 @@ static int parent_has_perm(struct dev_cgroup *childcg,
463} 463}
464 464
465/** 465/**
466 * parent_allows_removal - verify if it's ok to remove an exception
467 * @childcg: child cgroup from where the exception will be removed
468 * @ex: exception being removed
469 *
470 * When removing an exception in cgroups with default ALLOW policy, it must
471 * be checked if removing it will give the child cgroup more access than the
472 * parent.
473 *
474 * Return: true if it's ok to remove exception, false otherwise
475 */
476static bool parent_allows_removal(struct dev_cgroup *childcg,
477 struct dev_exception_item *ex)
478{
479 struct dev_cgroup *parent = css_to_devcgroup(css_parent(&childcg->css));
480
481 if (!parent)
482 return true;
483
484 /* It's always allowed to remove access to devices */
485 if (childcg->behavior == DEVCG_DEFAULT_DENY)
486 return true;
487
488 /*
489 * Make sure you're not removing part or a whole exception existing in
490 * the parent cgroup
491 */
492 return !match_exception_partial(&parent->exceptions, ex->type,
493 ex->major, ex->minor, ex->access);
494}
495
496/**
466 * may_allow_all - checks if it's possible to change the behavior to 497 * may_allow_all - checks if it's possible to change the behavior to
467 * allow based on parent's rules. 498 * allow based on parent's rules.
468 * @parent: device cgroup's parent 499 * @parent: device cgroup's parent
@@ -697,17 +728,21 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
697 728
698 switch (filetype) { 729 switch (filetype) {
699 case DEVCG_ALLOW: 730 case DEVCG_ALLOW:
700 if (!parent_has_perm(devcgroup, &ex))
701 return -EPERM;
702 /* 731 /*
703 * If the default policy is to allow by default, try to remove 732 * If the default policy is to allow by default, try to remove
704 * an matching exception instead. And be silent about it: we 733 * an matching exception instead. And be silent about it: we
705 * don't want to break compatibility 734 * don't want to break compatibility
706 */ 735 */
707 if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) { 736 if (devcgroup->behavior == DEVCG_DEFAULT_ALLOW) {
737 /* Check if the parent allows removing it first */
738 if (!parent_allows_removal(devcgroup, &ex))
739 return -EPERM;
708 dev_exception_rm(devcgroup, &ex); 740 dev_exception_rm(devcgroup, &ex);
709 return 0; 741 break;
710 } 742 }
743
744 if (!parent_has_perm(devcgroup, &ex))
745 return -EPERM;
711 rc = dev_exception_add(devcgroup, &ex); 746 rc = dev_exception_add(devcgroup, &ex);
712 break; 747 break;
713 case DEVCG_DENY: 748 case DEVCG_DENY: