aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-02 22:54:47 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-02 22:54:47 -0400
commitb028161fbba178ccd35aa69051c04d7673fe9d80 (patch)
treea164c39cdf5e1b954584dcdc51401e1521beae27 /security
parentf317ff9eed763e99bd226a447f93d42509434f43 (diff)
parentc7ba8287cd11f2fc9e2feee9e1fac34b7293658f (diff)
Merge branch 'for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup changes from Tejun Heo: "This pull request contains the following changes. - cgroup_subsys_state (css) reference counting has been converted to percpu-ref. css is what each resource controller embeds into its own control structure and perform reference count against. It may be used in hot paths of various subsystems and is similar to module refcnt in that aspect. For example, block-cgroup's css refcnting was showing up a lot in Mikulaus's device-mapper scalability work and this should alleviate it. - cgroup subtree iterator has been updated so that RCU read lock can be released after grabbing reference. This allows simplifying its users which requires blocking which used to build iteration list under RCU read lock and then traverse it outside. This pull request contains simplification of cgroup core and device-cgroup. A separate pull request will update cpuset. - Fixes for various bugs including corner race conditions and RCU usage bugs. - A lot of cleanups and some prepartory work for the planned unified hierarchy support." * 'for-3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: (48 commits) cgroup: CGRP_ROOT_SUBSYS_BOUND should also be ignored when mounting an existing hierarchy cgroup: CGRP_ROOT_SUBSYS_BOUND should be ignored when comparing mount options cgroup: fix deadlock on cgroup_mutex via drop_parsed_module_refcounts() cgroup: always use RCU accessors for protected accesses cgroup: fix RCU accesses around task->cgroups cgroup: fix RCU accesses to task->cgroups cgroup: grab cgroup_mutex in drop_parsed_module_refcounts() cgroup: fix cgroupfs_root early destruction path cgroup: reserve ID 0 for dummy_root and 1 for unified hierarchy cgroup: implement for_each_[builtin_]subsys() cgroup: move init_css_set initialization inside cgroup_mutex cgroup: s/for_each_subsys()/for_each_root_subsys()/ cgroup: clean up find_css_set() and friends cgroup: remove cgroup->actual_subsys_mask cgroup: prefix global variables with "cgroup_" cgroup: convert CFTYPE_* flags to enums cgroup: rename cont to cgrp cgroup: clean up cgroup_serial_nr_cursor cgroup: convert cgroup_cft_commit() to use cgroup_for_each_descendant_pre() cgroup: make serial_nr_cursor available throughout cgroup.c ...
Diffstat (limited to 'security')
-rw-r--r--security/device_cgroup.c56
1 files changed, 18 insertions, 38 deletions
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index dd0dc574d78d..e8aad69f0d69 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -49,8 +49,6 @@ struct dev_cgroup {
49 struct cgroup_subsys_state css; 49 struct cgroup_subsys_state css;
50 struct list_head exceptions; 50 struct list_head exceptions;
51 enum devcg_behavior behavior; 51 enum devcg_behavior behavior;
52 /* temporary list for pending propagation operations */
53 struct list_head propagate_pending;
54}; 52};
55 53
56static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s) 54static inline struct dev_cgroup *css_to_devcgroup(struct cgroup_subsys_state *s)
@@ -241,7 +239,6 @@ static struct cgroup_subsys_state *devcgroup_css_alloc(struct cgroup *cgroup)
241 if (!dev_cgroup) 239 if (!dev_cgroup)
242 return ERR_PTR(-ENOMEM); 240 return ERR_PTR(-ENOMEM);
243 INIT_LIST_HEAD(&dev_cgroup->exceptions); 241 INIT_LIST_HEAD(&dev_cgroup->exceptions);
244 INIT_LIST_HEAD(&dev_cgroup->propagate_pending);
245 dev_cgroup->behavior = DEVCG_DEFAULT_NONE; 242 dev_cgroup->behavior = DEVCG_DEFAULT_NONE;
246 243
247 return &dev_cgroup->css; 244 return &dev_cgroup->css;
@@ -445,34 +442,6 @@ static void revalidate_active_exceptions(struct dev_cgroup *devcg)
445} 442}
446 443
447/** 444/**
448 * get_online_devcg - walks the cgroup tree and fills a list with the online
449 * groups
450 * @root: cgroup used as starting point
451 * @online: list that will be filled with online groups
452 *
453 * Must be called with devcgroup_mutex held. Grabs RCU lock.
454 * Because devcgroup_mutex is held, no devcg will become online or offline
455 * during the tree walk (see devcgroup_online, devcgroup_offline)
456 * A separated list is needed because propagate_behavior() and
457 * propagate_exception() need to allocate memory and can block.
458 */
459static void get_online_devcg(struct cgroup *root, struct list_head *online)
460{
461 struct cgroup *pos;
462 struct dev_cgroup *devcg;
463
464 lockdep_assert_held(&devcgroup_mutex);
465
466 rcu_read_lock();
467 cgroup_for_each_descendant_pre(pos, root) {
468 devcg = cgroup_to_devcgroup(pos);
469 if (is_devcg_online(devcg))
470 list_add_tail(&devcg->propagate_pending, online);
471 }
472 rcu_read_unlock();
473}
474
475/**
476 * propagate_exception - propagates a new exception to the children 445 * propagate_exception - propagates a new exception to the children
477 * @devcg_root: device cgroup that added a new exception 446 * @devcg_root: device cgroup that added a new exception
478 * @ex: new exception to be propagated 447 * @ex: new exception to be propagated
@@ -482,15 +451,24 @@ static void get_online_devcg(struct cgroup *root, struct list_head *online)
482static int propagate_exception(struct dev_cgroup *devcg_root, 451static int propagate_exception(struct dev_cgroup *devcg_root,
483 struct dev_exception_item *ex) 452 struct dev_exception_item *ex)
484{ 453{
485 struct cgroup *root = devcg_root->css.cgroup; 454 struct cgroup *root = devcg_root->css.cgroup, *pos;
486 struct dev_cgroup *devcg, *parent, *tmp;
487 int rc = 0; 455 int rc = 0;
488 LIST_HEAD(pending);
489 456
490 get_online_devcg(root, &pending); 457 rcu_read_lock();
491 458
492 list_for_each_entry_safe(devcg, tmp, &pending, propagate_pending) { 459 cgroup_for_each_descendant_pre(pos, root) {
493 parent = cgroup_to_devcgroup(devcg->css.cgroup->parent); 460 struct dev_cgroup *devcg = cgroup_to_devcgroup(pos);
461
462 /*
463 * Because devcgroup_mutex is held, no devcg will become
464 * online or offline during the tree walk (see on/offline
465 * methods), and online ones are safe to access outside RCU
466 * read lock without bumping refcnt.
467 */
468 if (!is_devcg_online(devcg))
469 continue;
470
471 rcu_read_unlock();
494 472
495 /* 473 /*
496 * in case both root's behavior and devcg is allow, a new 474 * in case both root's behavior and devcg is allow, a new
@@ -512,8 +490,10 @@ static int propagate_exception(struct dev_cgroup *devcg_root,
512 } 490 }
513 revalidate_active_exceptions(devcg); 491 revalidate_active_exceptions(devcg);
514 492
515 list_del_init(&devcg->propagate_pending); 493 rcu_read_lock();
516 } 494 }
495
496 rcu_read_unlock();
517 return rc; 497 return rc;
518} 498}
519 499