[v2,29/36] ns: Implement set_user_ns()

Submitted by Kirill Tkhai on Feb. 3, 2017, 4:15 p.m.

Details

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

Commit Message

Kirill Tkhai Feb. 3, 2017, 4:15 p.m.
Add a field pstree_item::user_ns, which shows the task's current
user_ns, and introduce helpers to set it.

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 bf8b90eba..67a96d6b3 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -169,6 +169,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 create_ns_hierarhy(void);
+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 5a47a4971..0bbd57e96 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -2302,5 +2302,50 @@  int create_ns_hierarhy(void)
 	return 0;
 }
 
+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 = open_fd_of_real_pid(ns->owner.pid, ns->owner.fd, O_RDONLY);
+	if (fd < 0) {
+		pr_perror("Can't open 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");