[CRIU] [PATCH v3 27/33] ns: Implement set_user_ns()

Kirill Tkhai ktkhai at virtuozzo.com
Thu Feb 16 04:10:33 PST 2017


Add a field pstree_item::user_ns, which shows the task's current
user_ns, and introduce helpers to set it.

v3: Rebase on fdstore

Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
 criu/include/namespaces.h |    2 ++
 criu/include/pstree.h     |    1 +
 criu/namespaces.c         |   45 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+)

diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index 77ba31fb3..8c194181b 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -164,6 +164,8 @@ extern struct ns_id *lookup_ns_by_id(unsigned int id, struct ns_desc *nd);
 
 extern int collect_user_namespaces(bool for_dump);
 extern int prepare_userns(pid_t real_pid, UsernsEntry *e);
+extern int __set_user_ns(struct ns_id *ns);
+extern int set_user_ns(u32 id);
 extern int stop_usernsd(void);
 
 extern uid_t userns_uid(uid_t uid);
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index eeef6f87e..cb6ed90e6 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -29,6 +29,7 @@ struct pstree_item {
 		futex_t		task_st;
 		unsigned long	task_st_le_bits;
 	};
+	struct ns_id		*user_ns;
 };
 
 enum {
diff --git a/criu/namespaces.c b/criu/namespaces.c
index bf4c16d08..311570707 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -2285,5 +2285,50 @@ int prepare_namespace_before_tasks(void)
 	return -1;
 }
 
+int __set_user_ns(struct ns_id *ns)
+{
+	int fd;
+
+	if (!(root_ns_mask & CLONE_NEWUSER))
+		return 0;
+
+	if (current->user_ns && current->user_ns->id == ns->id)
+		return 0;
+
+	fd = fdstore_get(ns->user.nsfd_id);
+	if (fd < 0) {
+		pr_perror("Can't get ns fd");
+		return -1;
+	}
+	if (setns(fd, CLONE_NEWUSER) < 0) {
+		pr_perror("Can't setns");
+		close(fd);
+		return -1;
+	}
+	current->user_ns = ns;
+	close(fd);
+
+	if (prepare_userns_creds() < 0) {
+		pr_err("Can't set creds\n");
+		return -1;
+	}
+	return 0;
+}
+
+int set_user_ns(u32 id)
+{
+	struct ns_id *ns;
+
+	if (current->user_ns && current->user_ns->id == id)
+		return 0;
+
+	ns = lookup_ns_by_id(id, &user_ns_desc);
+	if (!ns) {
+		pr_err("Can't find user_ns %u\n", id);
+		return -1;
+	}
+	return __set_user_ns(ns);
+}
+
 struct ns_desc pid_ns_desc = NS_DESC_ENTRY(CLONE_NEWPID, "pid");
 struct ns_desc user_ns_desc = NS_DESC_ENTRY(CLONE_NEWUSER, "user");



More information about the CRIU mailing list