[lxc-devel] [lxc/master] start: handle kernels without setns support
brauner on Github
lxc-bot at linuxcontainers.org
Thu Mar 1 11:13:56 UTC 2018
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 381 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180301/773ea8c2/attachment.bin>
-------------- next part --------------
From 9e84479f4c386fce6253929ce85c891dc4b87e89 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 1 Mar 2018 11:52:49 +0100
Subject: [PATCH 1/2] attach: rename to LXC_ATTACH_TERMINAL
Rename from LXC_ATTACH_ALLOCATE_PTY to LXC_ATTACH_TERMINAL. The latter is
shorter and more generic. I don't want this whole terminology of ptys, ttys,
and consoles to leak through the API.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/attach.c | 117 +++++++++++++++++++++++----------------------
src/lxc/attach_options.h | 2 +-
src/lxc/tools/lxc_attach.c | 2 +-
3 files changed, 61 insertions(+), 60 deletions(-)
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index 241bd3566..9a8a836d5 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -743,7 +743,7 @@ static signed long get_personality(const char *name, const char *lxcpath)
struct attach_clone_payload {
int ipc_socket;
- int pty_fd;
+ int terminal_slave_fd;
lxc_attach_options_t *options;
struct lxc_proc_context_info *init_ctx;
lxc_attach_exec_t exec_function;
@@ -758,9 +758,9 @@ static void lxc_put_attach_clone_payload(struct attach_clone_payload *p)
p->ipc_socket = -EBADF;
}
- if (p->pty_fd >= 0) {
- close(p->pty_fd);
- p->pty_fd = -EBADF;
+ if (p->terminal_slave_fd >= 0) {
+ close(p->terminal_slave_fd);
+ p->terminal_slave_fd = -EBADF;
}
if (p->init_ctx) {
@@ -957,13 +957,13 @@ static int attach_child_main(struct attach_clone_payload *payload)
}
}
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
- ret = lxc_terminal_prepare_login(payload->pty_fd);
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ ret = lxc_terminal_prepare_login(payload->terminal_slave_fd);
if (ret < 0) {
- SYSERROR("Failed to prepare pty file descriptor %d", payload->pty_fd);
+ SYSERROR("Failed to prepare terminal file descriptor %d", payload->terminal_slave_fd);
goto on_error;
}
- TRACE("Prepared pty file descriptor %d", payload->pty_fd);
+ TRACE("Prepared terminal file descriptor %d", payload->terminal_slave_fd);
}
/* We're done, so we can now do whatever the user intended us to do. */
@@ -974,35 +974,36 @@ static int attach_child_main(struct attach_clone_payload *payload)
rexit(EXIT_FAILURE);
}
-static int lxc_attach_pty(struct lxc_conf *conf, struct lxc_terminal *pty)
+static int lxc_attach_terminal(struct lxc_conf *conf,
+ struct lxc_terminal *terminal)
{
int ret;
- lxc_terminal_init(pty);
+ lxc_terminal_init(terminal);
- ret = lxc_terminal_create(pty);
+ ret = lxc_terminal_create(terminal);
if (ret < 0) {
- SYSERROR("Failed to create pty");
+ SYSERROR("Failed to create terminal");
return -1;
}
/* Shift ttys to container. */
- ret = lxc_terminal_map_ids(conf, pty);
+ ret = lxc_terminal_map_ids(conf, terminal);
if (ret < 0) {
- ERROR("Failed to shift pty");
+ ERROR("Failed to chown terminal");
goto on_error;
}
return 0;
on_error:
- lxc_terminal_delete(pty);
- lxc_terminal_conf_free(pty);
+ lxc_terminal_delete(terminal);
+ lxc_terminal_conf_free(terminal);
return -1;
}
-static int lxc_attach_pty_mainloop_init(struct lxc_terminal *pty,
- struct lxc_epoll_descr *descr)
+static int lxc_attach_terminal_mainloop_init(struct lxc_terminal *terminal,
+ struct lxc_epoll_descr *descr)
{
int ret;
@@ -1012,7 +1013,7 @@ static int lxc_attach_pty_mainloop_init(struct lxc_terminal *pty,
return -1;
}
- ret = lxc_terminal_mainloop_add(descr, pty);
+ ret = lxc_terminal_mainloop_add(descr, terminal);
if (ret < 0) {
ERROR("Failed to add handlers to mainloop");
lxc_mainloop_close(descr);
@@ -1022,40 +1023,40 @@ static int lxc_attach_pty_mainloop_init(struct lxc_terminal *pty,
return 0;
}
-static inline void lxc_attach_pty_close_master(struct lxc_terminal *pty)
+static inline void lxc_attach_terminal_close_master(struct lxc_terminal *terminal)
{
- if (pty->master < 0)
+ if (terminal->master < 0)
return;
- close(pty->master);
- pty->master = -EBADF;
+ close(terminal->master);
+ terminal->master = -EBADF;
}
-static inline void lxc_attach_pty_close_slave(struct lxc_terminal *pty)
+static inline void lxc_attach_terminal_close_slave(struct lxc_terminal *terminal)
{
- if (pty->slave < 0)
+ if (terminal->slave < 0)
return;
- close(pty->slave);
- pty->slave = -EBADF;
+ close(terminal->slave);
+ terminal->slave = -EBADF;
}
-static inline void lxc_attach_pty_close_peer(struct lxc_terminal *pty)
+static inline void lxc_attach_terminal_close_peer(struct lxc_terminal *terminal)
{
- if (pty->peer < 0)
+ if (terminal->peer < 0)
return;
- close(pty->peer);
- pty->peer = -EBADF;
+ close(terminal->peer);
+ terminal->peer = -EBADF;
}
-static inline void lxc_attach_pty_close_log(struct lxc_terminal *pty)
+static inline void lxc_attach_terminal_close_log(struct lxc_terminal *terminal)
{
- if (pty->log_fd < 0)
+ if (terminal->log_fd < 0)
return;
- close(pty->log_fd);
- pty->log_fd = -EBADF;
+ close(terminal->log_fd);
+ terminal->log_fd = -EBADF;
}
int lxc_attach(const char *name, const char *lxcpath,
@@ -1068,7 +1069,7 @@ int lxc_attach(const char *name, const char *lxcpath,
signed long personality;
pid_t attached_pid, init_pid, pid;
struct lxc_proc_context_info *init_ctx;
- struct lxc_terminal pty;
+ struct lxc_terminal terminal;
struct lxc_conf *conf;
struct attach_clone_payload payload = {0};
@@ -1187,18 +1188,18 @@ int lxc_attach(const char *name, const char *lxcpath,
return -1;
}
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
- ret = lxc_attach_pty(conf, &pty);
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ ret = lxc_attach_terminal(conf, &terminal);
if (ret < 0) {
- ERROR("Failed to allocate pty");
+ ERROR("Failed to setup new terminal");
free(cwd);
lxc_proc_put_context_info(init_ctx);
return -1;
}
- pty.log_fd = options->log_fd;
+ terminal.log_fd = options->log_fd;
} else {
- lxc_terminal_init(&pty);
+ lxc_terminal_init(&terminal);
}
/* Create a socket pair for IPC communication; set SOCK_CLOEXEC in order
@@ -1266,8 +1267,8 @@ int lxc_attach(const char *name, const char *lxcpath,
close(ipc_sockets[1]);
free(cwd);
lxc_proc_close_ns_fd(init_ctx);
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY)
- lxc_attach_pty_close_slave(&pty);
+ if (options->attach_flags & LXC_ATTACH_TERMINAL)
+ lxc_attach_terminal_close_slave(&terminal);
/* Attach to cgroup, if requested. */
if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) {
@@ -1291,11 +1292,11 @@ int lxc_attach(const char *name, const char *lxcpath,
goto on_error;
}
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
- ret = lxc_attach_pty_mainloop_init(&pty, &descr);
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ ret = lxc_attach_terminal_mainloop_init(&terminal, &descr);
if (ret < 0)
goto on_error;
- TRACE("Initialized pty mainloop");
+ TRACE("Initialized terminal mainloop");
}
/* Let the child process know to go ahead. */
@@ -1364,7 +1365,7 @@ int lxc_attach(const char *name, const char *lxcpath,
ret_parent = 0;
to_cleanup_pid = -1;
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
ret = lxc_mainloop(&descr, -1);
if (ret < 0) {
ret_parent = -1;
@@ -1373,7 +1374,7 @@ int lxc_attach(const char *name, const char *lxcpath,
}
close_mainloop:
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY)
+ if (options->attach_flags & LXC_ATTACH_TERMINAL)
lxc_mainloop_close(&descr);
on_error:
@@ -1385,9 +1386,9 @@ int lxc_attach(const char *name, const char *lxcpath,
if (to_cleanup_pid > 0)
(void)wait_for_pid(to_cleanup_pid);
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
- lxc_terminal_delete(&pty);
- lxc_terminal_conf_free(&pty);
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ lxc_terminal_delete(&terminal);
+ lxc_terminal_conf_free(&terminal);
}
lxc_proc_put_context_info(init_ctx);
return ret_parent;
@@ -1396,10 +1397,10 @@ int lxc_attach(const char *name, const char *lxcpath,
/* close unneeded file descriptors */
close(ipc_sockets[0]);
ipc_sockets[0] = -EBADF;
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
- lxc_attach_pty_close_master(&pty);
- lxc_attach_pty_close_peer(&pty);
- lxc_attach_pty_close_log(&pty);
+ if (options->attach_flags & LXC_ATTACH_TERMINAL) {
+ lxc_attach_terminal_close_master(&terminal);
+ lxc_attach_terminal_close_peer(&terminal);
+ lxc_attach_terminal_close_log(&terminal);
}
/* Wait for the parent to have setup cgroups. */
@@ -1440,7 +1441,7 @@ int lxc_attach(const char *name, const char *lxcpath,
payload.ipc_socket = ipc_sockets[1];
payload.options = options;
payload.init_ctx = init_ctx;
- payload.pty_fd = pty.slave;
+ payload.terminal_slave_fd = terminal.slave;
payload.exec_function = exec_function;
payload.exec_payload = exec_payload;
@@ -1458,8 +1459,8 @@ int lxc_attach(const char *name, const char *lxcpath,
ERROR("Failed to exec");
_exit(EXIT_FAILURE);
}
- if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY)
- lxc_attach_pty_close_slave(&pty);
+ if (options->attach_flags & LXC_ATTACH_TERMINAL)
+ lxc_attach_terminal_close_slave(&terminal);
/* Tell grandparent the pid of the pid of the newly created child. */
ret = lxc_write_nointr(ipc_sockets[1], &pid, sizeof(pid));
diff --git a/src/lxc/attach_options.h b/src/lxc/attach_options.h
index 1e64e4abf..193fd7e7d 100644
--- a/src/lxc/attach_options.h
+++ b/src/lxc/attach_options.h
@@ -51,7 +51,7 @@ enum {
LXC_ATTACH_LSM_NOW = 0x00020000, /*!< FIXME: unknown */
/* Set PR_SET_NO_NEW_PRIVS to block execve() gainable privileges. */
LXC_ATTACH_NO_NEW_PRIVS = 0x00040000, /*!< PR_SET_NO_NEW_PRIVS */
- LXC_ATTACH_ALLOCATE_PTY = 0x00080000, /*!< Allocate new pty for attached process. */
+ LXC_ATTACH_TERMINAL = 0x00080000, /*!< Allocate new terminal for attached process. */
/* We have 16 bits for things that are on by default and 16 bits that
* are off by default, that should be sufficient to keep binary
diff --git a/src/lxc/tools/lxc_attach.c b/src/lxc/tools/lxc_attach.c
index 087a46f68..74b2829d6 100644
--- a/src/lxc/tools/lxc_attach.c
+++ b/src/lxc/tools/lxc_attach.c
@@ -321,7 +321,7 @@ int main(int argc, char *argv[])
if (elevated_privileges)
attach_options.attach_flags &= ~(elevated_privileges);
if (stdfd_is_pty())
- attach_options.attach_flags |= LXC_ATTACH_ALLOCATE_PTY;
+ attach_options.attach_flags |= LXC_ATTACH_TERMINAL;
attach_options.namespaces = namespace_flags;
attach_options.personality = new_personality;
attach_options.env_policy = env_policy;
From 4cb53844bc9a591704a10606de1107f4f67b90dd Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Thu, 1 Mar 2018 12:12:50 +0100
Subject: [PATCH 2/2] start: handle kernels without setns support
Closes #1390.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/start.c | 88 +++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 60 insertions(+), 28 deletions(-)
diff --git a/src/lxc/start.c b/src/lxc/start.c
index eb7331f8a..4e2f8a433 100644
--- a/src/lxc/start.c
+++ b/src/lxc/start.c
@@ -142,11 +142,31 @@ static void lxc_put_nsfds(struct lxc_handler *handler)
}
}
-/* lxc_preserve_namespaces: open /proc/@pid/ns/@ns for each namespace specified
- * in ns_clone_flags.
+static int lxc_try_preserve_ns(const int pid, const char *ns)
+{
+ int fd;
+
+ fd = lxc_preserve_ns(pid, ns);
+ if (fd < 0) {
+ if (errno != ENOENT) {
+ SYSERROR("Failed to preserve %s namespace", ns);
+ return -EINVAL;
+ }
+
+ WARN("%s - Kernel does not support preserving %s namespaces",
+ strerror(errno), ns);
+ return -EOPNOTSUPP;
+ }
+
+ return fd;
+}
+
+/* lxc_try_preserve_namespaces: open /proc/@pid/ns/@ns for each namespace
+ * specified in ns_clone_flags.
* Return true on success, false on failure.
*/
-static bool lxc_preserve_namespaces(struct lxc_handler *handler, int ns_clone_flags, pid_t pid)
+static bool lxc_try_preserve_namespaces(struct lxc_handler *handler,
+ int ns_clone_flags, pid_t pid)
{
int i;
@@ -154,27 +174,32 @@ static bool lxc_preserve_namespaces(struct lxc_handler *handler, int ns_clone_fl
handler->nsfd[i] = -EBADF;
for (i = 0; i < LXC_NS_MAX; i++) {
+ int fd;
+
if ((ns_clone_flags & ns_info[i].clone_flag) == 0)
continue;
- handler->nsfd[i] = lxc_preserve_ns(pid, ns_info[i].proc_name);
- if (handler->nsfd[i] < 0)
- goto error;
+ fd = lxc_try_preserve_ns(pid, ns_info[i].proc_name);
+ if (fd < 0) {
+ handler->nsfd[i] = -EBADF;
- DEBUG("Preserved %s namespace via fd %d", ns_info[i].proc_name, handler->nsfd[i]);
+ /* Do not fail to start container on kernels that do
+ * not support interacting with namespaces through
+ * /proc.
+ */
+ if (fd == -EOPNOTSUPP)
+ continue;
+
+ lxc_put_nsfds(handler);
+ return false;
+ }
+
+ handler->nsfd[i] = fd;
+ DEBUG("Preserved %s namespace via fd %d", ns_info[i].proc_name,
+ handler->nsfd[i]);
}
return true;
-
-error:
- if (errno == ENOENT)
- SYSERROR("Kernel does not support attaching to %s namespaces",
- ns_info[i].proc_name);
- else
- SYSERROR("Failed to open file descriptor for %s namespace",
- ns_info[i].proc_name);
- lxc_put_nsfds(handler);
- return false;
}
static int match_fd(int fd)
@@ -1590,7 +1615,7 @@ static int lxc_spawn(struct lxc_handler *handler)
if (handler->ns_on_clone_flags & ns_info[i].clone_flag)
INFO("Cloned %s", ns_info[i].flag_name);
- if (!lxc_preserve_namespaces(handler, handler->ns_on_clone_flags, handler->pid)) {
+ if (!lxc_try_preserve_namespaces(handler, handler->ns_on_clone_flags, handler->pid)) {
ERROR("Failed to preserve cloned namespaces for lxc.hook.stop");
goto out_delete_net;
}
@@ -1634,13 +1659,16 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net;
/* Now we're ready to preserve the network namespace */
- ret = lxc_preserve_ns(handler->pid, "net");
+ ret = lxc_try_preserve_ns(handler->pid, "net");
if (ret < 0) {
- ERROR("%s - Failed to preserve net namespace", strerror(errno));
- goto out_delete_net;
+ if (ret != -EOPNOTSUPP) {
+ ERROR("%s - Failed to preserve net namespace", strerror(errno));
+ goto out_delete_net;
+ }
+ } else {
+ handler->nsfd[LXC_NS_NET] = ret;
+ DEBUG("Preserved net namespace via fd %d", ret);
}
- handler->nsfd[LXC_NS_NET] = ret;
- DEBUG("Preserved net namespace via fd %d", ret);
/* Create the network configuration. */
if (handler->ns_clone_flags & CLONE_NEWNET) {
@@ -1703,13 +1731,17 @@ static int lxc_spawn(struct lxc_handler *handler)
if (handler->ns_clone_flags & CLONE_NEWCGROUP) {
/* Now we're ready to preserve the cgroup namespace */
- ret = lxc_preserve_ns(handler->pid, "cgroup");
+ ret = lxc_try_preserve_ns(handler->pid, "cgroup");
if (ret < 0) {
- ERROR("%s - Failed to preserve cgroup namespace", strerror(errno));
- goto out_delete_net;
+ if (ret != -EOPNOTSUPP) {
+ ERROR("%s - Failed to preserve cgroup namespace",
+ strerror(errno));
+ goto out_delete_net;
+ }
+ } else {
+ handler->nsfd[LXC_NS_CGROUP] = ret;
+ DEBUG("Preserved cgroup namespace via fd %d", ret);
}
- handler->nsfd[LXC_NS_CGROUP] = ret;
- DEBUG("Preserved cgroup namespace via fd %d", ret);
}
ret = snprintf(pidstr, 20, "%d", handler->pid);
More information about the lxc-devel
mailing list