[CRIU] [PATCH] cgroup: move tasks into cgroup via usernsd

Tycho Andersen tycho.andersen at canonical.com
Thu Oct 1 21:55:16 PDT 2015


Tasks in a user namespace cannot write themselves into cgroup tasks files,

(00.845068)      1: Error (cgroup.c:901): cg: Can't move into blkio/lxc/unpriv/tasks (-1/-1): Permission denied

So, let's write them into the tasks via usernsd.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 cgroup.c | 44 +++++++++++++++++++++++++++++++-------------
 1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/cgroup.c b/cgroup.c
index 2d79fc0..2135bb4 100644
--- a/cgroup.c
+++ b/cgroup.c
@@ -16,6 +16,7 @@
 #include "util.h"
 #include "imgset.h"
 #include "util-pie.h"
+#include "namespaces.h"
 #include "protobuf.h"
 #include "protobuf/core.pb-c.h"
 #include "protobuf/cgroup.pb-c.h"
@@ -857,15 +858,41 @@ static const char *special_cpuset_props[] = {
 	NULL,
 };
 
+static int userns_move(void *arg, int fd, pid_t pid)
+{
+	char pidbuf[32];
+	int cg, len, err;
+
+	len = snprintf(pidbuf, sizeof(pidbuf), "%d", pid);
+
+	if (len >= sizeof(pidbuf)) {
+		pr_err("pid printing failed: %d\n", pid);
+		return -1;
+	}
+
+	cg = get_service_fd(CGROUP_YARD);
+	err = fd = openat(cg, arg, O_WRONLY);
+	if (fd >= 0) {
+		err = write(fd, pidbuf, len);
+		close(fd);
+	}
+
+	if (err < 0) {
+		pr_perror("Can't move %s into %s (%d/%d)", pidbuf, (char *)arg, err, fd);
+		return -1;
+	}
+
+	return 0;
+}
+
 static int move_in_cgroup(CgSetEntry *se)
 {
-	int cg, i;
+	int i;
 
 	pr_info("Move into %d\n", se->id);
-	cg = get_service_fd(CGROUP_YARD);
 	for (i = 0; i < se->n_ctls; i++) {
 		char aux[PATH_MAX];
-		int fd, err, j, aux_off;
+		int fd = -1, err, j, aux_off;
 		CgMemberEntry *ce = se->ctls[i];
 		CgControllerEntry *ctrl = NULL;
 
@@ -886,16 +913,7 @@ static int move_in_cgroup(CgSetEntry *se)
 
 		snprintf(aux + aux_off, sizeof(aux) - aux_off, "/%s/tasks", ce->path);
 		pr_debug("  `-> %s\n", aux);
-		err = fd = openat(cg, aux, O_WRONLY);
-		if (fd >= 0) {
-			/*
-			 * Writing zero into this file moves current
-			 * task w/o any permissions checks :)
-			 */
-			err = write(fd, "0", 1);
-			close(fd);
-		}
-
+		err = userns_call(userns_move, UNS_ASYNC, aux, strlen(aux) + 1, -1);
 		if (err < 0) {
 			pr_perror("Can't move into %s (%d/%d)", aux, err, fd);
 			return -1;
-- 
2.1.4



More information about the CRIU mailing list