]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
fix console stdin,stdout,stderr fds
authorDwight Engen <dwight.engen@oracle.com>
Wed, 5 Mar 2014 20:48:39 +0000 (15:48 -0500)
committerStéphane Graber <stgraber@ubuntu.com>
Wed, 5 Mar 2014 20:58:58 +0000 (15:58 -0500)
The fds for stdin,stdout,stderr that we were leaving open for /sbin/init
in the container were those from /dev/tty or lxc.console (if given), which
wasn't right. Inside the container it should only have access to the pty
that lxc creates representing the console.

This was noticed because busybox's init was resetting the termio on its
stdin which was effecting the actual users terminal instead of the pty.
This meant it was setting icanon so were were not passing keystrokes
immediately to the pty, and hence command line history/editing wasn't
working.

Fix by dup'ing the console pty to stdin,stdout,stderr just before
exec()ing /sbin/init. Fix fd leak in error handling that I noticed while
going through this code.

Also tested with lxc.console = none, lxc.console = /dev/tty7 and no
lxc.console specified.

Signed-off-by: Dwight Engen <dwight.engen@oracle.com>
Acked-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/console.c
src/lxc/console.h
src/lxc/lxc_console.c
src/lxc/lxc_start.c
src/lxc/start.c

index 6bfc8a34c2f7f71383ce08481340ecb03ca51032..67e5d0f177e33ce4b2810b7e3c522b2c30bce6ce 100644 (file)
@@ -506,7 +506,7 @@ static void lxc_console_peer_default(struct lxc_console *console)
        DEBUG("using '%s' as console", path);
 
        if (!isatty(console->peer))
-               return;
+               goto err1;
 
        ts = lxc_console_sigwinch_init(console->peer, console->master);
        if (!ts)
@@ -611,7 +611,23 @@ err:
        return -1;
 }
 
+int lxc_console_set_stdfds(struct lxc_handler *handler)
+{
+       struct lxc_conf *conf = handler->conf;
+       struct lxc_console *console = &conf->console;
+
+       if (console->slave < 0)
+               return 0;
 
+       if (dup2(console->slave, 0) < 0 ||
+           dup2(console->slave, 1) < 0 ||
+           dup2(console->slave, 2) < 0)
+       {
+               SYSERROR("failed to dup console");
+               return -1;
+       }
+       return 0;
+}
 
 static int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata,
                                    struct lxc_epoll_descr *descr)
index d45260cbec5789c34aed0cceca32df141128dc2e..eb3894b34accb719c9feffa5962ae7a272222e24 100644 (file)
@@ -36,3 +36,4 @@ extern int  lxc_console(struct lxc_container *c, int ttynum,
                        int escape);
 extern int  lxc_console_getfd(struct lxc_container *c, int *ttynum,
                              int *masterfd);
+extern int  lxc_console_set_stdfds(struct lxc_handler *);
index bfee6fb570d7df774de1d7a8e320c6d145e4cdfe..0fd08e8792706a91d67b1cbcc4d290dbeb019e21 100644 (file)
@@ -28,7 +28,6 @@
 #include <errno.h>
 #include <string.h>
 #include <fcntl.h>
-#include <termios.h>
 #include <unistd.h>
 #include <signal.h>
 #include <libgen.h>
index 05fb1611319554ee83332f54d193dcc872b6a0c9..d9a5694e720f4868ebbfb6988c7fab0b92bf4608 100644 (file)
@@ -27,7 +27,6 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
-#include <termios.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
index eb1c6595581b4385932b120b8676db8fdb85d6f2..89b925fc79407d199c520cc6eb3e601064cf3d12 100644 (file)
@@ -31,7 +31,6 @@
 #include <unistd.h>
 #include <signal.h>
 #include <fcntl.h>
-#include <termios.h>
 #include <grp.h>
 #include <poll.h>
 #include <sys/param.h>
@@ -726,6 +725,15 @@ static int do_start(void *data)
                goto out_warn_father;
        }
 
+       /* Some init's such as busybox will set sane tty settings on stdin,
+        * stdout, stderr which it thinks is the console. We already set them
+        * the way we wanted on the real terminal, and we want init to do its
+        * setup on its console ie. the pty allocated in lxc_console_create()
+        * so make sure that that pty is stdin,stdout,stderr.
+        */
+       if (lxc_console_set_stdfds(handler) < 0)
+               goto out_warn_father;
+
        close(handler->sigfd);
 
        /* after this call, we are in error because this