diff options
author | Aristeu Rozanski <aris@redhat.com> | 2012-10-25 16:37:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-25 17:37:52 -0400 |
commit | 4cef7299b4786879a3e113e84084a72b24590c5b (patch) | |
tree | 31efb5e00be1c1e5cc266046c783c7569e495ede /security | |
parent | 26fd8405dd470cb8b54cb96859b7dd437e5e1391 (diff) |
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: Aristeu 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: Serge Hallyn <serge.hallyn@canonical.com>
Cc: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security')
-rw-r--r-- | security/device_cgroup.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 4fbae8d0b36c..842c254396db 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -344,6 +344,17 @@ static int parent_has_perm(struct dev_cgroup *childcg, | |||
344 | return may_access(parent, ex); | 344 | return may_access(parent, ex); |
345 | } | 345 | } |
346 | 346 | ||
347 | /** | ||
348 | * may_allow_all - checks if it's possible to change the behavior to | ||
349 | * allow based on parent's rules. | ||
350 | * @parent: device cgroup's parent | ||
351 | * returns: != 0 in case it's allowed, 0 otherwise | ||
352 | */ | ||
353 | static inline int may_allow_all(struct dev_cgroup *parent) | ||
354 | { | ||
355 | return parent->behavior == DEVCG_DEFAULT_ALLOW; | ||
356 | } | ||
357 | |||
347 | /* | 358 | /* |
348 | * Modify the exception list using allow/deny rules. | 359 | * Modify the exception list using allow/deny rules. |
349 | * CAP_SYS_ADMIN is needed for this. It's at least separate from CAP_MKNOD | 360 | * 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, | |||
364 | char temp[12]; /* 11 + 1 characters needed for a u32 */ | 375 | char temp[12]; /* 11 + 1 characters needed for a u32 */ |
365 | int count, rc; | 376 | int count, rc; |
366 | struct dev_exception_item ex; | 377 | struct dev_exception_item ex; |
378 | struct cgroup *p = devcgroup->css.cgroup; | ||
379 | struct dev_cgroup *parent = cgroup_to_devcgroup(p->parent); | ||
367 | 380 | ||
368 | if (!capable(CAP_SYS_ADMIN)) | 381 | if (!capable(CAP_SYS_ADMIN)) |
369 | return -EPERM; | 382 | return -EPERM; |
@@ -375,9 +388,13 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, | |||
375 | case 'a': | 388 | case 'a': |
376 | switch (filetype) { | 389 | switch (filetype) { |
377 | case DEVCG_ALLOW: | 390 | case DEVCG_ALLOW: |
378 | if (!parent_has_perm(devcgroup, &ex)) | 391 | if (!may_allow_all(parent)) |
379 | return -EPERM; | 392 | return -EPERM; |
380 | dev_exception_clean(devcgroup); | 393 | dev_exception_clean(devcgroup); |
394 | rc = dev_exceptions_copy(&devcgroup->exceptions, | ||
395 | &parent->exceptions); | ||
396 | if (rc) | ||
397 | return rc; | ||
381 | devcgroup->behavior = DEVCG_DEFAULT_ALLOW; | 398 | devcgroup->behavior = DEVCG_DEFAULT_ALLOW; |
382 | break; | 399 | break; |
383 | case DEVCG_DENY: | 400 | case DEVCG_DENY: |