diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/device_cgroup.c | 49 |
1 files changed, 31 insertions, 18 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 4ad55a9c6920..ddf3c709c0c2 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -25,6 +25,12 @@ | |||
25 | 25 | ||
26 | static DEFINE_MUTEX(devcgroup_mutex); | 26 | static DEFINE_MUTEX(devcgroup_mutex); |
27 | 27 | ||
28 | enum devcg_behavior { | ||
29 | DEVCG_DEFAULT_NONE, | ||
30 | DEVCG_DEFAULT_ALLOW, | ||
31 | DEVCG_DEFAULT_DENY, | ||
32 | }; | ||
33 | |||
28 | /* | 34 | /* |
29 | * exception list locking rules: | 35 | * exception list locking rules: |
30 | * hold devcgroup_mutex for update/read. | 36 | * hold devcgroup_mutex for update/read. |
@@ -42,10 +48,7 @@ struct dev_exception_item { | |||
42 | struct dev_cgroup { | 48 | struct dev_cgroup { |
43 | struct cgroup_subsys_state css; | 49 | struct cgroup_subsys_state css; |
44 | struct list_head exceptions; | 50 | struct list_head exceptions; |
45 | enum { | 51 | enum devcg_behavior behavior; |
46 | DEVCG_DEFAULT_ALLOW, | ||
47 | DEVCG_DEFAULT_DENY, | ||
48 | } behavior; | ||
49 | }; | 52 | }; |
50 | 53 | ||
51 | static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) | 54 | static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) |
@@ -304,9 +307,11 @@ static int devcgroup_seq_read(struct cgroup *cgroup, struct cftype *cft, | |||
304 | * verify if a certain access is allowed. | 307 | * verify if a certain access is allowed. |
305 | * @dev_cgroup: dev cgroup to be tested against | 308 | * @dev_cgroup: dev cgroup to be tested against |
306 | * @refex: new exception | 309 | * @refex: new exception |
310 | * @behavior: behavior of the exception | ||
307 | */ | 311 | */ |
308 | static bool may_access(struct dev_cgroup *dev_cgroup, | 312 | static bool may_access(struct dev_cgroup *dev_cgroup, |
309 | struct dev_exception_item *refex) | 313 | struct dev_exception_item *refex, |
314 | enum devcg_behavior behavior) | ||
310 | { | 315 | { |
311 | struct dev_exception_item *ex; | 316 | struct dev_exception_item *ex; |
312 | bool match = false; | 317 | bool match = false; |
@@ -330,19 +335,27 @@ static bool may_access(struct dev_cgroup *dev_cgroup, | |||
330 | break; | 335 | break; |
331 | } | 336 | } |
332 | 337 | ||
333 | /* | 338 | if (dev_cgroup->behavior == DEVCG_DEFAULT_ALLOW) { |
334 | * In two cases we'll consider this new exception valid: | 339 | if (behavior == DEVCG_DEFAULT_ALLOW) { |
335 | * - the dev cgroup has its default policy to deny + exception list: | 340 | /* the exception will deny access to certain devices */ |
336 | * the new exception *should* match the exceptions | 341 | return true; |
337 | * - the dev cgroup has its default policy to allow + exception list: | 342 | } else { |
338 | * the new exception should *not* match any of the exceptions | 343 | /* the exception will allow access to certain devices */ |
339 | */ | 344 | if (match) |
340 | if (dev_cgroup->behavior == DEVCG_DEFAULT_DENY) { | 345 | /* |
341 | if (match) | 346 | * a new exception allowing access shouldn't |
347 | * match an parent's exception | ||
348 | */ | ||
349 | return false; | ||
342 | return true; | 350 | return true; |
351 | } | ||
343 | } else { | 352 | } else { |
344 | if (!match) | 353 | /* only behavior == DEVCG_DEFAULT_DENY allowed here */ |
354 | if (match) | ||
355 | /* parent has an exception that matches the proposed */ | ||
345 | return true; | 356 | return true; |
357 | else | ||
358 | return false; | ||
346 | } | 359 | } |
347 | return false; | 360 | return false; |
348 | } | 361 | } |
@@ -361,7 +374,7 @@ static int parent_has_perm(struct dev_cgroup *childcg, | |||
361 | if (!pcg) | 374 | if (!pcg) |
362 | return 1; | 375 | return 1; |
363 | parent = cgroup_to_devcgroup(pcg); | 376 | parent = cgroup_to_devcgroup(pcg); |
364 | return may_access(parent, ex); | 377 | return may_access(parent, ex, childcg->behavior); |
365 | } | 378 | } |
366 | 379 | ||
367 | /** | 380 | /** |
@@ -395,7 +408,7 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup, | |||
395 | { | 408 | { |
396 | const char *b; | 409 | const char *b; |
397 | char temp[12]; /* 11 + 1 characters needed for a u32 */ | 410 | char temp[12]; /* 11 + 1 characters needed for a u32 */ |
398 | int count, rc; | 411 | int count, rc = 0; |
399 | struct dev_exception_item ex; | 412 | struct dev_exception_item ex; |
400 | struct cgroup *p = devcgroup->css.cgroup; | 413 | struct cgroup *p = devcgroup->css.cgroup; |
401 | struct dev_cgroup *parent = NULL; | 414 | struct dev_cgroup *parent = NULL; |
@@ -612,7 +625,7 @@ static int __devcgroup_check_permission(short type, u32 major, u32 minor, | |||
612 | 625 | ||
613 | rcu_read_lock(); | 626 | rcu_read_lock(); |
614 | dev_cgroup = task_devcgroup(current); | 627 | dev_cgroup = task_devcgroup(current); |
615 | rc = may_access(dev_cgroup, &ex); | 628 | rc = may_access(dev_cgroup, &ex, dev_cgroup->behavior); |
616 | rcu_read_unlock(); | 629 | rcu_read_unlock(); |
617 | 630 | ||
618 | if (!rc) | 631 | if (!rc) |