Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4cef7299 authored by Aristeu Rozanski's avatar Aristeu Rozanski Committed by Linus Torvalds
Browse files

device_cgroup: add proper checking when changing default behavior



Before changing a group's default behavior to ALLOW, we must check if
its parent's behavior is also ALLOW.

Signed-off-by: default avatarAristeu Rozanski <aris@redhat.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Li Zefan <lizefan@huawei.com>
Cc: James Morris <jmorris@namei.org>
Cc: Pavel Emelyanov <xemul@openvz.org>
Acked-by: default avatarSerge Hallyn <serge.hallyn@canonical.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 26fd8405
Loading
Loading
Loading
Loading
+18 −1
Original line number Original line Diff line number Diff line
@@ -344,6 +344,17 @@ static int parent_has_perm(struct dev_cgroup *childcg,
	return may_access(parent, ex);
	return may_access(parent, ex);
}
}


/**
 * may_allow_all - checks if it's possible to change the behavior to
 *		   allow based on parent's rules.
 * @parent: device cgroup's parent
 * returns: != 0 in case it's allowed, 0 otherwise
 */
static inline int may_allow_all(struct dev_cgroup *parent)
{
	return parent->behavior == DEVCG_DEFAULT_ALLOW;
}

/*
/*
 * Modify the exception list using allow/deny rules.
 * Modify the exception list using allow/deny rules.
 * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
 * CAP_SYS_ADMIN is needed for this.  It's at least separate from CAP_MKNOD
@@ -364,6 +375,8 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
	char temp[12];		/* 11 + 1 characters needed for a u32 */
	char temp[12];		/* 11 + 1 characters needed for a u32 */
	int count, rc;
	int count, rc;
	struct dev_exception_item ex;
	struct dev_exception_item ex;
	struct cgroup *p = devcgroup->css.cgroup;
	struct dev_cgroup *parent = cgroup_to_devcgroup(p->parent);


	if (!capable(CAP_SYS_ADMIN))
	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;
		return -EPERM;
@@ -375,9 +388,13 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
	case 'a':
	case 'a':
		switch (filetype) {
		switch (filetype) {
		case DEVCG_ALLOW:
		case DEVCG_ALLOW:
			if (!parent_has_perm(devcgroup, &ex))
			if (!may_allow_all(parent))
				return -EPERM;
				return -EPERM;
			dev_exception_clean(devcgroup);
			dev_exception_clean(devcgroup);
			rc = dev_exceptions_copy(&devcgroup->exceptions,
						 &parent->exceptions);
			if (rc)
				return rc;
			devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
			devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
			break;
			break;
		case DEVCG_DENY:
		case DEVCG_DENY: