KVM: MMU: invalidate and flush on spte small->large page size change
[safe/jmp/linux-2.6] / kernel / ns_cgroup.c
index 78bc3fd..2a5dfec 100644 (file)
@@ -34,7 +34,7 @@ int ns_cgroup_clone(struct task_struct *task, struct pid *pid)
 
 /*
  * Rules:
- *   1. you can only enter a cgroup which is a child of your current
+ *   1. you can only enter a cgroup which is a descendant of your current
  *     cgroup
  *   2. you can only place another process into a cgroup if
  *     a. you have CAP_SYS_ADMIN
@@ -42,25 +42,31 @@ int ns_cgroup_clone(struct task_struct *task, struct pid *pid)
  *       (hence either you are in the same cgroup as task, or in an
  *        ancestor cgroup thereof)
  */
-static int ns_can_attach(struct cgroup_subsys *ss,
-               struct cgroup *new_cgroup, struct task_struct *task)
+static int ns_can_attach(struct cgroup_subsys *ss, struct cgroup *new_cgroup,
+                        struct task_struct *task, bool threadgroup)
 {
-       struct cgroup *orig;
-
        if (current != task) {
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
 
-               if (!cgroup_is_descendant(new_cgroup))
+               if (!cgroup_is_descendant(new_cgroup, current))
                        return -EPERM;
        }
 
-       if (atomic_read(&new_cgroup->count) != 0)
+       if (!cgroup_is_descendant(new_cgroup, task))
                return -EPERM;
 
-       orig = task_cgroup(task, ns_subsys_id);
-       if (orig && orig != new_cgroup->parent)
-               return -EPERM;
+       if (threadgroup) {
+               struct task_struct *c;
+               rcu_read_lock();
+               list_for_each_entry_rcu(c, &task->thread_group, thread_group) {
+                       if (!cgroup_is_descendant(new_cgroup, c)) {
+                               rcu_read_unlock();
+                               return -EPERM;
+                       }
+               }
+               rcu_read_unlock();
+       }
 
        return 0;
 }
@@ -77,7 +83,7 @@ static struct cgroup_subsys_state *ns_create(struct cgroup_subsys *ss,
 
        if (!capable(CAP_SYS_ADMIN))
                return ERR_PTR(-EPERM);
-       if (!cgroup_is_descendant(cgroup))
+       if (!cgroup_is_descendant(cgroup, current))
                return ERR_PTR(-EPERM);
 
        ns_cgroup = kzalloc(sizeof(*ns_cgroup), GFP_KERNEL);