[CRIU] [PATCH v4 03/31] ns: Set nested namespaces hookups
Andrei Vagin
avagin at virtuozzo.com
Wed Feb 22 13:09:38 PST 2017
On Wed, Feb 22, 2017 at 02:30:51PM +0300, Kirill Tkhai wrote:
> Introduce ns_id::parent and assign a pointer to parent
> for every ns except NS_CRIU and NS_ROOT.
> Also populate user_ns for pid_ns.
>
> v4: Set "ret = -1" on one of the error pathes.
> Add comment about user_ns finding.
>
> Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
> ---
> criu/include/namespaces.h | 12 ++++++
> criu/namespaces.c | 92 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 104 insertions(+)
>
> diff --git a/criu/include/namespaces.h b/criu/include/namespaces.h
> index 1b454e0c1..69df0313b 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"
> @@ -40,6 +42,12 @@
>
> #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;
> @@ -76,6 +84,10 @@ struct ns_id {
> unsigned int id;
> pid_t ns_pid;
> struct ns_desc *nd;
> + struct ns_id *parent;
> + struct list_head children;
> + struct list_head siblings;
> + struct ns_id *user_ns;
> struct ns_id *next;
> enum ns_type type;
>
> diff --git a/criu/namespaces.c b/criu/namespaces.c
> index b22162a3a..dd9fb7680 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"
> @@ -302,6 +303,8 @@ struct ns_id *rst_new_ns_id(unsigned int id, pid_t pid,
> nsid->type = type;
> nsid_add(nsid, nd, id, pid);
> nsid->ns_populated = false;
> + INIT_LIST_HEAD(&nsid->children);
> + INIT_LIST_HEAD(&nsid->siblings);
> }
>
> return nsid;
> @@ -421,6 +424,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->children);
> + INIT_LIST_HEAD(&nsid->siblings);
> nsid_add(nsid, nd, ns_next_id++, pid);
>
> found:
> @@ -661,6 +666,93 @@ int dump_task_ns_ids(struct pstree_item *item)
> return 0;
> }
>
> +static int set_ns_opt(int ns_fd, unsigned ioc, struct ns_id **ns, struct ns_desc *nd)
> +{
> + int opt_fd, ret = -1;
> + struct stat st;
> +
> + opt_fd = ioctl(ns_fd, ioc);
> + if (opt_fd < 0) {
> + pr_info("Can't do ns ioctl %x\n", ioc);
> + return -errno;
> + }
> + if (fstat(opt_fd, &st) < 0) {
> + pr_perror("Unable to stat on ns fd");
> + ret = -errno;
> + goto out;
> + }
> + *ns = lookup_ns_by_kid(st.st_ino, nd);
> + if (!*ns) {
> + pr_err("Namespaces hierarhies with holes are not supported\n");
> + ret = -EINVAL;
> + goto out;
> + }
> + ret = 0;
> +out:
> + close(opt_fd);
> + return ret;
> +}
> +
> +static int set_ns_hookups(struct ns_id *ns)
> +{
> + struct ns_desc *nd = ns->nd;
> + struct ns_id *u_ns;
> + int fd, ret = -1;
> +
> + fd = open_proc(ns->ns_pid, "ns/%s", nd->str);
> + if (fd < 0) {
> + pr_perror("Can't open %s, pid %d", nd->str, ns->ns_pid);
> + return -1;
> + }
> +
> + if (ns->type != NS_ROOT && (nd == &pid_ns_desc || nd == &user_ns_desc)) {
> + if (set_ns_opt(fd, NS_GET_PARENT, &ns->parent, nd) < 0)
> + goto out;
> + if (ns->parent && ns->parent->type == NS_CRIU) {
> + pr_err("Wrong determined NS_ROOT, or root_item has NS_OTHER user_ns\n");
> + goto out;
> + }
CID 176742: Null pointer dereferences (FORWARD_NULL)
Comparing "ns->parent" to null implies that "ns->parent" might
be null.
> + list_add(&ns->siblings, &ns->parent->children);
> + }
> +
> + if (nd != &user_ns_desc) {
> + ret = set_ns_opt(fd, NS_GET_USERNS, &ns->user_ns, &user_ns_desc);
> + if (ret == -ENOTTY) {
> + u_ns = NULL;
> + if (root_ns_mask & CLONE_NEWUSER) {
> + /*
> + * Assume, we have the only user_ns. If it's not so,
> + * we'll later fail on NS_GET_PARENT for the second user_ns.
> + */
> + pr_info("Can't get user_ns of %s %u, assuming NS_ROOT\n",
> + nd->str, ns->id);
> + for (u_ns = ns_ids; u_ns; u_ns = u_ns->next) {
> + if (u_ns->nd == &user_ns_desc && u_ns->type == NS_ROOT)
> + break;
> + }
> + if (!u_ns) {
> + pr_err("Can't find root user_ns\n");
> + goto out;
> + }
> + }
> + ns->user_ns = u_ns;
> + } else if (ret < 0) {
> + goto out;
> + } else if (ns->user_ns->type == NS_CRIU) {
> + if (root_ns_mask & CLONE_NEWUSER) {
> + pr_err("Must not be criu user_ns\n");
> + ret = -1;
> + goto out;
> + }
> + ns->user_ns = NULL;
> + }
> + }
> + ret = 0;
> +out:
> + close(fd);
> + return ret;
> +}
> +
> static UsernsEntry userns_entry = USERNS_ENTRY__INIT;
> #define INVALID_ID (~0U)
>
>
More information about the CRIU
mailing list