Commit 1ba79bfe by Christian Brauner Committed by Stéphane Graber

start, utils: improve preserve_ns()

- Allocating an error message that the caller must free seems pointless. We can just print the error message in preserve_ns() itself. This also allows us to avoid using the GNU extension asprintf(). - Improve lxc_preserve_ns(): By passing in NULL or "" as the second argument the function can now also be used to check whether namespaces are supported by the kernel. - Use lxc_preserve_ns() in preserve_ns(). Signed-off-by: 's avatarChristian Brauner <christian.brauner@canonical.com>
parent 74ba4120
...@@ -128,34 +128,29 @@ static void close_ns(int ns_fd[LXC_NS_MAX]) { ...@@ -128,34 +128,29 @@ static void close_ns(int ns_fd[LXC_NS_MAX]) {
} }
} }
/* /* preserve_ns: open /proc/@pid/ns/@ns for each namespace specified
* preserve_ns: open /proc/@pid/ns/@ns for each namespace specified
* in clone_flags. * in clone_flags.
* Return true on success, false on failure. On failure, leave an error * Return true on success, false on failure.
* message in *errmsg, which caller must free.
*/ */
static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid, static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid)
char **errmsg)
{ {
int i, ret; int i, ret;
char path[MAXPATHLEN];
for (i = 0; i < LXC_NS_MAX; i++) for (i = 0; i < LXC_NS_MAX; i++)
ns_fd[i] = -1; ns_fd[i] = -1;
snprintf(path, MAXPATHLEN, "/proc/%d/ns", pid); ret = lxc_preserve_ns(pid, "");
if (access(path, X_OK)) { if (ret < 0) {
if (asprintf(errmsg, "Kernel does not support setns.") == -1) SYSERROR("Kernel does not support attaching to namespaces.");
*errmsg = NULL;
return false; return false;
} else {
close(ret);
} }
for (i = 0; i < LXC_NS_MAX; i++) { for (i = 0; i < LXC_NS_MAX; i++) {
if ((clone_flags & ns_info[i].clone_flag) == 0) if ((clone_flags & ns_info[i].clone_flag) == 0)
continue; continue;
snprintf(path, MAXPATHLEN, "/proc/%d/ns/%s", pid, ns_fd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
ns_info[i].proc_name);
ns_fd[i] = open(path, O_RDONLY | O_CLOEXEC);
if (ns_fd[i] < 0) if (ns_fd[i] < 0)
goto error; goto error;
} }
...@@ -163,15 +158,10 @@ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid, ...@@ -163,15 +158,10 @@ static bool preserve_ns(int ns_fd[LXC_NS_MAX], int clone_flags, pid_t pid,
return true; return true;
error: error:
if (errno == ENOENT) { if (errno == ENOENT)
ret = asprintf(errmsg, "Kernel does not support setns for %s", SYSERROR("Kernel does not support attaching to %s namespaces.", ns_info[i].proc_name);
ns_info[i].proc_name); else
} else { SYSERROR("Failed to open file descriptor for %s namespace: %s.", ns_info[i].proc_name, strerror(errno));
ret = asprintf(errmsg, "Failed to open %s: %s",
path, strerror(errno));
}
if (ret == -1)
*errmsg = NULL;
close_ns(ns_fd); close_ns(ns_fd);
return false; return false;
} }
...@@ -1068,7 +1058,6 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1068,7 +1058,6 @@ static int lxc_spawn(struct lxc_handler *handler)
{ {
int failed_before_rename = 0; int failed_before_rename = 0;
const char *name = handler->name; const char *name = handler->name;
char *errmsg = NULL;
bool cgroups_connected = false; bool cgroups_connected = false;
int saved_ns_fd[LXC_NS_MAX]; int saved_ns_fd[LXC_NS_MAX];
int preserve_mask = 0, i, flags; int preserve_mask = 0, i, flags;
...@@ -1143,12 +1132,9 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1143,12 +1132,9 @@ static int lxc_spawn(struct lxc_handler *handler)
INFO("failed to pin the container's rootfs"); INFO("failed to pin the container's rootfs");
} }
if (!preserve_ns(saved_ns_fd, preserve_mask, getpid(), &errmsg)) { if (!preserve_ns(saved_ns_fd, preserve_mask, getpid()))
SYSERROR("Failed to preserve requested namespaces: %s",
errmsg ? errmsg : "(Out of memory)");
free(errmsg);
goto out_delete_net; goto out_delete_net;
}
if (attach_ns(handler->conf->inherit_ns_fd) < 0) if (attach_ns(handler->conf->inherit_ns_fd) < 0)
goto out_delete_net; goto out_delete_net;
...@@ -1173,11 +1159,8 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1173,11 +1159,8 @@ static int lxc_spawn(struct lxc_handler *handler)
INFO("Cloned a set of new namespaces."); INFO("Cloned a set of new namespaces.");
} }
if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid, &errmsg)) { if (!preserve_ns(handler->nsfd, handler->clone_flags | preserve_mask, handler->pid))
INFO("Failed to store namespace references for stop hook: %s", INFO("Failed to preserve namespace for lxc.hook.stop.");
errmsg ? errmsg : "(Out of memory)");
free(errmsg);
}
if (attach_ns(saved_ns_fd)) if (attach_ns(saved_ns_fd))
WARN("failed to restore saved namespaces"); WARN("failed to restore saved namespaces");
......
...@@ -1975,7 +1975,13 @@ int lxc_preserve_ns(const int pid, const char *ns) ...@@ -1975,7 +1975,13 @@ int lxc_preserve_ns(const int pid, const char *ns)
size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 3 /* /ns */ + 20 /* /NS_NAME */ + 1 /* \0 */; size_t len = 5 /* /proc */ + 21 /* /int_as_str */ + 3 /* /ns */ + 20 /* /NS_NAME */ + 1 /* \0 */;
char path[len]; char path[len];
ret = snprintf(path, len, "/proc/%d/ns/%s", pid, ns); /* This way we can use this function to also check whether namespaces
* are supported by the kernel by passing in the NULL or the empty
* string.
*/
ret = snprintf(path, len, "/proc/%d/ns%s%s", pid,
!ns || strcmp(ns, "") == 0 ? "" : "/",
!ns || strcmp(ns, "") == 0 ? "" : ns);
if (ret < 0 || (size_t)ret >= len) if (ret < 0 || (size_t)ret >= len)
return -1; return -1;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment