[CRIU] [PATCH] userns: check that all namespaces were created from a target userns

Andrey Vagin avagin at openvz.org
Tue Oct 28 06:41:06 PDT 2014


We enter into the target userns and try to enter in other namespaces.
The "enter" operation requires CAP_SYS_ADMIN in a user namespace,
where a taget namespace was created.

Now if one or more namespaces were created in another userns,
criu stops dumping and return an error. I want to find someone, who uses
this configuration. In this case restore will be more complicated.
Current version covers containers needs.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 namespaces.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git a/namespaces.c b/namespaces.c
index 7ec4019..74cf4aa 100644
--- a/namespaces.c
+++ b/namespaces.c
@@ -573,12 +573,63 @@ err:
 	return -1;
 }
 
+static int check_user_ns(int pid)
+{
+	int status;
+	pid_t chld;
+
+	chld = fork();
+	if (chld == -1) {
+		pr_perror("Unable to fork a process\n");
+		return -1;
+	}
+
+	if (chld == 0) {
+		/*
+		 * Check that we are able to enter into other namespaces
+		 * from a target namespace. This signs that these namespaces
+		 * were created from a target user namespace.
+		 */
+
+		if (switch_ns(pid, &user_ns_desc, NULL))
+			exit(-1);
+		if ((root_ns_mask & CLONE_NEWNET) &&
+		    switch_ns(pid, &net_ns_desc, NULL))
+			exit(-1);
+		if ((root_ns_mask & CLONE_NEWUTS) &&
+		    switch_ns(pid, &uts_ns_desc, NULL))
+			exit(-1);
+		if ((root_ns_mask & CLONE_NEWIPC) &&
+		    switch_ns(pid, &ipc_ns_desc, NULL))
+			exit(-1);
+		if ((root_ns_mask & CLONE_NEWNS) &&
+		    switch_ns(pid, &mnt_ns_desc, NULL))
+			exit(-1);
+		exit(0);
+	}
+
+	if (waitpid(chld, &status, 0) != chld) {
+		pr_perror("Unable to wait the %d process", pid);
+		return -1;
+	}
+
+	if (status) {
+		pr_err("One or more namespaces doesn't belong to the target user namespace\n");
+		return -1;
+	}
+
+	return 0;
+}
+
 int dump_user_ns(pid_t pid, int ns_id)
 {
 	int ret, exit_code = -1;
 	UsernsEntry *e = &userns_entry;
 	struct cr_img *img;
 
+	if (check_user_ns(pid))
+		return -1;
+
 	ret = parse_id_map(pid, "uid_map", &e->uid_map);
 	if (ret < 0)
 		goto err;
-- 
1.9.3



More information about the CRIU mailing list