[cgmanager-devel] [PATCH RFC] add a configurable maximum cgroup depth
Serge Hallyn
serge.hallyn at ubuntu.com
Wed Feb 26 16:30:43 UTC 2014
Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>
---
cgmanager.c | 42 +++++++++++++++++++++++++++++-------------
fs.c | 21 ++++++++++++++++++++-
fs.h | 4 +++-
3 files changed, 52 insertions(+), 15 deletions(-)
diff --git a/cgmanager.c b/cgmanager.c
index b77220a..7c38c25 100644
--- a/cgmanager.c
+++ b/cgmanager.c
@@ -19,6 +19,14 @@
#include <frontend.h>
+/*
+ * Maximum depth of directories we allow in Create
+ * Default is 16. Figure 4 directories per level of container
+ * nesting (/user/1000.user/c2.session/c1), that lets us nest
+ * 4 containers deep.
+ * */
+static int maxdepth = 16;
+
/* GetPidCgroup */
int get_pid_cgroup_main(void *parent, const char *controller,struct ucred p,
struct ucred r, struct ucred v, char **output)
@@ -26,13 +34,13 @@ int get_pid_cgroup_main(void *parent, const char *controller,struct ucred p,
char rcgpath[MAXPATHLEN], vcgpath[MAXPATHLEN];
// Get r's current cgroup in rcgpath
- if (!compute_pid_cgroup(r.pid, controller, "", rcgpath)) {
+ if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, NULL)) {
nih_error("Could not determine the requestor cgroup");
return -1;
}
// Get v's cgroup in vcgpath
- if (!compute_pid_cgroup(v.pid, controller, "", vcgpath)) {
+ if (!compute_pid_cgroup(v.pid, controller, "", vcgpath, NULL)) {
nih_error("Could not determine the victim cgroup");
return -1;
}
@@ -57,7 +65,7 @@ static bool victim_under_proxy_cgroup(char *rcgpath, pid_t v,
{
char vcgpath[MAXPATHLEN];
- if (!compute_pid_cgroup(v, controller, "", vcgpath)) {
+ if (!compute_pid_cgroup(v, controller, "", vcgpath, NULL)) {
nih_error("Could not determine the victim's cgroup");
return false;
}
@@ -87,7 +95,7 @@ int do_move_pid_main(const char *controller, const char *cgroup, struct ucred p,
// Get r's current cgroup in rcgpath
if (escape)
query = p.pid;
- if (!compute_pid_cgroup(query, controller, "", rcgpath)) {
+ if (!compute_pid_cgroup(query, controller, "", rcgpath, NULL)) {
nih_error("Could not determine the requested cgroup");
return -1;
}
@@ -163,7 +171,7 @@ int move_pid_abs_main(const char *controller, const char *cgroup, struct ucred p
int create_main(const char *controller, const char *cgroup, struct ucred p,
struct ucred r, int32_t *existed)
{
- int ret;
+ int ret, depth;
char rcgpath[MAXPATHLEN], path[MAXPATHLEN], dirpath[MAXPATHLEN];
nih_local char *copy = NULL;
size_t cgroup_len;
@@ -179,11 +187,17 @@ int create_main(const char *controller, const char *cgroup, struct ucred p,
}
// Get r's current cgroup in rcgpath
- if (!compute_pid_cgroup(r.pid, controller, "", rcgpath)) {
+ if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, &depth)) {
nih_error("Could not determine the requested cgroup");
return -1;
}
+ depth += get_path_depth(cgroup);
+ if (depth > maxdepth) {
+ nih_error("Cgroup too deep: %s/%s", rcgpath, cgroup);
+ return -1;
+ }
+
cgroup_len = strlen(cgroup);
if (strlen(rcgpath) + cgroup_len > MAXPATHLEN) {
@@ -200,7 +214,7 @@ int create_main(const char *controller, const char *cgroup, struct ucred p,
oldp2 = *p2;
*p2 = '\0';
if (strcmp(p1, "..") == 0) {
- nih_error("Out of memory copying cgroup name");
+ nih_error("Invalid cgroup path at create: %s", p1);
return -1;
}
strncat(path, "/", MAXPATHLEN-1);
@@ -272,7 +286,7 @@ int chown_main(const char *controller, const char *cgroup, struct ucred p,
}
// Get r's current cgroup in rcgpath
- if (!compute_pid_cgroup(r.pid, controller, "", rcgpath)) {
+ if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, NULL)) {
nih_error("Could not determine the requested cgroup");
return -1;
}
@@ -327,7 +341,7 @@ int chmod_main(const char *controller, const char *cgroup, const char *file,
}
// Get r's current cgroup in rcgpath
- if (!compute_pid_cgroup(r.pid, controller, "", rcgpath)) {
+ if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, NULL)) {
nih_error("Could not determine the requested cgroup");
return -1;
}
@@ -372,7 +386,7 @@ int get_value_main(void *parent, const char *controller, const char *cgroup,
return -1;
}
- if (!compute_pid_cgroup(r.pid, controller, cgroup, path)) {
+ if (!compute_pid_cgroup(r.pid, controller, cgroup, path, NULL)) {
nih_error("Could not determine the requested cgroup");
return -1;
}
@@ -421,7 +435,7 @@ int set_value_main(const char *controller, const char *cgroup,
return -1;
}
- if (!compute_pid_cgroup(r.pid, controller, cgroup, path)) {
+ if (!compute_pid_cgroup(r.pid, controller, cgroup, path, NULL)) {
nih_error("Could not determine the requested cgroup");
return -1;
}
@@ -545,7 +559,7 @@ int remove_main(const char *controller, const char *cgroup, struct ucred p,
}
// Get r's current cgroup in rcgpath
- if (!compute_pid_cgroup(r.pid, controller, "", rcgpath)) {
+ if (!compute_pid_cgroup(r.pid, controller, "", rcgpath, NULL)) {
nih_error("Could not determine the requested cgroup");
return -1;
}
@@ -604,7 +618,7 @@ int get_tasks_main(void *parent, const char *controller, const char *cgroup,
return -1;
}
- if (!compute_pid_cgroup(r.pid, controller, cgroup, path)) {
+ if (!compute_pid_cgroup(r.pid, controller, cgroup, path, NULL)) {
nih_error("Could not determine the requested cgroup");
return -1;
}
@@ -643,6 +657,8 @@ my_setter (NihOption *option, const char *arg)
* Command-line options accepted by this program.
**/
static NihOption options[] = {
+ { 0, "max-depth", N_("Maximum cgroup depth"),
+ NULL, NULL, &maxdepth, NULL },
{ 'm', "mount", N_("Extra subsystems to mount"),
NULL, "subsystems to mount", NULL, my_setter },
{ 0, "daemon", N_("Detach and run in the background"),
diff --git a/fs.c b/fs.c
index b6dd4fd..32a06a5 100644
--- a/fs.c
+++ b/fs.c
@@ -455,6 +455,21 @@ const char *get_controller_path(const char *controller)
return NULL;
}
+int get_path_depth(const char *p)
+{
+ int depth = 0;
+
+ while (*p) {
+ while (*p && *p == '/')
+ p++;
+ if (*p)
+ depth++;
+ while (*p && *p != '/')
+ p++;
+ }
+ return depth;
+}
+
/*
* Calculate a full path to the cgroup being requested.
* @pid is the process making the request
@@ -464,7 +479,8 @@ const char *get_controller_path(const char *controller)
* "a/b", then we concatenate "/cgroup/for/pid" with "a/b"
* If @cgroup is "/a/b", then we use "/a/b"
*/
-bool compute_pid_cgroup(pid_t pid, const char *controller, const char *cgroup, char *path)
+bool compute_pid_cgroup(pid_t pid, const char *controller, const char *cgroup,
+ char *path, int *depth)
{
int ret;
char requestor_cgpath[MAXPATHLEN], fullpath[MAXPATHLEN], *cg;
@@ -479,6 +495,9 @@ bool compute_pid_cgroup(pid_t pid, const char *controller, const char *cgroup, c
} else
abspath = true;
+ if (depth)
+ *depth = get_path_depth(cg);
+
if ((cont_path = get_controller_path(controller)) == NULL) {
nih_error("Controller %s not mounted", controller);
return false;
diff --git a/fs.h b/fs.h
index b5d3868..6067e23 100644
--- a/fs.h
+++ b/fs.h
@@ -25,7 +25,9 @@
*/
int setup_cgroup_mounts(char *extra_mounts);
-bool compute_pid_cgroup(pid_t pid, const char *controller, const char *cgroup, char *path);
+bool compute_pid_cgroup(pid_t pid, const char *controller, const char *cgroup,
+ char *path, int *depth);
+int get_path_depth(const char *path);
bool may_access(pid_t pid, uid_t uid, gid_t gid, const char *path, int mode);
void get_pid_creds(pid_t pid, uid_t *uid, gid_t *gid);
char *file_read_string(void *parent, const char *path);
--
1.9.0
More information about the cgmanager-devel
mailing list