1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include <lxc/lxccontainer.h>
13 #include <sys/epoll.h>
14 #include <sys/types.h>
26 #include "memory_utils.h"
28 #include "syscall_wrappers.h"
38 #define LXC_TERMINAL_BUFFER_SIZE 1024
40 lxc_log_define(terminal
, lxc
);
42 void lxc_terminal_winsz(int srcfd
, int dstfd
)
50 ret
= ioctl(srcfd
, TIOCGWINSZ
, &wsz
);
52 WARN("Failed to get window size");
56 ret
= ioctl(dstfd
, TIOCSWINSZ
, &wsz
);
58 WARN("Failed to set window size");
60 DEBUG("Set window size to %d columns and %d rows", wsz
.ws_col
,
66 static void lxc_terminal_winch(struct lxc_terminal_state
*ts
)
68 lxc_terminal_winsz(ts
->stdinfd
, ts
->ptxfd
);
71 int lxc_terminal_signalfd_cb(int fd
, uint32_t events
, void *cbdata
,
72 struct lxc_async_descr
*descr
)
75 struct signalfd_siginfo siginfo
;
76 struct lxc_terminal_state
*ts
= cbdata
;
78 ret
= lxc_read_nointr(fd
, &siginfo
, sizeof(siginfo
));
79 if (ret
< 0 || (size_t)ret
< sizeof(siginfo
)) {
80 ERROR("Failed to read signal info");
81 return LXC_MAINLOOP_ERROR
;
84 if (siginfo
.ssi_signo
== SIGTERM
) {
85 DEBUG("Received SIGTERM. Detaching from the terminal");
86 return LXC_MAINLOOP_CLOSE
;
89 if (siginfo
.ssi_signo
== SIGWINCH
)
90 lxc_terminal_winch(ts
);
92 return LXC_MAINLOOP_CONTINUE
;
95 struct lxc_terminal_state
*lxc_terminal_signal_init(int srcfd
, int dstfd
)
97 __do_close
int signal_fd
= -EBADF
;
98 __do_free
struct lxc_terminal_state
*ts
= NULL
;
102 ts
= malloc(sizeof(*ts
));
106 memset(ts
, 0, sizeof(*ts
));
111 ret
= sigemptyset(&mask
);
113 SYSERROR("Failed to initialize an empty signal set");
118 ret
= sigaddset(&mask
, SIGWINCH
);
120 SYSNOTICE("Failed to add SIGWINCH to signal set");
122 INFO("fd %d does not refer to a tty device", srcfd
);
125 /* Exit the mainloop cleanly on SIGTERM. */
126 ret
= sigaddset(&mask
, SIGTERM
);
128 SYSERROR("Failed to add SIGWINCH to signal set");
132 ret
= pthread_sigmask(SIG_BLOCK
, &mask
, &ts
->oldmask
);
134 WARN("Failed to block signals");
138 signal_fd
= signalfd(-1, &mask
, SFD_CLOEXEC
);
140 WARN("Failed to create signal fd");
141 (void)pthread_sigmask(SIG_SETMASK
, &ts
->oldmask
, NULL
);
144 ts
->sigfd
= move_fd(signal_fd
);
145 TRACE("Created signal fd %d", ts
->sigfd
);
150 int lxc_terminal_signal_sigmask_safe_blocked(struct lxc_terminal
*terminal
)
152 struct lxc_terminal_state
*state
= terminal
->tty_state
;
157 return pthread_sigmask(SIG_SETMASK
, &state
->oldmask
, NULL
);
161 * lxc_terminal_signal_fini: uninstall signal handler
163 * @terminal: terminal instance
165 * Restore the saved signal handler that was in effect at the time
166 * lxc_terminal_signal_init() was called.
168 static void lxc_terminal_signal_fini(struct lxc_terminal
*terminal
)
170 struct lxc_terminal_state
*state
= terminal
->tty_state
;
172 if (!terminal
->tty_state
)
175 state
= terminal
->tty_state
;
176 if (state
->sigfd
>= 0) {
179 if (pthread_sigmask(SIG_SETMASK
, &state
->oldmask
, NULL
) < 0)
180 SYSWARN("Failed to restore signal mask");
183 free(terminal
->tty_state
);
184 terminal
->tty_state
= NULL
;
187 static int lxc_terminal_truncate_log_file(struct lxc_terminal
*terminal
)
189 /* be very certain things are kosher */
190 if (!terminal
->log_path
|| terminal
->log_fd
< 0)
193 return lxc_unpriv(ftruncate(terminal
->log_fd
, 0));
196 static int lxc_terminal_rotate_log_file(struct lxc_terminal
*terminal
)
198 __do_free
char *tmp
= NULL
;
202 if (!terminal
->log_path
|| terminal
->log_rotate
== 0)
205 /* be very certain things are kosher */
206 if (terminal
->log_fd
< 0)
209 len
= strlen(terminal
->log_path
) + sizeof(".1");
210 tmp
= must_realloc(NULL
, len
);
212 ret
= strnprintf(tmp
, len
, "%s.1", terminal
->log_path
);
216 close(terminal
->log_fd
);
217 terminal
->log_fd
= -1;
218 ret
= lxc_unpriv(rename(terminal
->log_path
, tmp
));
222 return lxc_terminal_create_log_file(terminal
);
225 static int lxc_terminal_write_log_file(struct lxc_terminal
*terminal
, char *buf
,
230 int64_t space_left
= -1;
232 if (terminal
->log_fd
< 0)
235 /* A log size <= 0 means that there's no limit on the size of the log
236 * file at which point we simply ignore whether the log is supposed to
239 if (terminal
->log_size
<= 0)
240 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
242 /* Get current size of the log file. */
243 ret
= fstat(terminal
->log_fd
, &st
);
245 SYSERROR("Failed to stat the terminal log file descriptor");
249 /* handle non-regular files */
250 if ((st
.st_mode
& S_IFMT
) != S_IFREG
) {
251 /* This isn't a regular file. so rotating the file seems a
252 * dangerous thing to do, size limits are also very
253 * questionable. Let's not risk anything and tell the user that
254 * they're requesting us to do weird stuff.
256 if (terminal
->log_rotate
> 0 || terminal
->log_size
> 0)
259 /* I mean, sure log wherever you want to. */
260 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
263 space_left
= terminal
->log_size
- st
.st_size
;
265 /* User doesn't want to rotate the log file and there's no more space
266 * left so simply truncate it.
268 if (space_left
<= 0 && terminal
->log_rotate
<= 0) {
269 ret
= lxc_terminal_truncate_log_file(terminal
);
273 if (bytes_read
<= terminal
->log_size
)
274 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
276 /* Write as much as we can into the buffer and loose the rest. */
277 return lxc_write_nointr(terminal
->log_fd
, buf
, terminal
->log_size
);
280 /* There's enough space left. */
281 if (bytes_read
<= space_left
)
282 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
284 /* There's not enough space left but at least write as much as we can
285 * into the old log file.
287 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, space_left
);
291 /* Calculate how many bytes we still need to write. */
292 bytes_read
-= space_left
;
294 /* There'd be more to write but we aren't instructed to rotate the log
295 * file so simply return. There's no error on our side here.
297 if (terminal
->log_rotate
> 0)
298 ret
= lxc_terminal_rotate_log_file(terminal
);
300 ret
= lxc_terminal_truncate_log_file(terminal
);
304 if (terminal
->log_size
< bytes_read
) {
305 /* Well, this is unfortunate because it means that there is more
306 * to write than the user has granted us space. There are
307 * multiple ways to handle this but let's use the simplest one:
308 * write as much as we can, tell the user that there was more
309 * stuff to write and move on.
310 * Note that this scenario shouldn't actually happen with the
311 * standard pty-based terminal that LXC allocates since it will
312 * be switched into raw mode. In raw mode only 1 byte at a time
313 * should be read and written.
315 WARN("Size of terminal log file is smaller than the bytes to write");
316 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, terminal
->log_size
);
323 /* Yay, we made it. */
324 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
331 static int lxc_terminal_ptx_io(struct lxc_terminal
*terminal
)
333 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
334 int r
, w
, w_log
, w_rbuf
;
336 w
= r
= lxc_read_nointr(terminal
->ptx
, buf
, sizeof(buf
));
341 /* write to peer first */
342 if (terminal
->peer
>= 0)
343 w
= lxc_write_nointr(terminal
->peer
, buf
, r
);
345 /* write to terminal ringbuffer */
346 if (terminal
->buffer_size
> 0)
347 w_rbuf
= lxc_ringbuf_write(&terminal
->ringbuf
, buf
, r
);
349 /* write to terminal log */
350 if (terminal
->log_fd
>= 0)
351 w_log
= lxc_terminal_write_log_file(terminal
, buf
, r
);
354 WARN("Short write on terminal r:%d != w:%d", r
, w
);
358 SYSTRACE("Failed to write %d bytes to terminal ringbuffer", r
);
362 TRACE("Failed to write %d bytes to terminal log", r
);
367 static int lxc_terminal_peer_io(struct lxc_terminal
*terminal
)
369 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
372 w
= r
= lxc_read_nointr(terminal
->peer
, buf
, sizeof(buf
));
376 w
= lxc_write_nointr(terminal
->ptx
, buf
, r
);
378 WARN("Short write on terminal r:%d != w:%d", r
, w
);
383 static int lxc_terminal_ptx_io_handler(int fd
, uint32_t events
, void *data
,
384 struct lxc_async_descr
*descr
)
386 struct lxc_terminal
*terminal
= data
;
389 ret
= lxc_terminal_ptx_io(data
);
391 return log_info(LXC_MAINLOOP_CLOSE
,
392 "Terminal client on fd %d has exited",
395 return LXC_MAINLOOP_CONTINUE
;
398 static int lxc_terminal_peer_io_handler(int fd
, uint32_t events
, void *data
,
399 struct lxc_async_descr
*descr
)
401 struct lxc_terminal
*terminal
= data
;
404 ret
= lxc_terminal_peer_io(data
);
406 return log_info(LXC_MAINLOOP_CLOSE
,
407 "Terminal client on fd %d has exited",
410 return LXC_MAINLOOP_CONTINUE
;
413 static int lxc_terminal_mainloop_add_peer(struct lxc_terminal
*terminal
)
417 if (terminal
->peer
>= 0) {
418 ret
= lxc_mainloop_add_handler(terminal
->descr
, terminal
->peer
,
419 lxc_terminal_peer_io_handler
,
420 default_cleanup_handler
,
421 terminal
, "lxc_terminal_peer_io_handler");
423 WARN("Failed to add terminal peer handler to mainloop");
428 if (!terminal
->tty_state
|| terminal
->tty_state
->sigfd
< 0)
431 ret
= lxc_mainloop_add_handler(terminal
->descr
,
432 terminal
->tty_state
->sigfd
,
433 lxc_terminal_signalfd_cb
,
434 default_cleanup_handler
,
436 "lxc_terminal_signalfd_cb");
438 WARN("Failed to add signal handler to mainloop");
445 int lxc_terminal_mainloop_add(struct lxc_async_descr
*descr
,
446 struct lxc_terminal
*terminal
)
450 if (terminal
->ptx
< 0) {
451 INFO("Terminal is not initialized");
455 ret
= lxc_mainloop_add_handler(descr
, terminal
->ptx
,
456 lxc_terminal_ptx_io_handler
,
457 default_cleanup_handler
,
458 terminal
, "lxc_terminal_ptx_io_handler");
460 ERROR("Failed to add handler for terminal ptx fd %d to mainloop", terminal
->ptx
);
464 /* We cache the descr so that we can add an fd to it when someone
465 * does attach to it in lxc_terminal_allocate().
467 terminal
->descr
= descr
;
469 return lxc_terminal_mainloop_add_peer(terminal
);
472 int lxc_setup_tios(int fd
, struct termios
*oldtios
)
475 struct termios newtios
;
478 ERROR("File descriptor %d does not refer to a terminal", fd
);
482 /* Get current termios. */
483 ret
= tcgetattr(fd
, oldtios
);
485 SYSERROR("Failed to get current terminal settings");
489 /* ensure we don't end up in an endless loop:
490 * The kernel might fire SIGTTOU while an
491 * ioctl() in tcsetattr() is executed. When the ioctl()
492 * is resumed and retries, the signal handler interrupts it again.
494 signal (SIGTTIN
, SIG_IGN
);
495 signal (SIGTTOU
, SIG_IGN
);
499 /* We use the same settings that ssh does. */
500 newtios
.c_iflag
|= IGNPAR
;
501 newtios
.c_iflag
&= ~(ISTRIP
| INLCR
| IGNCR
| ICRNL
| IXON
| IXANY
| IXOFF
);
503 newtios
.c_iflag
&= ~IUCLC
;
505 newtios
.c_lflag
&= ~(TOSTOP
| ISIG
| ICANON
| ECHO
| ECHOE
| ECHOK
| ECHONL
);
507 newtios
.c_lflag
&= ~IEXTEN
;
509 newtios
.c_oflag
|= ONLCR
;
510 newtios
.c_oflag
|= OPOST
;
511 newtios
.c_cc
[VMIN
] = 1;
512 newtios
.c_cc
[VTIME
] = 0;
514 /* Set new attributes. */
515 ret
= tcsetattr(fd
, TCSAFLUSH
, &newtios
);
517 ERROR("Failed to set new terminal settings");
524 static void lxc_terminal_peer_proxy_free(struct lxc_terminal
*terminal
)
526 lxc_terminal_signal_fini(terminal
);
528 close(terminal
->proxy
.ptx
);
529 terminal
->proxy
.ptx
= -1;
531 close(terminal
->proxy
.pty
);
532 terminal
->proxy
.pty
= -1;
534 terminal
->proxy
.busy
= -1;
536 terminal
->proxy
.name
[0] = '\0';
541 static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal
*terminal
,
545 struct termios oldtermio
;
546 struct lxc_terminal_state
*ts
;
548 if (terminal
->ptx
< 0) {
549 ERROR("Terminal not set up");
553 if (terminal
->proxy
.busy
!= -1 || terminal
->peer
!= -1) {
554 NOTICE("Terminal already in use");
558 if (terminal
->tty_state
) {
559 ERROR("Terminal has already been initialized");
563 /* This is the proxy terminal that will be given to the client, and
564 * that the real terminal ptx will send to / recv from.
566 ret
= openpty(&terminal
->proxy
.ptx
, &terminal
->proxy
.pty
, NULL
,
569 SYSERROR("Failed to open proxy terminal");
573 ret
= ttyname_r(terminal
->proxy
.pty
, terminal
->proxy
.name
,
574 sizeof(terminal
->proxy
.name
));
576 SYSERROR("Failed to retrieve name of proxy terminal pty");
580 ret
= fd_cloexec(terminal
->proxy
.ptx
, true);
582 SYSERROR("Failed to set FD_CLOEXEC flag on proxy terminal ptx");
586 ret
= fd_cloexec(terminal
->proxy
.pty
, true);
588 SYSERROR("Failed to set FD_CLOEXEC flag on proxy terminal pty");
592 ret
= lxc_setup_tios(terminal
->proxy
.pty
, &oldtermio
);
596 ts
= lxc_terminal_signal_init(terminal
->proxy
.ptx
, terminal
->ptx
);
600 terminal
->tty_state
= ts
;
601 terminal
->peer
= terminal
->proxy
.pty
;
602 terminal
->proxy
.busy
= sockfd
;
603 ret
= lxc_terminal_mainloop_add_peer(terminal
);
607 NOTICE("Opened proxy terminal with ptx fd %d and pty fd %d",
608 terminal
->proxy
.ptx
, terminal
->proxy
.pty
);
612 lxc_terminal_peer_proxy_free(terminal
);
616 int lxc_terminal_allocate(struct lxc_conf
*conf
, int sockfd
, int *ttyreq
)
620 struct lxc_tty_info
*ttys
= &conf
->ttys
;
621 struct lxc_terminal
*terminal
= &conf
->console
;
626 ret
= lxc_terminal_peer_proxy_alloc(terminal
, sockfd
);
630 ptxfd
= terminal
->proxy
.ptx
;
635 if (*ttyreq
> ttys
->max
)
638 if (ttys
->tty
[*ttyreq
- 1].busy
>= 0)
641 /* The requested tty is available. */
646 /* Search for next available tty, fixup index tty1 => [0]. */
647 for (ttynum
= 1; ttynum
<= ttys
->max
&& ttys
->tty
[ttynum
- 1].busy
>= 0; ttynum
++) {
651 /* We didn't find any available slot for tty. */
652 if (ttynum
> ttys
->max
)
658 ttys
->tty
[ttynum
- 1].busy
= sockfd
;
659 ptxfd
= ttys
->tty
[ttynum
- 1].ptx
;
665 void lxc_terminal_free(struct lxc_conf
*conf
, int fd
)
668 struct lxc_tty_info
*ttys
= &conf
->ttys
;
669 struct lxc_terminal
*terminal
= &conf
->console
;
671 for (i
= 0; i
< ttys
->max
; i
++)
672 if (ttys
->tty
[i
].busy
== fd
)
673 ttys
->tty
[i
].busy
= -1;
675 if (terminal
->proxy
.busy
!= fd
)
678 lxc_mainloop_del_handler(terminal
->descr
, terminal
->proxy
.pty
);
679 lxc_terminal_peer_proxy_free(terminal
);
682 static int lxc_terminal_peer_default(struct lxc_terminal
*terminal
)
684 struct lxc_terminal_state
*ts
;
689 path
= terminal
->path
;
693 terminal
->peer
= lxc_unpriv(open(path
, O_RDWR
| O_CLOEXEC
));
694 if (terminal
->peer
< 0) {
695 if (!terminal
->path
) {
697 SYSDEBUG("The process does not have a controlling terminal");
701 SYSERROR("Failed to open proxy terminal \"%s\"", path
);
704 DEBUG("Using terminal \"%s\" as proxy", path
);
706 if (!isatty(terminal
->peer
)) {
707 ERROR("File descriptor for \"%s\" does not refer to a terminal", path
);
708 goto on_error_free_tios
;
711 ts
= lxc_terminal_signal_init(terminal
->peer
, terminal
->ptx
);
712 terminal
->tty_state
= ts
;
714 WARN("Failed to install signal handler");
715 goto on_error_free_tios
;
718 lxc_terminal_winsz(terminal
->peer
, terminal
->ptx
);
720 terminal
->tios
= malloc(sizeof(*terminal
->tios
));
722 goto on_error_free_tios
;
724 ret
= lxc_setup_tios(terminal
->peer
, terminal
->tios
);
726 goto on_error_close_peer
;
731 free(terminal
->tios
);
732 terminal
->tios
= NULL
;
735 close(terminal
->peer
);
743 int lxc_terminal_write_ringbuffer(struct lxc_terminal
*terminal
)
748 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
750 /* There's not log file where we can dump the ringbuffer to. */
751 if (terminal
->log_fd
< 0)
754 used
= lxc_ringbuf_used(buf
);
758 ret
= lxc_terminal_truncate_log_file(terminal
);
762 /* Write as much as we can without exceeding the limit. */
763 if (terminal
->log_size
< used
)
764 used
= terminal
->log_size
;
766 r_addr
= lxc_ringbuf_get_read_addr(buf
);
767 ret
= lxc_write_nointr(terminal
->log_fd
, r_addr
, used
);
774 void lxc_terminal_delete(struct lxc_terminal
*terminal
)
778 ret
= lxc_terminal_write_ringbuffer(terminal
);
780 WARN("Failed to write terminal log to disk");
782 if (terminal
->tios
&& terminal
->peer
>= 0) {
783 ret
= tcsetattr(terminal
->peer
, TCSAFLUSH
, terminal
->tios
);
785 SYSWARN("Failed to set old terminal settings");
787 free(terminal
->tios
);
788 terminal
->tios
= NULL
;
790 if (terminal
->peer
>= 0)
791 close(terminal
->peer
);
794 if (terminal
->ptx
>= 0)
795 close(terminal
->ptx
);
798 if (terminal
->pty
>= 0)
799 close(terminal
->pty
);
802 terminal
->pty_nr
= -1;
804 if (terminal
->log_fd
>= 0)
805 close(terminal
->log_fd
);
806 terminal
->log_fd
= -1;
810 * Note that this function needs to run before the mainloop starts. Since we
811 * register a handler for the terminal's ptxfd when we create the mainloop
812 * the terminal handler needs to see an allocated ringbuffer.
814 static int lxc_terminal_create_ringbuf(struct lxc_terminal
*terminal
)
817 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
818 uint64_t size
= terminal
->buffer_size
;
820 /* no ringbuffer previously allocated and no ringbuffer requested */
821 if (!buf
->addr
&& size
<= 0)
824 /* ringbuffer allocated but no new ringbuffer requested */
825 if (buf
->addr
&& size
<= 0) {
826 lxc_ringbuf_release(buf
);
831 TRACE("Deallocated terminal ringbuffer");
838 /* check wether the requested size for the ringbuffer has changed */
839 if (buf
->addr
&& buf
->size
!= size
) {
840 TRACE("Terminal ringbuffer size changed from %" PRIu64
841 " to %" PRIu64
" bytes. Deallocating terminal ringbuffer",
843 lxc_ringbuf_release(buf
);
846 ret
= lxc_ringbuf_create(buf
, size
);
848 ERROR("Failed to setup %" PRIu64
" byte terminal ringbuffer", size
);
852 TRACE("Allocated %" PRIu64
" byte terminal ringbuffer", size
);
857 * This is the terminal log file. Please note that the terminal log file is
858 * (implementation wise not content wise) independent of the terminal ringbuffer.
860 int lxc_terminal_create_log_file(struct lxc_terminal
*terminal
)
862 if (!terminal
->log_path
)
865 terminal
->log_fd
= lxc_unpriv(open(terminal
->log_path
, O_CLOEXEC
| O_RDWR
| O_CREAT
| O_APPEND
, 0600));
866 if (terminal
->log_fd
< 0) {
867 SYSERROR("Failed to open terminal log file \"%s\"", terminal
->log_path
);
871 DEBUG("Using \"%s\" as terminal log file", terminal
->log_path
);
875 static int lxc_terminal_map_ids(struct lxc_conf
*c
, struct lxc_terminal
*terminal
)
879 if (list_empty(&c
->id_map
))
882 if (is_empty_string(terminal
->name
) && terminal
->pty
< 0)
885 if (terminal
->pty
>= 0)
886 ret
= userns_exec_mapped_root(NULL
, terminal
->pty
, c
);
888 ret
= userns_exec_mapped_root(terminal
->name
, -EBADF
, c
);
890 return log_error(-1, "Failed to chown terminal %d(%s)", terminal
->pty
,
891 !is_empty_string(terminal
->name
) ? terminal
->name
: "(null)");
893 TRACE("Chowned terminal %d(%s)", terminal
->pty
,
894 !is_empty_string(terminal
->name
) ? terminal
->name
: "(null)");
899 static int lxc_terminal_create_foreign(struct lxc_conf
*conf
, struct lxc_terminal
*terminal
)
903 ret
= openpty(&terminal
->ptx
, &terminal
->pty
, NULL
, NULL
, NULL
);
905 SYSERROR("Failed to open terminal");
909 ret
= lxc_terminal_map_ids(conf
, terminal
);
911 SYSERROR("Failed to change ownership of terminal multiplexer device");
915 ret
= ttyname_r(terminal
->pty
, terminal
->name
, sizeof(terminal
->name
));
917 SYSERROR("Failed to retrieve name of terminal pty");
921 ret
= fd_cloexec(terminal
->ptx
, true);
923 SYSERROR("Failed to set FD_CLOEXEC flag on terminal ptx");
927 ret
= fd_cloexec(terminal
->pty
, true);
929 SYSERROR("Failed to set FD_CLOEXEC flag on terminal pty");
933 ret
= lxc_terminal_peer_default(terminal
);
935 ERROR("Failed to allocate proxy terminal");
942 lxc_terminal_delete(terminal
);
946 int lxc_devpts_terminal(int devpts_fd
, int *ret_ptx
, int *ret_pty
,
947 int *ret_pty_nr
, bool require_tiocgptpeer
)
949 __do_close
int fd_devpts
= -EBADF
, fd_ptx
= -EBADF
,
950 fd_opath_pty
= -EBADF
, fd_pty
= -EBADF
;
955 * When we aren't told what devpts instance to allocate from we assume
956 * it is the one in the caller's mount namespace.
957 * This poses a slight complication, a lot of distros will change
958 * permissions on /dev/ptmx so it can be opened by unprivileged users
959 * but will not change permissions on /dev/pts/ptmx itself. In
960 * addition, /dev/ptmx can either be a symlink, a bind-mount, or a
961 * separate device node. So we need to allow for fairly lax lookup.
964 fd_ptx
= open_at(-EBADF
, "/dev/ptmx", PROTECT_OPEN_RW
& ~O_NOFOLLOW
,
965 PROTECT_LOOKUP_ABSOLUTE_XDEV_SYMLINKS
, 0);
967 fd_ptx
= open_beneath(devpts_fd
, "ptmx", O_RDWR
| O_NOCTTY
| O_CLOEXEC
);
970 return systrace("Exceeded number of allocatable terminals");
972 return syserror("Failed to open terminal multiplexer device");
976 fd_devpts
= open_at(-EBADF
, "/dev/pts", PROTECT_OPATH_DIRECTORY
,
977 PROTECT_LOOKUP_ABSOLUTE_XDEV
, 0);
979 return syserror("Failed to open devpts instance");
981 if (!same_device(fd_devpts
, "ptmx", fd_ptx
, ""))
982 return syserror("The acquired ptmx devices don't match");
983 devpts_fd
= fd_devpts
;
986 ret
= unlockpt(fd_ptx
);
988 return syswarn_set(-ENODEV
, "Failed to unlock multiplexer device device");
990 fd_pty
= ioctl(fd_ptx
, TIOCGPTPEER
, O_RDWR
| O_NOCTTY
| O_CLOEXEC
);
994 SYSTRACE("Pure fd-based terminal allocation not possible");
997 SYSTRACE("Exceeded number of allocatable terminals");
1000 SYSWARN("Failed to allocate new pty device");
1004 /* The caller tells us that they trust the devpts instance. */
1005 if (require_tiocgptpeer
)
1006 return ret_errno(ENODEV
);
1009 ret
= ioctl(fd_ptx
, TIOCGPTN
, &pty_nr
);
1011 return syswarn_set(-ENODEV
, "Failed to retrieve name of terminal pty");
1015 * If we end up it means that TIOCGPTPEER isn't supported but
1016 * the caller told us they trust the devpts instance so we use
1017 * the pty nr to open the pty side.
1019 fd_pty
= open_at(devpts_fd
, fdstr(pty_nr
), PROTECT_OPEN_RW
,
1020 PROTECT_LOOKUP_ABSOLUTE_XDEV
, 0);
1022 return syswarn_set(-ENODEV
, "Failed to open terminal pty fd by path %d/%d",
1025 fd_opath_pty
= open_at(devpts_fd
, fdstr(pty_nr
), PROTECT_OPATH_FILE
,
1026 PROTECT_LOOKUP_ABSOLUTE_XDEV
, 0);
1027 if (fd_opath_pty
< 0)
1028 return syswarn_set(-ENODEV
, "Failed to open terminal pty fd by path %d/%d",
1031 if (!same_file_lax(fd_pty
, fd_opath_pty
))
1032 return syswarn_set(-ENODEV
, "Terminal file descriptor changed");
1035 *ret_ptx
= move_fd(fd_ptx
);
1036 *ret_pty
= move_fd(fd_pty
);
1037 *ret_pty_nr
= pty_nr
;
1041 int lxc_terminal_parent(struct lxc_conf
*conf
)
1043 struct lxc_terminal
*console
= &conf
->console
;
1046 if (!wants_console(&conf
->console
))
1049 /* Allocate console from the container's devpts. */
1050 if (conf
->pty_max
> 1)
1053 /* Allocate console for the container from the host's devpts. */
1054 ret
= lxc_devpts_terminal(-EBADF
, &console
->ptx
, &console
->pty
,
1055 &console
->pty_nr
, false);
1057 return syserror("Failed to allocate console");
1059 ret
= strnprintf(console
->name
, sizeof(console
->name
),
1060 "/dev/pts/%d", console
->pty_nr
);
1062 return syserror("Failed to create console path");
1064 return lxc_terminal_map_ids(conf
, &conf
->console
);
1067 static int lxc_terminal_create_native(const char *name
, const char *lxcpath
,
1068 struct lxc_terminal
*terminal
)
1070 __do_close
int devpts_fd
= -EBADF
;
1073 devpts_fd
= lxc_cmd_get_devpts_fd(name
, lxcpath
);
1075 return sysinfo("Failed to receive devpts fd");
1077 ret
= lxc_devpts_terminal(devpts_fd
, &terminal
->ptx
, &terminal
->pty
,
1078 &terminal
->pty_nr
, true);
1082 ret
= strnprintf(terminal
->name
, sizeof(terminal
->name
),
1083 "/dev/pts/%d", terminal
->pty_nr
);
1085 return syserror("Failed to create path");
1087 ret
= lxc_terminal_peer_default(terminal
);
1089 lxc_terminal_delete(terminal
);
1090 return syswarn_set(-ENODEV
, "Failed to allocate proxy terminal");
1096 int lxc_terminal_create(const char *name
, const char *lxcpath
,
1097 struct lxc_conf
*conf
, struct lxc_terminal
*terminal
)
1099 if (!lxc_terminal_create_native(name
, lxcpath
, terminal
))
1102 return lxc_terminal_create_foreign(conf
, terminal
);
1105 int lxc_terminal_setup(struct lxc_conf
*conf
)
1108 struct lxc_terminal
*terminal
= &conf
->console
;
1110 if (terminal
->path
&& strequal(terminal
->path
, "none"))
1111 return log_info(0, "No terminal requested");
1113 ret
= lxc_terminal_peer_default(terminal
);
1117 ret
= lxc_terminal_create_log_file(terminal
);
1121 ret
= lxc_terminal_create_ringbuf(terminal
);
1128 lxc_terminal_delete(terminal
);
1132 static bool __terminal_dup2(int duplicate
, int original
)
1136 if (!isatty(original
))
1139 ret
= dup2(duplicate
, original
);
1141 SYSERROR("Failed to dup2(%d, %d)", duplicate
, original
);
1148 int lxc_terminal_set_stdfds(int fd
)
1155 for (i
= 0; i
< 3; i
++)
1156 if (!__terminal_dup2(fd
, (int[]){STDIN_FILENO
, STDOUT_FILENO
,
1163 int lxc_terminal_stdin_cb(int fd
, uint32_t events
, void *cbdata
,
1164 struct lxc_async_descr
*descr
)
1168 struct lxc_terminal_state
*ts
= cbdata
;
1170 if (fd
!= ts
->stdinfd
)
1171 return LXC_MAINLOOP_CLOSE
;
1173 ret
= lxc_read_nointr(ts
->stdinfd
, &c
, 1);
1175 return LXC_MAINLOOP_CLOSE
;
1177 if (ts
->escape
>= 1) {
1178 /* we want to exit the terminal with Ctrl+a q */
1179 if (c
== ts
->escape
&& !ts
->saw_escape
) {
1181 return LXC_MAINLOOP_CONTINUE
;
1184 if (c
== 'q' && ts
->saw_escape
)
1185 return LXC_MAINLOOP_CLOSE
;
1190 ret
= lxc_write_nointr(ts
->ptxfd
, &c
, 1);
1192 return LXC_MAINLOOP_CLOSE
;
1194 return LXC_MAINLOOP_CONTINUE
;
1197 int lxc_terminal_ptx_cb(int fd
, uint32_t events
, void *cbdata
,
1198 struct lxc_async_descr
*descr
)
1201 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
1202 struct lxc_terminal_state
*ts
= cbdata
;
1204 if (fd
!= ts
->ptxfd
)
1205 return LXC_MAINLOOP_CLOSE
;
1207 r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
1209 return LXC_MAINLOOP_CLOSE
;
1211 w
= lxc_write_nointr(ts
->stdoutfd
, buf
, r
);
1212 if (w
<= 0 || w
!= r
)
1213 return LXC_MAINLOOP_CLOSE
;
1215 return LXC_MAINLOOP_CONTINUE
;
1218 int lxc_terminal_getfd(struct lxc_container
*c
, int *ttynum
, int *ptxfd
)
1220 return lxc_cmd_get_tty_fd(c
->name
, ttynum
, ptxfd
, c
->config_path
);
1223 int lxc_console(struct lxc_container
*c
, int ttynum
,
1224 int stdinfd
, int stdoutfd
, int stderrfd
,
1227 int ptxfd
, ret
, ttyfd
;
1228 struct lxc_async_descr descr
;
1229 struct termios oldtios
;
1230 struct lxc_terminal_state
*ts
;
1231 struct lxc_terminal terminal
= {
1236 ttyfd
= lxc_cmd_get_tty_fd(c
->name
, &ttynum
, &ptxfd
, c
->config_path
);
1242 TRACE("Process is already group leader");
1244 ts
= lxc_terminal_signal_init(stdinfd
, ptxfd
);
1249 terminal
.tty_state
= ts
;
1250 ts
->escape
= escape
;
1251 ts
->stdoutfd
= stdoutfd
;
1253 istty
= isatty(stdinfd
);
1255 lxc_terminal_winsz(stdinfd
, ptxfd
);
1256 lxc_terminal_winsz(ts
->stdinfd
, ts
->ptxfd
);
1258 INFO("File descriptor %d does not refer to a terminal", stdinfd
);
1261 ret
= lxc_mainloop_open(&descr
);
1263 ERROR("Failed to create mainloop");
1267 if (ts
->sigfd
!= -1) {
1268 ret
= lxc_mainloop_add_handler(&descr
, ts
->sigfd
,
1269 lxc_terminal_signalfd_cb
,
1270 default_cleanup_handler
,
1271 ts
, "lxc_terminal_signalfd_cb");
1273 ERROR("Failed to add signal handler to mainloop");
1274 goto close_mainloop
;
1278 ret
= lxc_mainloop_add_handler(&descr
, ts
->stdinfd
,
1279 lxc_terminal_stdin_cb
,
1280 default_cleanup_handler
,
1281 ts
, "lxc_terminal_stdin_cb");
1283 ERROR("Failed to add stdin handler");
1284 goto close_mainloop
;
1287 ret
= lxc_mainloop_add_handler(&descr
, ts
->ptxfd
,
1288 lxc_terminal_ptx_cb
,
1289 default_cleanup_handler
,
1290 ts
, "lxc_terminal_ptx_cb");
1292 ERROR("Failed to add ptx handler");
1293 goto close_mainloop
;
1296 if (ts
->escape
>= 1) {
1299 "Connected to tty %1$d\n"
1300 "Type <Ctrl+%2$c q> to exit the console, "
1301 "<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n",
1302 ttynum
, 'a' + escape
- 1);
1306 ret
= lxc_setup_tios(stdinfd
, &oldtios
);
1308 goto close_mainloop
;
1311 ret
= lxc_mainloop(&descr
, -1);
1313 ERROR("The mainloop returned an error");
1321 istty
= tcsetattr(stdinfd
, TCSAFLUSH
, &oldtios
);
1323 SYSWARN("Failed to restore terminal properties");
1327 lxc_mainloop_close(&descr
);
1330 lxc_terminal_signal_fini(&terminal
);
1339 int lxc_make_controlling_terminal(int fd
)
1345 ret
= ioctl(fd
, TIOCSCTTY
, (char *)NULL
);
1352 int lxc_terminal_prepare_login(int fd
)
1356 ret
= lxc_make_controlling_terminal(fd
);
1360 ret
= lxc_terminal_set_stdfds(fd
);
1364 if (fd
> STDERR_FILENO
)
1370 void lxc_terminal_info_init(struct lxc_terminal_info
*terminal
)
1372 terminal
->name
[0] = '\0';
1373 terminal
->ptx
= -EBADF
;
1374 terminal
->pty
= -EBADF
;
1375 terminal
->busy
= -1;
1378 void lxc_terminal_init(struct lxc_terminal
*terminal
)
1380 memset(terminal
, 0, sizeof(*terminal
));
1381 terminal
->pty_nr
= -1;
1382 terminal
->pty
= -EBADF
;
1383 terminal
->ptx
= -EBADF
;
1384 terminal
->peer
= -EBADF
;
1385 terminal
->log_fd
= -EBADF
;
1386 lxc_terminal_info_init(&terminal
->proxy
);
1389 void lxc_terminal_conf_free(struct lxc_terminal
*terminal
)
1391 free(terminal
->log_path
);
1392 free(terminal
->path
);
1393 if (terminal
->buffer_size
> 0 && terminal
->ringbuf
.addr
)
1394 lxc_ringbuf_release(&terminal
->ringbuf
);
1395 lxc_terminal_signal_fini(terminal
);