[cgmanager-devel] [PATCH RFC] add a configurable maximum cgroup depth

Stéphane Graber stgraber at ubuntu.com
Wed Feb 26 16:33:58 UTC 2014


On Wed, Feb 26, 2014 at 10:30:43AM -0600, Serge Hallyn wrote:
> Signed-off-by: Serge Hallyn <serge.hallyn at ubuntu.com>

Looks good to me. Let me know when you have a FFe.

Acked-by: Stéphane Graber <stgraber 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
> 
> _______________________________________________
> cgmanager-devel mailing list
> cgmanager-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/cgmanager-devel

-- 
Stéphane Graber
Ubuntu developer
http://www.ubuntu.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.linuxcontainers.org/pipermail/cgmanager-devel/attachments/20140226/8170cfe6/attachment.pgp>


More information about the cgmanager-devel mailing list