Skip to content

Commit

Permalink
Better handle preserve_ns behavior
Browse files Browse the repository at this point in the history
Commit b6b2b19 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>
  • Loading branch information
hallyn authored and stgraber committed Nov 17, 2016
1 parent fc0451a commit 74d1b69
Showing 1 changed file with 34 additions and 13 deletions.
47 changes: 34 additions & 13 deletions src/lxc/start.c
Expand Up @@ -117,17 +117,25 @@ 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++)
ns_fd[i] = -1;

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++) {
Expand All @@ -140,14 +148,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]) {
Expand Down Expand Up @@ -798,6 +812,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;
Expand Down Expand Up @@ -889,8 +904,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;

Expand All @@ -910,9 +929,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))
Expand Down

0 comments on commit 74d1b69

Please sign in to comment.