Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

devcg: prepare may_access() for hierarchy support

Currently may_access() is only able to verify if an exception is valid for the
current cgroup, which has the same behavior. With hierarchy, it'll be also used
to verify if a cgroup local exception is valid towards its cgroup parent, which
might have different behavior.

v2:
- updated patch description
- rebased on top of a new patch to expand the may_access() logic to make it
more clear
- fixed argument description order in may_access()

Acked-by: Tejun Heo <tj@kernel.org>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Aristeu Rozanski <aris@redhat.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Aristeu Rozanski and committed by
Tejun Heo
c39a2a30 26898fdf

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