diff --git a/include/syscall-types.h b/include/syscall-types.h index ca22b8e9c..bab3dbaca 100644 --- a/include/syscall-types.h +++ b/include/syscall-types.h @@ -59,6 +59,9 @@ struct itimerspec; #define CLONE_ALLNS (CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_NEWNS) +/* Nested namespaces are supported only for these types */ +#define CLONE_SUBNS (CLONE_NEWNS) + #define setns sys_setns struct rlimit; diff --git a/namespaces.c b/namespaces.c index bcb9ddf82..acb316b00 100644 --- a/namespaces.c +++ b/namespaces.c @@ -182,7 +182,7 @@ static unsigned int generate_ns_id(int pid, unsigned int kid, struct ns_desc *nd BUG_ON(current_ns_mask & nd->cflag); pr_info("Will take %s namespace in the image\n", nd->str); current_ns_mask |= nd->cflag; - } else { + } else if (nd->cflag & ~CLONE_SUBNS) { pr_err("Can't dump nested %s namespace for %d\n", nd->str, pid); return 0; diff --git a/pstree.c b/pstree.c index d91edea28..f0e66c337 100644 --- a/pstree.c +++ b/pstree.c @@ -663,16 +663,22 @@ static int prepare_pstree_kobj_ids(void) set_mask: item->rst->clone_flags = cflags; - /* - * Workaround for current namespaces model -- - * all tasks should be in one namespace. And - * this namespace is either inherited from the - * criu or is created for the init task (only) - */ + cflags &= CLONE_ALLNS; + if (item == root_item) { pr_info("Will restore in %lx namespaces\n", cflags); - current_ns_mask = cflags & CLONE_ALLNS; - } else if (cflags & CLONE_ALLNS) { + current_ns_mask = cflags; + } else if (cflags & ~(current_ns_mask & CLONE_SUBNS)) { + /* + * Namespaces from CLONE_SUBNS can be nested, but in + * this case nobody can't share external namespaces of + * these types. + * + * Workaround for all other namespaces -- + * all tasks should be in one namespace. And + * this namespace is either inherited from the + * criu or is created for the init task (only) + */ pr_err("Can't restore sub-task in NS\n"); return -1; }