diff options
Diffstat (limited to 'security/device_cgroup.c')
| -rw-r--r-- | security/device_cgroup.c | 18 | 
1 files changed, 13 insertions, 5 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 842c254396d..b08d20c66c2 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -164,8 +164,8 @@ static void dev_exception_clean(struct dev_cgroup *dev_cgroup)  	struct dev_exception_item *ex, *tmp;  	list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) { -		list_del(&ex->list); -		kfree(ex); +		list_del_rcu(&ex->list); +		kfree_rcu(ex, rcu);  	}  } @@ -298,7 +298,7 @@ static int may_access(struct dev_cgroup *dev_cgroup,  	struct dev_exception_item *ex;  	bool match = false; -	list_for_each_entry(ex, &dev_cgroup->exceptions, list) { +	list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) {  		if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))  			continue;  		if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR)) @@ -352,6 +352,8 @@ static int parent_has_perm(struct dev_cgroup *childcg,   */  static inline int may_allow_all(struct dev_cgroup *parent)  { +	if (!parent) +		return 1;  	return parent->behavior == DEVCG_DEFAULT_ALLOW;  } @@ -376,11 +378,14 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,  	int count, rc;  	struct dev_exception_item ex;  	struct cgroup *p = devcgroup->css.cgroup; -	struct dev_cgroup *parent = cgroup_to_devcgroup(p->parent); +	struct dev_cgroup *parent = NULL;  	if (!capable(CAP_SYS_ADMIN))  		return -EPERM; +	if (p->parent) +		parent = cgroup_to_devcgroup(p->parent); +  	memset(&ex, 0, sizeof(ex));  	b = buffer; @@ -391,11 +396,14 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,  			if (!may_allow_all(parent))  				return -EPERM;  			dev_exception_clean(devcgroup); +			devcgroup->behavior = DEVCG_DEFAULT_ALLOW; +			if (!parent) +				break; +  			rc = dev_exceptions_copy(&devcgroup->exceptions,  						 &parent->exceptions);  			if (rc)  				return rc; -			devcgroup->behavior = DEVCG_DEFAULT_ALLOW;  			break;  		case DEVCG_DENY:  			dev_exception_clean(devcgroup);  |