]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
Better handle preserve_ns behavior 700/head
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Tue, 17 Nov 2015 18:59:05 +0000 (12:59 -0600)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Tue, 17 Nov 2015 19:31:08 +0000 (13:31 -0600)
Commit b6b2b194a8 preserves the container's namespaces for
possible later use in stop hook.  But some kernels don't have
/proc/pid/ns/ns for all the namespaces we may be interested in.
So warn but continue if this is the case.

Implement stgraber's suggested semantics.

 - User requests some namespaces be preserved:
    - If /proc/self/ns is missing => fail (saying kernel misses setns)
    - If /proc/self/ns/<namespace> entry is missing => fail (saying kernel misses setns for <namespace>)
 - User doesn't request some namespaces be preserved:
    - If /proc/self/ns is missing => log an INFO message (kernel misses setns) and continue
    - If /proc/self/ns/<namespace> entry is missing => log an INFO message (kernel misses setns for <namespace>) and continue

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
src/lxc/start.c

index a294d18bd10e84588ff4ca350904f24f4e7baa79..fa64b6dcf94c859de472161111feb2f3ae787dbc 100644 (file)
@@ -124,8 +124,15 @@ static void close_ns(int ns_fd[LXC_NS_MAX]) {
        }
 }
 
-static int preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid) {
-       int i, saved_errno;
+/*
+ * preserve_ns: open /proc/@pid/ns/@ns for each namespace specified
+ * in clone_flags.
+ * Return true on success, false on failure.  On failure, leave an error
+ * message in *errmsg, which caller must free.
+ */
+static
+bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid, char **errmsg) {
+       int i, ret;
        char path[MAXPATHLEN];
 
        for (i = 0; i < LXC_NS_MAX; i++)
@@ -133,8 +140,9 @@ static int preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid) {
 
        snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid);
        if (access(path, X_OK)) {
-               WARN("Kernel does not support attach; preserve_ns ignored");
-               return 0;
+               if (asprintf(errmsg, "Kernel does not support setns.") == -1)
+                       *errmsg = NULL;
+               return false;
        }
 
        for (i = 0; i < LXC_NS_MAX; i++) {
@@ -147,14 +155,20 @@ static int preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid) {
                        goto error;
        }
 
-       return 0;
+       return true;
 
 error:
-       saved_errno = errno;
+       if (errno == ENOENT) {
+               ret = asprintf(errmsg, "Kernel does not support setns for %s",
+                       ns_info[i].proc_name);
+       } else {
+               ret = asprintf(errmsg, "Failed to open %s: %s",
+                       path, strerror(errno));
+       }
+       if (ret == -1)
+               *errmsg = NULL;
        close_ns(ns_fd);
-       errno = saved_errno;
-       SYSERROR("failed to open '%s'", path);
-       return -1;
+       return false;
 }
 
 static int attach_ns(const int ns_fd[LXC_NS_MAX]) {
@@ -933,6 +947,7 @@ static int lxc_spawn(struct lxc_handler *handler)
 {
        int failed_before_rename = 0;
        const char *name = handler->name;
+       char *errmsg = NULL;
        bool cgroups_connected = false;
        int saved_ns_fd[LXC_NS_MAX];
        int preserve_mask = 0, i;
@@ -1007,8 +1022,12 @@ static int lxc_spawn(struct lxc_handler *handler)
                        INFO("failed to pin the container's rootfs");
        }
 
-       if (preserve_ns(saved_ns_fd, preserve_mask, getpid()) < 0)
+       if (!preserve_ns(saved_ns_fd, preserve_mask, getpid(), &errmsg)) {
+               SYSERROR("Failed to preserve requested namespaces: %s",
+                       errmsg ? errmsg : "(Out of memory)");
+               free(errmsg);
                goto out_delete_net;
+       }
        if (attach_ns(handler->conf->inherit_ns_fd) < 0)
                goto out_delete_net;
 
@@ -1028,9 +1047,11 @@ static int lxc_spawn(struct lxc_handler *handler)
                goto out_delete_net;
        }
 
-       if (preserve_ns(handler->nsfd, handler->clone_flags, handler->pid) < 0) {
-           ERROR("failed to store namespace references");
-           goto out_delete_net;
+       if (preserve_ns(handler->nsfd, handler->clone_flags, handler->pid,
+                               &errmsg) < 0) {
+               INFO("Failed to store namespace references for stop hook: %s",
+                       errmsg ? errmsg : "(Out of memory)");
+               free(errmsg);
        }
 
        if (attach_ns(saved_ns_fd))