[v4,25/31] ns: Implement set_user_ns()

Submitted by Kirill Tkhai on Feb. 22, 2017, 11:34 a.m.

Details

Message ID 148776325529.17334.10599401537814764753.stgit@localhost.localdomain
State New
Series "Nested user namespaces support"
Headers show

Commit Message

Kirill Tkhai Feb. 22, 2017, 11:34 a.m.
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@virtuozzo.com>
---
 criu/include/namespaces.h |    2 ++
 criu/include/pstree.h     |    1 +
 criu/namespaces.c         |   45 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 48 insertions(+)

Patch hide | download patch | download mbox

diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index c1d819f32..6aed3817e 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 b082e3586..5790943be 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;
 };
 
 static inline pid_t vpid(const struct pstree_item *i)
diff --git a/criu/namespaces.c b/criu/namespaces.c
index 0a67903d6..ebca5700f 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -2276,5 +2276,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");