The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/1728
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Closes #1620. Signed-off-by: Christian Brauner <[email protected]>
From 154750341d37deeca3a5e65eb60e118e55d03383 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Wed, 2 Aug 2017 22:21:56 +0200 Subject: [PATCH 1/5] conf: lxc-setup() non-functional changes Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/conf.c | 156 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 97 insertions(+), 59 deletions(-) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 9508f6946..651ba7844 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -4180,51 +4180,62 @@ static int lxc_send_ttys_to_parent(struct lxc_handler *handler) int lxc_setup(struct lxc_handler *handler) { + int ret; const char *name = handler->name; - struct lxc_conf *lxc_conf = handler->conf; const char *lxcpath = handler->lxcpath; + struct lxc_conf *lxc_conf = handler->conf; - if (do_rootfs_setup(lxc_conf, name, lxcpath) < 0) { - ERROR("Error setting up rootfs mount after spawn"); + ret = do_rootfs_setup(lxc_conf, name, lxcpath); + if (ret < 0) { + ERROR("Failed to set up rootfs"); return -1; } if (lxc_conf->inherit_ns_fd[LXC_NS_UTS] == -1) { - if (setup_utsname(lxc_conf->utsname)) { - ERROR("failed to setup the utsname for '%s'", name); + ret = setup_utsname(lxc_conf->utsname); + if (ret < 0) { + ERROR("Failed to set up uts name"); return -1; } } - if (lxc_setup_networks_in_child_namespaces(lxc_conf, - &lxc_conf->network)) { - ERROR("failed to setup the network for '%s'", name); + ret = lxc_setup_networks_in_child_namespaces(lxc_conf, &lxc_conf->network); + if (ret < 0) { + ERROR("Failed to set up networking"); return -1; } if (lxc_conf->autodev > 0) { - if (mount_autodev(name, &lxc_conf->rootfs, lxcpath)) { - ERROR("failed to mount /dev in the container"); + ret = mount_autodev(name, &lxc_conf->rootfs, lxcpath); + if (ret < 0) { + ERROR("Failed to set up \"/dev\""); return -1; } } - /* do automatic mounts (mainly /proc and /sys), but exclude - * those that need to wait until other stuff has finished + /* Do automatic mounts (mainly /proc and /sys), but exclude those that + * need to wait until other stuff has finished. */ - if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler) < 0) { - ERROR("failed to setup the automatic mounts for '%s'", name); + ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & ~LXC_AUTO_CGROUP_MASK, handler); + if (ret < 0) { + ERROR("Failed to set up initial automatic mounts"); return -1; } - if (setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, lxcpath)) { - ERROR("failed to setup the mounts for '%s'", name); + ret = setup_mount(lxc_conf, &lxc_conf->rootfs, lxc_conf->fstab, name, + lxcpath); + if (ret < 0) { + ERROR("Failed to set up fstab mounts"); return -1; } - if (!lxc_list_empty(&lxc_conf->mount_list) && setup_mount_entries(lxc_conf, &lxc_conf->rootfs, &lxc_conf->mount_list, name, lxcpath)) { - ERROR("failed to setup the mount entries for '%s'", name); - return -1; + if (!lxc_list_empty(&lxc_conf->mount_list)) { + ret = setup_mount_entries(lxc_conf, &lxc_conf->rootfs, + &lxc_conf->mount_list, name, lxcpath); + if (ret < 0) { + ERROR("Failed to set up mount entries"); + return -1; + } } /* Make sure any start hooks are in the container */ @@ -4238,94 +4249,121 @@ int lxc_setup(struct lxc_handler *handler) * before, /sys could not have been mounted * (is either mounted automatically or via fstab entries) */ - if (lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler) < 0) { - ERROR("failed to setup the automatic mounts for '%s'", name); + ret = lxc_mount_auto_mounts(lxc_conf, lxc_conf->auto_mounts & LXC_AUTO_CGROUP_MASK, handler); + if (ret < 0) { + ERROR("Failed to set up remaining automatic mounts"); return -1; } - if (run_lxc_hooks(name, "mount", lxc_conf, lxcpath, NULL)) { - ERROR("failed to run mount hooks for container '%s'.", name); + ret = run_lxc_hooks(name, "mount", lxc_conf, lxcpath, NULL); + if (ret < 0) { + ERROR("Failed to run mount hooks"); return -1; } if (lxc_conf->autodev > 0) { - if (run_lxc_hooks(name, "autodev", lxc_conf, lxcpath, NULL)) { - ERROR("failed to run autodev hooks for container '%s'.", name); + ret = run_lxc_hooks(name, "autodev", lxc_conf, lxcpath, NULL); + if (ret < 0) { + ERROR("Failed to run autodev hooks"); return -1; } - if (lxc_fill_autodev(&lxc_conf->rootfs)) { - ERROR("failed to populate /dev in the container"); + ret = lxc_fill_autodev(&lxc_conf->rootfs); + if (ret < 0) { + ERROR("Failed to populate \"/dev\""); return -1; } } - if (!lxc_conf->is_execute && lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, lxc_conf->ttydir)) { - ERROR("failed to setup the console for '%s'", name); - return -1; - } + if (!lxc_conf->is_execute) { + ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console, + lxc_conf->ttydir); + if (ret < 0) { + ERROR("Failed to set up console"); + return -1; + } - if (!lxc_conf->is_execute && setup_dev_symlinks(&lxc_conf->rootfs)) { - ERROR("failed to setup /dev symlinks for '%s'", name); - return -1; + ret = setup_dev_symlinks(&lxc_conf->rootfs); + if (ret < 0) { + ERROR("Failed to setup \"/dev\" symlinks"); + return -1; + } } /* mount /proc if it's not already there */ - if (lxc_create_tmp_proc_mount(lxc_conf) < 0) { - ERROR("failed to LSM mount proc for '%s'", name); + ret = lxc_create_tmp_proc_mount(lxc_conf); + if (ret < 0) { + ERROR("Failed to create temporary proc mount for LSM"); return -1; } - if (setup_pivot_root(&lxc_conf->rootfs)) { - ERROR("failed to set rootfs for '%s'", name); + ret = setup_pivot_root(&lxc_conf->rootfs); + if (ret < 0) { + ERROR("Failed to set up rootfs"); return -1; } - if (lxc_setup_devpts(lxc_conf->pts)) { - ERROR("failed to setup the new pts instance"); + ret = lxc_setup_devpts(lxc_conf->pts); + if (ret < 0) { + ERROR("Failed to set up new devpts instance"); return -1; } - if (lxc_create_tty(name, lxc_conf)) { - ERROR("failed to create the ttys"); + ret = lxc_create_tty(name, lxc_conf); + if (ret < 0) { + ERROR("Failed to allocate ttys"); return -1; } - if (lxc_send_ttys_to_parent(handler) < 0) { - ERROR("failure sending console info to parent"); + ret = lxc_send_ttys_to_parent(handler); + if (ret < 0) { + ERROR("Failed to send ttys to parent"); return -1; } - if (!lxc_conf->is_execute && lxc_setup_tty(lxc_conf)) { - ERROR("failed to setup the ttys for '%s'", name); - return -1; + if (!lxc_conf->is_execute) { + ret = lxc_setup_tty(lxc_conf); + if (ret < 0) { + ERROR("Failed to set up ttys"); + return -1; + } } - if (lxc_conf->pty_names && setenv("container_ttys", lxc_conf->pty_names, 1)) - SYSERROR("failed to set environment variable for container ptys"); + if (lxc_conf->pty_names) { + ret = setenv("container_ttys", lxc_conf->pty_names, 1); + if (ret < 0) + SYSERROR("Failed to set environment variable for ptys"); + } - if (setup_personality(lxc_conf->personality)) { - ERROR("failed to setup personality"); + ret = setup_personality(lxc_conf->personality); + if (ret < 0) { + ERROR("Failed to setup personality"); return -1; } if (!lxc_list_empty(&lxc_conf->keepcaps)) { if (!lxc_list_empty(&lxc_conf->caps)) { - ERROR("Container requests lxc.cap.drop and lxc.cap.keep: either use lxc.cap.drop or lxc.cap.keep, not both."); + ERROR("Container requests lxc.cap.drop and " + "lxc.cap.keep: either use lxc.cap.drop or " + "lxc.cap.keep, not both"); return -1; } - if (dropcaps_except(&lxc_conf->keepcaps)) { - ERROR("failed to keep requested caps"); + + ret = dropcaps_except(&lxc_conf->keepcaps); + if (ret < 0) { + ERROR("Failed to keep requested capabilities"); + return -1; + } + } else { + ret = setup_caps(&lxc_conf->caps); + if (ret < 0) { + ERROR("Failed to drop requested capabilities"); return -1; } - } else if (setup_caps(&lxc_conf->caps)) { - ERROR("failed to drop capabilities"); - return -1; } - NOTICE("Container \"%s\" is set up", name); - + NOTICE("Finished setting up container"); return 0; } From 534efb2ce57c426aa5ac583afba8eff0893cdf9a Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Thu, 3 Aug 2017 17:42:00 +0200 Subject: [PATCH 2/5] conf: non-functional changes Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/conf.h | 57 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/src/lxc/conf.h b/src/lxc/conf.h index 4d3f6d78f..c1c9543ff 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -329,8 +329,10 @@ struct lxc_conf { struct lxc_list caps; struct lxc_list keepcaps; struct lxc_tty_info tty_info; - /* Comma-separated list of lxc.tty.max pty names. */ + + /* comma-separated list of lxc.tty.max pty names */ char *pty_names; + struct lxc_console console; struct lxc_rootfs rootfs; char *ttydir; @@ -341,24 +343,35 @@ struct lxc_conf { unsigned int lsm_aa_allow_incomplete; char *lsm_se_context; int tmp_umount_proc; - char *seccomp; // filename with the seccomp rules + char *seccomp; #if HAVE_SCMP_FILTER_CTX scmp_filter_ctx seccomp_ctx; #endif int maincmd_fd; - unsigned int autodev; // if 1, mount and fill a /dev at start - int haltsignal; // signal used to halt container - int rebootsignal; // signal used to reboot container - int stopsignal; // signal used to hard stop container - char *rcfile; // Copy of the top level rcfile we read - - // Logfile and logleve can be set in a container config file. - // Those function as defaults. The defaults can be overriden - // by command line. However we don't want the command line - // specified values to be saved on c->save_config(). So we - // store the config file specified values here. - char *logfile; // the logfile as specifed in config - int loglevel; // loglevel as specifed in config (if any) + + /* if 1, mount and fill a /dev at start */ + unsigned int autodev; + + /* signal used to halt container */ + int haltsignal; + + /* signal used to reboot container */ + int rebootsignal; + + /* signal used to hard stop container */ + int stopsignal; + + /* Copy of the top level rcfile we read */ + char *rcfile; + + /* Logfile and loglevel can be set in a container config file. Those + * function as defaults. The defaults can be overriden by command line. + * However we don't want the command line specified values to be saved + * on c->save_config(). So we store the config file specified values + * here. + */ + char *logfile; + int loglevel; int logfd; int inherit_ns_fd[LXC_NS_MAX]; @@ -377,11 +390,13 @@ struct lxc_conf { /* list of included files */ struct lxc_list includes; + /* config entries which are not "lxc.*" are aliens */ struct lxc_list aliens; - /* list of environment variables we'll add to the container when - * started */ + /* List of environment variables we'll add to the container when + * started. + */ struct lxc_list environment; /* text representation of the config file */ @@ -391,8 +406,9 @@ struct lxc_conf { /* init command */ char *init_cmd; - /* if running in a new user namespace, the UID/GID that init and COMMAND - * should run under when using lxc-execute */ + /* If running in a new user namespace, the UID/GID that init and COMMAND + * should run under when using lxc-execute. + */ uid_t init_uid; gid_t init_gid; @@ -400,7 +416,8 @@ struct lxc_conf { unsigned int ephemeral; /* The facility to pass to syslog. Let's users establish as what type of - * program liblxc is supposed to write to the syslog. */ + * program liblxc is supposed to write to the syslog. + */ char *syslog; /* Whether PR_SET_NO_NEW_PRIVS will be set for the container. */ From 1d732b29e33730f5bcf320ebf69b8d07a1212c33 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Thu, 3 Aug 2017 17:47:54 +0200 Subject: [PATCH 3/5] conf: allocate O_PATH /dev/pts/ptmx file descriptor Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/conf.c | 30 ++++++++++++++++++++++++++++++ src/lxc/conf.h | 7 +++++++ src/lxc/start.c | 8 ++++++++ 3 files changed, 45 insertions(+) diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 651ba7844..72569edea 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1427,6 +1427,18 @@ static int lxc_setup_devpts(int num_pts) return 0; } +static int lxc_allocate_dev_ptmx_opath_fd(struct lxc_conf *conf) +{ + int fd; + + fd = open("/dev/pts/ptmx", O_PATH); + if (fd < 0) + return -1; + + conf->dev_ptmx.opath_fd = fd; + return 0; +} + static int setup_personality(int persona) { #if HAVE_SYS_PERSONALITY_H @@ -2769,6 +2781,7 @@ struct lxc_conf *lxc_conf_init(void) * default to running as UID/GID 0 when using lxc-execute */ new->init_uid = 0; new->init_gid = 0; + new->dev_ptmx.opath_fd = -1; return new; } @@ -4309,6 +4322,21 @@ int lxc_setup(struct lxc_handler *handler) return -1; } + /* Allocate "/dev/pts/ptmx" O_PATH file descriptor. */ + ret = lxc_allocate_dev_ptmx_opath_fd(lxc_conf); + if (ret < 0) { + ERROR("Failed to allocate \"/dev/pts/ptmx\" file descriptor"); + return -1; + } + + /* Send "/dev/pts/ptmx" O_PATH file descriptor to parent. */ + ret = lxc_abstract_unix_send_fds(handler->ttysock[0], + &lxc_conf->dev_ptmx.opath_fd, 1, NULL, 0); + if (ret < 0) { + ERROR("Failed to send \"/dev/pts/ptmx\" file descriptor"); + return -1; + } + ret = lxc_create_tty(name, lxc_conf); if (ret < 0) { ERROR("Failed to allocate ttys"); @@ -4644,6 +4672,8 @@ void lxc_conf_free(struct lxc_conf *conf) lxc_clear_aliens(conf); lxc_clear_environment(conf); lxc_clear_limits(conf, "lxc.prlimit"); + if (conf->dev_ptmx.opath_fd >= 0) + close(conf->dev_ptmx.opath_fd); free(conf); } diff --git a/src/lxc/conf.h b/src/lxc/conf.h index c1c9543ff..73b3a0d5a 100644 --- a/src/lxc/conf.h +++ b/src/lxc/conf.h @@ -311,6 +311,11 @@ struct saved_nic { char *orig_name; }; +/* O_PATH File descriptor */ +struct lxc_dev_ptmx { + int opath_fd; +}; + struct lxc_conf { int is_execute; char *fstab; @@ -425,6 +430,8 @@ struct lxc_conf { /* RLIMIT_* limits */ struct lxc_list limits; + + struct lxc_dev_ptmx dev_ptmx; }; #ifdef HAVE_TLS diff --git a/src/lxc/start.c b/src/lxc/start.c index d2a054bfc..7e8156662 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -1419,6 +1419,14 @@ static int lxc_spawn(struct lxc_handler *handler) if (lxc_sync_barrier_child(handler, LXC_SYNC_POST_CGROUP)) return -1; + /* Receive "/dev/pts/ptmx" O_PATH file descriptor from child. */ + if (lxc_abstract_unix_recv_fds(handler->ttysock[1], + &handler->conf->dev_ptmx.opath_fd, 1, NULL, + 0) < 0) { + ERROR("Failed to send \"/dev/pts/ptmx\" file descriptor"); + return -1; + } + /* Read tty fds allocated by child. */ if (lxc_recv_ttys_from_child(handler) < 0) { ERROR("Failed to receive tty info from child process."); From 078d81f3418cabc5372e9bf6ec05f5c101e982f5 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Thu, 3 Aug 2017 19:55:32 +0200 Subject: [PATCH 4/5] commands: non-functional changes Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/commands.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/lxc/commands.c b/src/lxc/commands.c index c6ece2cc7..416388ad8 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -21,33 +21,35 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include <stdio.h> +#include "config.h" + #include <errno.h> -#include <unistd.h> -#include <signal.h> #include <fcntl.h> +#include <malloc.h> #include <poll.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/param.h> #include <sys/socket.h> #include <sys/un.h> -#include <sys/param.h> -#include <malloc.h> -#include <stdlib.h> -#include "log.h" -#include "lxc.h" -#include "conf.h" -#include "start.h" /* for struct lxc_handler */ -#include "utils.h" +#include "af_unix.h" #include "cgroup.h" #include "commands.h" #include "commands_utils.h" -#include "console.h" +#include "conf.h" +#include "config.h" #include "confile.h" +#include "console.h" +#include "log.h" +#include "lxc.h" #include "lxclock.h" #include "mainloop.h" #include "monitor.h" -#include "af_unix.h" -#include "config.h" +#include "start.h" /* for struct lxc_handler */ +#include "utils.h" /* * This file provides the different functions for clients to From 6abc60506a94d94a0f56f6730102610cc0b4a009 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Thu, 3 Aug 2017 19:55:47 +0200 Subject: [PATCH 5/5] commands: add LXC_CMD_OPENPTY Closes #1620. Signed-off-by: Christian Brauner <[email protected]> --- src/lxc/commands.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/lxc/commands.h | 9 +++++ src/lxc/conf.c | 4 +- src/lxc/utils.h | 9 +++++ 4 files changed, 126 insertions(+), 3 deletions(-) diff --git a/src/lxc/commands.c b/src/lxc/commands.c index 416388ad8..07113b6e5 100644 --- a/src/lxc/commands.c +++ b/src/lxc/commands.c @@ -92,6 +92,7 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd) [LXC_CMD_GET_NAME] = "get_name", [LXC_CMD_GET_LXCPATH] = "get_lxcpath", [LXC_CMD_ADD_STATE_CLIENT] = "add_state_client", + [LXC_CMD_OPENPTY] = "openpty", }; if (cmd >= LXC_CMD_MAX) @@ -118,10 +119,15 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd) */ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd) { - int ret, rspfd; + int ret; + int rspfd = -1; + int pty_fds[2] = {-1, -1}; struct lxc_cmd_rsp *rsp = &cmd->rsp; - ret = lxc_abstract_unix_recv_fds(sock, &rspfd, 1, rsp, sizeof(*rsp)); + if (cmd->req.cmd == LXC_CMD_OPENPTY) + ret = lxc_abstract_unix_recv_fds(sock, pty_fds, 2, rsp, sizeof(*rsp)); + else + ret = lxc_abstract_unix_recv_fds(sock, &rspfd, 1, rsp, sizeof(*rsp)); if (ret < 0) { WARN("Command %s failed to receive response: %s.", lxc_cmd_str(cmd->req.cmd), strerror(errno)); @@ -147,6 +153,18 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd) rspdata->masterfd = rspfd; rspdata->ttynum = PTR_TO_INT(rsp->data); rsp->data = rspdata; + } else if (cmd->req.cmd == LXC_CMD_OPENPTY) { + struct lxc_cmd_openpty_rsp_data *openpty_rsp = NULL; + + openpty_rsp = malloc(sizeof(*openpty_rsp)); + if (!openpty_rsp) { + ERROR("Command %s couldn't allocate response buffer.", + lxc_cmd_str(cmd->req.cmd)); + return -1; + } + openpty_rsp->master = pty_fds[0]; + openpty_rsp->slave = pty_fds[1]; + rsp->data = openpty_rsp; } if (rsp->datalen == 0) { @@ -934,6 +952,90 @@ static int lxc_cmd_add_state_client_callback(int fd, struct lxc_cmd_req *req, return lxc_cmd_rsp_send(fd, &rsp); } +int lxc_cmd_openpty(const char *name, const char *lxcpath, int *amaster, + int *aslave) +{ + int ret, stopped; + struct lxc_cmd_rr cmd = { + .req = { + .cmd = LXC_CMD_OPENPTY + }, + }; + struct lxc_cmd_openpty_rsp_data *openpty_rsp; + + ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL); + if (ret < 0) + return -1; + + if (cmd.rsp.ret < 0) + return -1; + + openpty_rsp = cmd.rsp.data; + + *amaster = openpty_rsp->master; + *aslave = openpty_rsp->slave; + + return 0; +} + +static int lxc_cmd_openpty_callback(int fd, struct lxc_cmd_req *req, + struct lxc_handler *handler) +{ + int ret; + struct lxc_cmd_rsp rsp; + char proc_self_path[LXC_PROC_SELF_LEN]; + int pty_fds[2] = {-1, -1}; + + memset(&rsp, 0, sizeof(rsp)); + + ret = snprintf(proc_self_path, LXC_PROC_SELF_LEN, "/proc/self/fd/%d", + handler->conf->dev_ptmx.opath_fd); + if (ret < 0 || (size_t)ret >= LXC_PROC_SELF_LEN) { + SYSERROR("Failed to create string: %d != %d", ret, LXC_PROC_SELF_LEN); + return -1; + } + + /* open the pseudoterminal master */ + pty_fds[0] = open(proc_self_path, O_RDWR | O_NOCTTY); + if (pty_fds[0] < 0) { + ERROR("%s - Failed to open \"%s\"", proc_self_path, + strerror(errno)); + return -1; + } + + ret = grantpt(pty_fds[0]); + if (ret < 0) { + ERROR("%s - Failed to grant access to slave pseudoterminal", + strerror(errno)); + close(pty_fds[0]); + return -1; + } + + ret = unlockpt(pty_fds[0]); + if (ret < 0) { + ERROR("%s - Failed to unlock slave pseudoterminal", + strerror(errno)); + close(pty_fds[0]); + return -1; + } + + pty_fds[1] = ioctl(pty_fds[0], TIOCGPTPEER, O_RDWR | O_NOCTTY); + if (pty_fds[1] < 0) { + ERROR("%s - Failed to unlock slave pseudoterminal file " + "descriptor", strerror(errno)); + close(pty_fds[0]); + return -1; + } + + ret = lxc_abstract_unix_send_fds(fd, pty_fds, 2, NULL, 0); + if (ret < 0) { + ERROR("Failed to send pseudoterminal file descriptors"); + return -1; + } + + return 0; +} + static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, struct lxc_handler *handler) { @@ -951,6 +1053,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req, [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback, [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback, [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback, + [LXC_CMD_OPENPTY] = lxc_cmd_openpty_callback, }; if (req->cmd >= LXC_CMD_MAX) { diff --git a/src/lxc/commands.h b/src/lxc/commands.h index 28428c774..4b20f967c 100644 --- a/src/lxc/commands.h +++ b/src/lxc/commands.h @@ -48,6 +48,7 @@ typedef enum { LXC_CMD_GET_NAME, LXC_CMD_GET_LXCPATH, LXC_CMD_ADD_STATE_CLIENT, + LXC_CMD_OPENPTY, LXC_CMD_MAX, } lxc_cmd_t; @@ -73,6 +74,11 @@ struct lxc_cmd_console_rsp_data { int ttynum; }; +struct lxc_cmd_openpty_rsp_data { + int master; + int slave; +}; + extern int lxc_cmd_console_winch(const char *name, const char *lxcpath); extern int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath); @@ -116,4 +122,7 @@ extern int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr, struct lxc_handler *handler); extern int lxc_try_cmd(const char *name, const char *lxcpath); +extern int lxc_cmd_openpty(const char *name, const char *lxcpath, int *amaster, + int *aslave); + #endif /* __commands_h */ diff --git a/src/lxc/conf.c b/src/lxc/conf.c index 72569edea..334cecca7 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -1431,7 +1431,7 @@ static int lxc_allocate_dev_ptmx_opath_fd(struct lxc_conf *conf) { int fd; - fd = open("/dev/pts/ptmx", O_PATH); + fd = open("/dev/ptmx", O_PATH | O_CLOEXEC); if (fd < 0) return -1; @@ -4332,6 +4332,8 @@ int lxc_setup(struct lxc_handler *handler) /* Send "/dev/pts/ptmx" O_PATH file descriptor to parent. */ ret = lxc_abstract_unix_send_fds(handler->ttysock[0], &lxc_conf->dev_ptmx.opath_fd, 1, NULL, 0); + close(lxc_conf->dev_ptmx.opath_fd); + lxc_conf->dev_ptmx.opath_fd = -1; if (ret < 0) { ERROR("Failed to send \"/dev/pts/ptmx\" file descriptor"); return -1; diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 4408c6d69..72efc7d79 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -51,6 +51,15 @@ #define LXC_NUMSTRLEN64 21 #define LXC_LINELEN 4096 #define LXC_IDMAPLEN 4096 +/* strlen("/proc/self/") = 11 + * + + * uint64_t_as_string = 21 + * + + * strlen("fd/") = 3; + * + + * \0 + */ +#define LXC_PROC_SELF_LEN 36 /* returns 1 on success, 0 if there were any failures */ extern int lxc_rmdir_onedev(char *path, const char *exclude);
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
