Description: always allow comounted controllers to be passed in together
Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/lxcfs/+bug/1438345

Index: cgmanager-0.36/cgmanager.c
===================================================================
--- cgmanager-0.36.orig/cgmanager.c
+++ cgmanager-0.36/cgmanager.c
@@ -32,11 +32,17 @@
 static int maxdepth = 16;
 
 /* GetPidCgroup */
-int get_pid_cgroup_main(void *parent, const char *controller,struct ucred p,
+int get_pid_cgroup_main(void *parent, const char *controller, struct ucred p,
 			 struct ucred r, struct ucred v, char **output)
 {
 	char rcgpath[MAXPATHLEN], vcgpath[MAXPATHLEN];
 
+	if (!(prune_verify_comounts(controller))) {
+		nih_error("%s: Multiple controllers given: %s",
+				__func__, controller);
+		return -1;
+	}
+
 	// Get r's current cgroup in rcgpath
 	if (!compute_proxy_cgroup(r.pid, controller, "", rcgpath, NULL)) {
 		nih_error("%s: Could not determine the requestor's cgroup for %s",
@@ -72,6 +78,12 @@ int get_pid_cgroup_abs_main(void *parent
 {
 	char rcgpath[MAXPATHLEN], vcgpath[MAXPATHLEN];
 
+	if (!(prune_verify_comounts(controller))) {
+		nih_error("%s: Multiple controllers given: %s",
+				__func__, controller);
+		return -1;
+	}
+
 	// Get p's current cgroup in rcgpath
 	if (!compute_proxy_cgroup(p.pid, controller, "", rcgpath, NULL)) {
 		nih_error("%s: Could not determine the requestor's cgroup for %s",
@@ -559,6 +571,12 @@ int get_value_main(void *parent, const c
 {
 	char path[MAXPATHLEN];
 
+	if (!(prune_verify_comounts(controller))) {
+		nih_error("%s: Multiple controllers given: %s",
+				__func__, controller);
+		return -1;
+	}
+
 	if (!sane_cgroup(cgroup)) {
 		nih_error("%s: unsafe cgroup", __func__);
 		return -1;
@@ -615,6 +633,12 @@ int set_value_main(const char *controlle
 {
 	char path[MAXPATHLEN];
 
+	if (!(prune_verify_comounts(controller))) {
+		nih_error("%s: Multiple controllers given: %s",
+				__func__, controller);
+		return -1;
+	}
+
 	if (!sane_cgroup(cgroup)) {
 		nih_error("%s: unsafe cgroup", __func__);
 		return -1;
@@ -843,6 +867,12 @@ int get_tasks_main(void *parent, const c
 		return -1;
 	}
 
+	if (!(prune_verify_comounts(controller))) {
+		nih_error("%s: Multiple controllers given: %s",
+				__func__, controller);
+		return -1;
+	}
+
 	if (!compute_proxy_cgroup(r.pid, controller, cgroup, path, NULL)) {
 		nih_error("%s: Could not determine the requested cgroup (%s:%s)",
                 __func__, controller, cgroup);
@@ -1016,6 +1046,12 @@ int list_children_main(void *parent, con
 		return -1;
 	}
 
+	if (!(prune_verify_comounts(controller))) {
+		nih_error("%s: Multiple controllers given: %s",
+				__func__, controller);
+		return -1;
+	}
+
 	if (!compute_proxy_cgroup(r.pid, controller, cgroup, path, NULL)) {
 		nih_error("%s: Could not determine the requested cgroup (%s:%s)",
                 __func__, controller, cgroup);
@@ -1272,6 +1308,12 @@ int list_keys_main(void *parent, const c
 		return -1;
 	}
 
+	if (!(prune_verify_comounts(controller))) {
+		nih_error("%s: Multiple controllers given: %s",
+				__func__, controller);
+		return -1;
+	}
+
 	if (!compute_proxy_cgroup(r.pid, controller, cgroup, path, NULL)) {
 		nih_error("%s: Could not determine the requested cgroup (%s:%s)",
                 __func__, controller, cgroup);
Index: cgmanager-0.36/fs.c
===================================================================
--- cgmanager-0.36.orig/fs.c
+++ cgmanager-0.36/fs.c
@@ -750,6 +750,26 @@ void do_prune_comounts(char *controllers
 }
 
 /*
+ * If we are passed 'cpu', do nothing and return true.
+ * If we are passed 'cpu,cpuacct,devices', and all three are comounted,
+ *   set controllers to 'cpu' and return true.
+ * If we are passed 'cpu,cpuacct,devices', and all three are not comounted,
+ *   return false.
+ */
+bool prune_verify_comounts(char *controllers)
+{
+	char *comma;
+	do_prune_comounts(controllers);
+	comma = strchr(controllers, ',');
+	if (!comma)
+		return true;
+	if (*(comma+1) != '\0')
+		return false;
+	*comma = '\0';
+	return true;
+}
+
+/*
  * @list is a comma-separated list of words.
  * Return true if @word is in @list.
  */
Index: cgmanager-0.36/fs.h
===================================================================
--- cgmanager-0.36.orig/fs.h
+++ cgmanager-0.36/fs.h
@@ -55,6 +55,7 @@ bool setup_base_run_path(void);
 bool create_agent_symlinks(void);
 bool was_premounted(const char *controller);
 void do_prune_comounts(char *controllers);
+bool prune_verify_comounts(char *controllers);
 void do_list_controllers(void *parent, char ***output);
 void convert_directory_contents(struct keys_return_type **keys, struct ucred r);
 bool path_is_under_taskcg(pid_t pid, const char *contr,const char *path);
