[lxc-devel] [lxc/master] [RFC] commands: add LXC_CMD_OPENPTY
brauner on Github
lxc-bot at linuxcontainers.org
Thu Aug 3 20:41:04 UTC 2017
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/20170803/2b64ce25/attachment.bin>
-------------- next part --------------
From 154750341d37deeca3a5e65eb60e118e55d03383 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Wed, 2 Aug 2017 22:21:56 +0200
Subject: [PATCH 1/5] conf: lxc-setup()
non-functional changes
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
Date: Thu, 3 Aug 2017 17:42:00 +0200
Subject: [PATCH 2/5] conf: non-functional changes
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
Date: Thu, 3 Aug 2017 19:55:32 +0200
Subject: [PATCH 4/5] commands: non-functional changes
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
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 <christian.brauner at ubuntu.com>
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 <christian.brauner at ubuntu.com>
---
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);
More information about the lxc-devel
mailing list