]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: handle kernels without TIOCGPTPEER
authorChristian Brauner <christian.brauner@ubuntu.com>
Sat, 31 Jul 2021 08:14:39 +0000 (10:14 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Sat, 31 Jul 2021 08:14:39 +0000 (10:14 +0200)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/conf.c
src/lxc/syscall_wrappers.h
src/lxc/terminal.c
src/lxc/terminal.h

index 12b227959b65d0678c360c3cdc79e708965442a3..a20d1f073c4f2a51cdb408e52caa63e1beef59df 100644 (file)
@@ -1072,7 +1072,7 @@ static int lxc_allocate_ttys(struct lxc_conf *conf)
                struct lxc_terminal_info *tty = &ttys->tty[i];
 
                ret = lxc_devpts_terminal(conf->devpts_fd, &tty->ptx,
-                                         &tty->pty, &pty_nr);
+                                         &tty->pty, &pty_nr, false);
                if (ret < 0) {
                        conf->ttys.max = i;
                        return syserror_set(-ENOTTY, "Failed to create tty %zu", i);
@@ -2031,7 +2031,7 @@ static int lxc_setup_console(const struct lxc_handler *handler,
                 * available.
                 */
                ret = lxc_devpts_terminal(handler->conf->devpts_fd, &console->ptx,
-                                         &console->pty, &console->pty_nr);
+                                         &console->pty, &console->pty_nr, false);
                if (ret < 0)
                        return syserror("Failed to allocate console from container's devpts instance");
 
index 4c6ef0731ef4fbb299f6f3b49d7c9425e807cbec..f50875cc12fb9d03e43b9d8ab144402f45072153 100644 (file)
@@ -294,6 +294,7 @@ struct lxc_open_how {
 
 #define PROTECT_OPEN_W_WITH_TRAILING_SYMLINKS (O_CLOEXEC | O_NOCTTY | O_WRONLY)
 #define PROTECT_OPEN_W (PROTECT_OPEN_W_WITH_TRAILING_SYMLINKS | O_NOFOLLOW)
+#define PROTECT_OPEN_RW (O_CLOEXEC | O_NOCTTY | O_RDWR | O_NOFOLLOW)
 
 #ifndef HAVE_OPENAT2
 static inline int openat2(int dfd, const char *filename, struct lxc_open_how *how, size_t size)
index 1e1e2111bf08d2aaab2e5d06fb1ae794e4d1e1d8..13bc7212f3ceacb39cc531bb52dd14b023887e0f 100644 (file)
@@ -911,7 +911,8 @@ err:
        return -ENODEV;
 }
 
-int lxc_devpts_terminal(int devpts_fd, int *ret_ptx, int *ret_pty, int *ret_pty_nr)
+int lxc_devpts_terminal(int devpts_fd, int *ret_ptx, int *ret_pty,
+                       int *ret_pty_nr, bool require_tiocgptpeer)
 {
        __do_close int fd_ptx = -EBADF, fd_opath_pty = -EBADF, fd_pty = -EBADF;
        int pty_nr = -1;
@@ -946,20 +947,35 @@ int lxc_devpts_terminal(int devpts_fd, int *ret_ptx, int *ret_pty, int *ret_pty_
                        break;
                }
 
-               return ret_errno(ENODEV);
+               if (require_tiocgptpeer)
+                       return ret_errno(ENODEV);
        }
 
        ret = ioctl(fd_ptx, TIOCGPTN, &pty_nr);
        if (ret)
                return syswarn_set(-ENODEV, "Failed to retrieve name of terminal pty");
 
-       fd_opath_pty = open_at(devpts_fd, fdstr(pty_nr), PROTECT_OPATH_FILE,
-                              PROTECT_LOOKUP_ABSOLUTE_XDEV, 0);
-       if (fd_opath_pty < 0)
-               return syswarn_set(-ENODEV, "Failed to open terminal pty fd by path %d/%d", devpts_fd, pty_nr);
-
-       if (!same_file_lax(fd_pty, fd_opath_pty))
-               return syswarn_set(-ENODEV, "Terminal file descriptor changed");
+       if (fd_pty < 0) {
+               /*
+                * If we end up it means that TIOCGPTPEER isn't supported but
+                * the caller told us they trust the devpts instance so we use
+                * the pty nr to open the pty side.
+                */
+               fd_pty = open_at(devpts_fd, fdstr(pty_nr), PROTECT_OPEN_RW,
+                                PROTECT_LOOKUP_ABSOLUTE_XDEV, 0);
+               if (fd_pty < 0)
+                       return syswarn_set(-ENODEV, "Failed to open terminal pty fd by path %d/%d",
+                                          devpts_fd, pty_nr);
+       } else {
+               fd_opath_pty = open_at(devpts_fd, fdstr(pty_nr), PROTECT_OPATH_FILE,
+                                      PROTECT_LOOKUP_ABSOLUTE_XDEV, 0);
+               if (fd_opath_pty < 0)
+                       return syswarn_set(-ENODEV, "Failed to open terminal pty fd by path %d/%d",
+                                          devpts_fd, pty_nr);
+
+               if (!same_file_lax(fd_pty, fd_opath_pty))
+                       return syswarn_set(-ENODEV, "Terminal file descriptor changed");
+       }
 
        *ret_ptx = move_fd(fd_ptx);
        *ret_pty = move_fd(fd_pty);
@@ -989,8 +1005,8 @@ int lxc_terminal_parent(struct lxc_conf *conf)
        if (fd_devpts < 0)
                return syserror("Failed to open devpts instance");
 
-       ret = lxc_devpts_terminal(fd_devpts, &console->ptx,
-                                 &console->pty, &console->pty_nr);
+       ret = lxc_devpts_terminal(fd_devpts, &console->ptx, &console->pty,
+                                 &console->pty_nr, false);
        if (ret < 0)
                return syserror("Failed to allocate console");
 
@@ -1013,7 +1029,7 @@ static int lxc_terminal_create_native(const char *name, const char *lxcpath,
                return log_error_errno(-1, errno, "Failed to receive devpts fd");
 
        ret = lxc_devpts_terminal(devpts_fd, &terminal->ptx, &terminal->pty,
-                                 &terminal->pty_nr);
+                                 &terminal->pty_nr, true);
        if (ret < 0)
                return ret;
 
index 05a01e5508670625087910ed17603624694cc7f5..a41aadf0e2d1fbfe670720a827fe47e7f70d8373 100644 (file)
@@ -254,7 +254,8 @@ __hidden extern void lxc_terminal_info_init(struct lxc_terminal_info *terminal);
 __hidden extern void lxc_terminal_init(struct lxc_terminal *terminal);
 __hidden extern int lxc_terminal_signal_sigmask_safe_blocked(struct lxc_terminal *terminal);
 __hidden extern int lxc_devpts_terminal(int devpts_fd, int *ret_ptx,
-                                       int *ret_pty, int *ret_pty_nr);
+                                       int *ret_pty, int *ret_pty_nr,
+                                       bool require_tiocgptpeer);
 __hidden extern int lxc_terminal_parent(struct lxc_conf *conf);
 
 static inline bool wants_console(const struct lxc_terminal *terminal)