diff -Nru cgmanager-0.24/debian/changelog cgmanager-0.24/debian/changelog --- cgmanager-0.24/debian/changelog 2015-01-05 20:49:04.000000000 +0000 +++ cgmanager-0.24/debian/changelog 2015-02-12 05:23:21.000000000 +0000 @@ -1,3 +1,10 @@ +cgmanager (0.24-0ubuntu7.3) trusty-proposed; urgency=medium + + * 0010-Fix-subdirectory-check.patch: prevent a task from administering + sibling cgroups (LP: #1421068) + + -- Serge Hallyn Wed, 11 Feb 2015 23:17:19 -0600 + cgmanager (0.24-0ubuntu7.2) trusty-proposed; urgency=medium * 0009-chown-stop-cgmanager-crash-on-chown-of-bad-file.patch - prevent diff -Nru cgmanager-0.24/debian/patches/0010-Fix-subdirectory-check.patch cgmanager-0.24/debian/patches/0010-Fix-subdirectory-check.patch --- cgmanager-0.24/debian/patches/0010-Fix-subdirectory-check.patch 1970-01-01 00:00:00.000000000 +0000 +++ cgmanager-0.24/debian/patches/0010-Fix-subdirectory-check.patch 2015-02-12 05:19:17.000000000 +0000 @@ -0,0 +1,197 @@ +From 9c41660679e740eecc4831b4a0043a09197d44dd Mon Sep 17 00:00:00 2001 +From: Serge Hallyn +Date: Wed, 11 Feb 2015 19:07:38 -0600 +Subject: [PATCH 1/1] Fix subdirectory check + +Commit 6a30adc22cc05b5 was not quite complete. If the task is in +/xxx then it may act on /xxx or /xxx/a, but not /xxx2. This commit +fixes the check to disallow /xxx2. It also commonizes the check, +cleaning up the code a bit. + +Signed-off-by: Serge Hallyn +--- + cgmanager.c | 65 ++++++++++--------------------------------------------------- + fs.c | 31 +++++++++++++++++++++++++++++ + fs.h | 1 + + 3 files changed, 42 insertions(+), 55 deletions(-) + +Index: cgmanager-0.24/cgmanager.c +=================================================================== +--- cgmanager-0.24.orig/cgmanager.c ++++ cgmanager-0.24/cgmanager.c +@@ -410,20 +410,13 @@ int chmod_main(const char *controller, c + int get_value_main(void *parent, const char *controller, const char *cgroup, + const char *key, struct ucred p, struct ucred r, char **value) + { +- char pcgpath[MAXPATHLEN], path[MAXPATHLEN]; ++ char path[MAXPATHLEN]; + + if (!sane_cgroup(cgroup)) { + nih_error("%s: unsafe cgroup", __func__); + return -1; + } + +- // Get p's current cgroup in pcgpath +- if (!compute_pid_cgroup(p.pid, controller, "", pcgpath, NULL)) { +- nih_error("%s: Could not determine the proxy's cgroup for %s", +- __func__, controller); +- return -1; +- } +- + if (!compute_pid_cgroup(r.pid, controller, cgroup, path, NULL)) { + nih_error("%s: Could not determine the requested cgroup", __func__); + return -1; +@@ -435,9 +428,7 @@ int get_value_main(void *parent, const c + return -1; + } + +- // Make sure target cgroup is under proxy's +- int plen = strlen(pcgpath); +- if (strncmp(pcgpath, path, plen) != 0) { ++ if (!path_is_under_taskcg(p.pid, controller, path)) { + nih_error("%s: target cgroup is not below r (%d)'s", __func__, + r.pid); + return -1; +@@ -474,28 +465,19 @@ int set_value_main(const char *controlle + struct ucred r) + + { +- char pcgpath[MAXPATHLEN], path[MAXPATHLEN]; ++ char path[MAXPATHLEN]; + + if (!sane_cgroup(cgroup)) { + nih_error("%s: unsafe cgroup", __func__); + return -1; + } + +- // Get p's current cgroup in pcgpath +- if (!compute_pid_cgroup(p.pid, controller, "", pcgpath, NULL)) { +- nih_error("%s: Could not determine the proxy's cgroup for %s", +- __func__, controller); +- return -1; +- } +- + if (!compute_pid_cgroup(r.pid, controller, cgroup, path, NULL)) { + nih_error("%s: Could not determine the requested cgroup", __func__); + return -1; + } + +- // Make sure target cgroup is under proxy's +- int plen = strlen(pcgpath); +- if (strncmp(pcgpath, path, plen) != 0) { ++ if (!path_is_under_taskcg(p.pid, controller, path)) { + nih_error("%s: target cgroup is not below r (%d)'s", __func__, + r.pid); + return -1; +@@ -671,7 +653,7 @@ int remove_main(const char *controller, + int get_tasks_main(void *parent, const char *controller, const char *cgroup, + struct ucred p, struct ucred r, int32_t **pids) + { +- char pcgpath[MAXPATHLEN], path[MAXPATHLEN]; ++ char path[MAXPATHLEN]; + const char *key = "tasks"; + + if (!sane_cgroup(cgroup)) { +@@ -679,21 +661,12 @@ int get_tasks_main(void *parent, const c + return -1; + } + +- // Get p's current cgroup in pcgpath +- if (!compute_pid_cgroup(p.pid, controller, "", pcgpath, NULL)) { +- nih_error("%s: Could not determine the proxy's cgroup for %s", +- __func__, controller); +- return -1; +- } +- + if (!compute_pid_cgroup(r.pid, controller, cgroup, path, NULL)) { + nih_error("%s: Could not determine the requested cgroup", __func__); + return -1; + } + +- // Make sure target cgroup is under proxy's +- int plen = strlen(pcgpath); +- if (strncmp(pcgpath, path, plen) != 0) { ++ if (!path_is_under_taskcg(p.pid, controller, path)) { + nih_error("%s: target cgroup is not below r (%d)'s", __func__, + r.pid); + return -1; +@@ -720,7 +693,7 @@ int get_tasks_main(void *parent, const c + int list_children_main(void *parent, const char *controller, const char *cgroup, + struct ucred p, struct ucred r, char ***output) + { +- char pcgpath[MAXPATHLEN], path[MAXPATHLEN]; ++ char path[MAXPATHLEN]; + + *output = NULL; + if (!sane_cgroup(cgroup)) { +@@ -728,21 +701,12 @@ int list_children_main(void *parent, con + return -1; + } + +- // Get p's current cgroup in pcgpath +- if (!compute_pid_cgroup(p.pid, controller, "", pcgpath, NULL)) { +- nih_error("%s: Could not determine the proxy's cgroup for %s", +- __func__, controller); +- return -1; +- } +- + if (!compute_pid_cgroup(r.pid, controller, cgroup, path, NULL)) { + nih_error("%s: Could not determine the requested cgroup", __func__); + return -1; + } + +- // Make sure target cgroup is under proxy's +- int plen = strlen(pcgpath); +- if (strncmp(pcgpath, path, plen) != 0) { ++ if (!path_is_under_taskcg(p.pid, controller, path)) { + nih_error("%s: target cgroup is not below r (%d)'s", __func__, + r.pid); + return -1; +Index: cgmanager-0.24/fs.c +=================================================================== +--- cgmanager-0.24.orig/fs.c ++++ cgmanager-0.24/fs.c +@@ -1097,3 +1097,34 @@ int get_child_directories(void *parent, + closedir(d); + return used; + } ++ ++/* ++ * Check that (absolute) @path is under @pid's cgroup for @contr ++ */ ++bool path_is_under_taskcg(pid_t pid, const char *contr,const char *path) ++{ ++ char pcgpath[MAXPATHLEN]; ++ size_t plen; ++ ++ // Get p's current cgroup in pcgpath ++ if (!compute_pid_cgroup(pid, contr, "", pcgpath, NULL)) { ++ nih_error("%s: Could not determine the proxy's cgroup for %s", ++ __func__, contr); ++ return false; ++ } ++ plen = strlen(pcgpath); ++ // path must start with pcgpath ++ if (strncmp(pcgpath, path, plen) != 0) ++ return false; ++ // If path is equal to pcgpath then that's ok ++ if (plen == strlen(path)) ++ return true; ++ /* ++ * if path is longer than pcpgath, then it must be a subdirectory ++ * of pcpgpath. I.e. if pcgpath is /xxx then /xxx/a is ok, /xxx2 is ++ * not. ++ */ ++ if (path[plen] == '/') ++ return true; ++ return false; ++} +Index: cgmanager-0.24/fs.h +=================================================================== +--- cgmanager-0.24.orig/fs.h ++++ cgmanager-0.24/fs.h +@@ -48,3 +48,4 @@ bool move_self_to_root(void); + int get_child_directories(void *parent, const char *path, char ***output); + bool setup_base_run_path(void); + bool create_agent_symlinks(void); ++bool path_is_under_taskcg(pid_t pid, const char *contr,const char *path); diff -Nru cgmanager-0.24/debian/patches/series cgmanager-0.24/debian/patches/series --- cgmanager-0.24/debian/patches/series 2015-01-05 20:48:01.000000000 +0000 +++ cgmanager-0.24/debian/patches/series 2015-02-12 05:14:47.000000000 +0000 @@ -8,3 +8,4 @@ 0007-fix-crash-on-free.patch 0001-make-sure-to-check-cgroup-hierarchy.patch 0009-chown-stop-cgmanager-crash-on-chown-of-bad-file.patch +0010-Fix-subdirectory-check.patch