[CRIU] [PATCH v1 03/17] user_ns: Set nested namespaces hierarhy
Kirill Tkhai
ktkhai at virtuozzo.com
Thu Jan 12 09:52:29 PST 2017
Introduce ns_id::parent and assign a pointer to parent
for every ns except NS_CRIU.
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/cr-dump.c | 3 ++
criu/include/namespaces.h | 12 ++++++++
criu/namespaces.c | 65 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 80 insertions(+)
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index b6a9c9b63..18ff6d6d1 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -1755,6 +1755,9 @@ int cr_dump_tasks(pid_t pid)
if (collect_file_locks())
goto err;
+ if (populate_ns_hierarhy() < 0)
+ goto err;
+
if (collect_namespaces(true) < 0)
goto err;
diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
index c9f3e8a74..558050783 100644
--- a/criu/include/namespaces.h
+++ b/criu/include/namespaces.h
@@ -1,6 +1,8 @@
#ifndef __CR_NS_H__
#define __CR_NS_H__
+#include <sys/ioctl.h>
+
#include "common/compiler.h"
#include "files.h"
#include "common/list.h"
@@ -39,6 +41,12 @@
#define CLONE_SUBNS (CLONE_NEWNS)
#define EXTRA_SIZE 20
+#ifndef NSIO
+#define NSIO 0xb7
+#define NS_GET_USERNS _IO(NSIO, 0x1)
+#define NS_GET_PARENT _IO(NSIO, 0x2)
+#endif
+
struct ns_desc {
unsigned int cflag;
char *str;
@@ -75,6 +83,9 @@ struct ns_id {
unsigned int id;
pid_t ns_pid;
struct ns_desc *nd;
+ struct ns_id *parent;
+ struct list_head parent_head;
+ struct list_head child_node;
struct ns_id *next;
enum ns_type type;
@@ -135,6 +146,7 @@ extern int predump_task_ns_ids(struct pstree_item *);
extern struct ns_id *rst_new_ns_id(unsigned int id, pid_t pid, struct ns_desc *nd, enum ns_type t);
extern int rst_add_ns_id(unsigned int id, struct pstree_item *, struct ns_desc *nd);
extern struct ns_id *lookup_ns_by_id(unsigned int id, struct ns_desc *nd);
+extern int populate_ns_hierarhy(void);
extern int collect_user_namespaces(bool for_dump);
extern int prepare_userns(struct pstree_item *item);
diff --git a/criu/namespaces.c b/criu/namespaces.c
index b954f9796..148b54a00 100644
--- a/criu/namespaces.c
+++ b/criu/namespaces.c
@@ -13,6 +13,7 @@
#include <sys/stat.h>
#include <limits.h>
#include <errno.h>
+#include <sys/ioctl.h>
#include "page.h"
#include "rst-malloc.h"
@@ -421,6 +422,8 @@ static unsigned int generate_ns_id(int pid, unsigned int kid, struct ns_desc *nd
nsid->type = type;
nsid->kid = kid;
nsid->ns_populated = true;
+ INIT_LIST_HEAD(&nsid->parent_head);
+ INIT_LIST_HEAD(&nsid->child_node);
nsid_add(nsid, nd, ns_next_id++, pid);
found:
@@ -661,6 +664,68 @@ int dump_task_ns_ids(struct pstree_item *item)
return 0;
}
+static int set_parent_ns(struct ns_id *ns, void *oarg)
+{
+ int proc_dir, ns_fd, p_ns_fd, ret = -1;
+ struct ns_id *p_ns;
+ char ns_path[10];
+ struct stat st;
+
+ if (ns->type == NS_CRIU || ns->type == NS_ROOT)
+ return 0;
+
+ proc_dir = open_pid_proc(ns->ns_pid);
+ if (proc_dir < 0)
+ return -1;
+
+ sprintf(ns_path, "ns/%s", ns->nd->str);
+
+ ns_fd = openat(proc_dir, ns_path, O_RDONLY);
+ if (ns_fd < 0) {
+ pr_perror("Can't open %s, pid %d", ns_path, ns->ns_pid);
+ return -1;
+ }
+
+ p_ns_fd = ioctl(ns_fd, NS_GET_PARENT);
+ if (p_ns_fd < 0) {
+ pr_perror("Can't get parent of ns user:[%u], err=%d.\n"
+ "Check, that you kernel has NS_GET_PARENT support.\n",
+ ns->kid, p_ns_fd);
+ goto close_ns_fd;
+ }
+
+ if (fstat(p_ns_fd, &st) < 0) {
+ pr_perror("Unable to stat parent %s ns of pid %d", ns->nd->str, ns->ns_pid);
+ } else {
+ p_ns = lookup_ns_by_kid(st.st_ino, ns->nd);
+ if (!p_ns) {
+ pr_err("User namespaces hierarhies with holes are not supported\n");
+ goto close_p_ns_fd;
+ }
+ ns->parent = p_ns;
+ list_add(&ns->child_node, &p_ns->parent_head);
+ pr_debug("%s ns: %u(%d)<<%u(%d)\n", ns->nd->str, ns->kid,
+ ns->type, p_ns->kid, p_ns->type);
+ ret = 0;
+ }
+
+close_p_ns_fd:
+ close(p_ns_fd);
+close_ns_fd:
+ close(ns_fd);
+
+ return ret;
+}
+
+int populate_ns_hierarhy(void)
+{
+ if (!(root_ns_mask & CLONE_NEWUSER))
+ return 0;
+
+ /* Currently only user_ns needs the hierarhy populated */
+ return walk_namespaces(&user_ns_desc, set_parent_ns, NULL);
+}
+
static UsernsEntry userns_entry = USERNS_ENTRY__INIT;
#define INVALID_ID (~0U)
More information about the CRIU
mailing list