From 62d05d9b4b862eef14639096c3e6e34871bf8610 Mon Sep 17 00:00:00 2001 From: Serge Hallyn Date: Tue, 17 Nov 2015 12:59:05 -0600 Subject: [PATCH] Better handle preserve_ns behavior 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/ entry is missing => fail (saying kernel misses setns for ) - 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/ entry is missing => log an INFO message (kernel misses setns for ) and continue Signed-off-by: Serge Hallyn --- src/lxc/start.c | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/lxc/start.c b/src/lxc/start.c index a294d18bd..fa64b6dcf 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -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)) -- 2.47.2