[CRIU] [PATCH v3 05/33] ns: Set nested namespaces hookups
Kirill Tkhai
ktkhai at virtuozzo.com
Wed Feb 22 00:53:43 PST 2017
On 22.02.2017 07:43, Andrei Vagin wrote:
> On Tue, Feb 21, 2017 at 02:53:38PM +0300, Kirill Tkhai wrote:
>> On 21.02.2017 08:45, Andrei Vagin wrote:
>>> On Thu, Feb 16, 2017 at 03:07:19PM +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.
>>>>
>>>> Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
>>>> ---
>>>> criu/include/namespaces.h | 12 ++++++
>>>> criu/namespaces.c | 87 +++++++++++++++++++++++++++++++++++++++++++++
>>>> 2 files changed, 99 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 9e61c9481..c4ef52733 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,88 @@ 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;
>>>> + }
>>>> + 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) {
>>>> + pr_info("Can't get user_ns of %s %u, assuming NS_ROOT\n",
>>>> + nd->str, ns->id);
>>>
>>> It is possible only if we dump only one userns.
>>
>> Sure, and if we have several user_ns, we'll fail on NS_GET_PARENT made for one of them.
>
> pls, add a comment here about this.
OK
>>
>>>> + u_ns = NULL;
>>>> + if (root_ns_mask & CLONE_NEWUSER) {
>>>> + 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 is zero here
>>
>> Yeah, I'll fix that.
>>
>>>
>>>> + goto out;
>>>> + }
>>>> + ns->user_ns = NULL;
>>>> + }
>>>> + }
>>>> + ret = 0;
>>>> +out:
>>>> + close(fd);
>>>> + return ret;
>>>> +}
>>>> +
>>>> static UsernsEntry userns_entry = USERNS_ENTRY__INIT;
>>>> #define INVALID_ID (~0U)
>>>>
>>>>
>>>> _______________________________________________
>>>> CRIU mailing list
>>>> CRIU at openvz.org
>>>> https://lists.openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list