cgroup: refactor allow_attach function into common code
authorRom Lemarchand <romlem@android.com>
Fri, 7 Nov 2014 20:48:17 +0000 (12:48 -0800)
committerJohn Stultz <john.stultz@linaro.org>
Tue, 16 Feb 2016 21:53:42 +0000 (13:53 -0800)
move cpu_cgroup_allow_attach to a common subsys_cgroup_allow_attach.
This allows any process with CAP_SYS_NICE to move tasks across cgroups if
they use this function as their allow_attach handler.

Bug: 18260435
Change-Id: I6bb4933d07e889d0dc39e33b4e71320c34a2c90f
Signed-off-by: Rom Lemarchand <romlem@android.com>
include/linux/cgroup.h
kernel/cgroup.c

index cb91b44f5f7877d5899403b26ca1d9231c1ac9b6..c08c83182e086facfbd2d02db5f2eb87e45dd2fa 100644 (file)
@@ -528,6 +528,17 @@ static inline void pr_cont_cgroup_path(struct cgroup *cgrp)
        pr_cont_kernfs_path(cgrp->kn);
 }
 
+/*
+ * Default Android check for whether the current process is allowed to move a
+ * task across cgroups, either because CAP_SYS_NICE is set or because the uid
+ * of the calling process is the same as the moved task or because we are
+ * running as root.
+ * Returns 0 if this is allowed, or -EACCES otherwise.
+ */
+int subsys_cgroup_allow_attach(struct cgroup_subsys_state *css,
+                              struct cgroup_taskset *tset);
+
+
 #else /* !CONFIG_CGROUPS */
 
 struct cgroup_subsys_state;
@@ -552,6 +563,11 @@ static inline void cgroup_free(struct task_struct *p) {}
 static inline int cgroup_init_early(void) { return 0; }
 static inline int cgroup_init(void) { return 0; }
 
+static inline int subsys_cgroup_allow_attach(struct cgroup_subsys_state *css,
+                                            struct cgroup_taskset *tset)
+{
+       return 0;
+}
 #endif /* !CONFIG_CGROUPS */
 
 #endif /* _LINUX_CGROUP_H */
index 470f6536b9e8cfb029eedb5ecdb3c3e8c3c341be..35591b841db2176fae8be7e4a4a5ac455b0798cc 100644 (file)
@@ -2663,6 +2663,25 @@ static int cgroup_attach_task(struct cgroup *dst_cgrp,
        return ret;
 }
 
+int subsys_cgroup_allow_attach(struct cgroup_subsys_state *css, struct cgroup_taskset *tset)
+{
+       const struct cred *cred = current_cred(), *tcred;
+       struct task_struct *task;
+
+       if (capable(CAP_SYS_NICE))
+               return 0;
+
+       cgroup_taskset_for_each(task, css, tset) {
+               tcred = __task_cred(task);
+
+               if (current != task && !uid_eq(cred->euid, tcred->uid) &&
+                   !uid_eq(cred->euid, tcred->suid))
+                       return -EACCES;
+       }
+
+       return 0;
+}
+
 static int cgroup_procs_write_permission(struct task_struct *task,
                                         struct cgroup *dst_cgrp,
                                         struct kernfs_open_file *of)