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 ((uint64_t)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
< (uint64_t)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 ((size_t)*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
)
655 *ttyreq
= (int)ttynum
;
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
)
667 struct lxc_tty_info
*ttys
= &conf
->ttys
;
668 struct lxc_terminal
*terminal
= &conf
->console
;
670 for (size_t i
= 0; i
< ttys
->max
; i
++)
671 if (ttys
->tty
[i
].busy
== fd
)
672 ttys
->tty
[i
].busy
= -1;
674 if (terminal
->proxy
.busy
!= fd
)
677 lxc_mainloop_del_handler(terminal
->descr
, terminal
->proxy
.pty
);
678 lxc_terminal_peer_proxy_free(terminal
);
681 static int lxc_terminal_peer_default(struct lxc_terminal
*terminal
)
683 struct lxc_terminal_state
*ts
;
688 path
= terminal
->path
;
692 terminal
->peer
= lxc_unpriv(open(path
, O_RDWR
| O_CLOEXEC
));
693 if (terminal
->peer
< 0) {
694 if (!terminal
->path
) {
696 SYSDEBUG("The process does not have a controlling terminal");
700 SYSERROR("Failed to open proxy terminal \"%s\"", path
);
703 DEBUG("Using terminal \"%s\" as proxy", path
);
705 if (!isatty(terminal
->peer
)) {
706 ERROR("File descriptor for \"%s\" does not refer to a terminal", path
);
707 goto on_error_free_tios
;
710 ts
= lxc_terminal_signal_init(terminal
->peer
, terminal
->ptx
);
711 terminal
->tty_state
= ts
;
713 WARN("Failed to install signal handler");
714 goto on_error_free_tios
;
717 lxc_terminal_winsz(terminal
->peer
, terminal
->ptx
);
719 terminal
->tios
= malloc(sizeof(*terminal
->tios
));
721 goto on_error_free_tios
;
723 ret
= lxc_setup_tios(terminal
->peer
, terminal
->tios
);
725 goto on_error_close_peer
;
730 free(terminal
->tios
);
731 terminal
->tios
= NULL
;
734 close(terminal
->peer
);
742 int lxc_terminal_write_ringbuffer(struct lxc_terminal
*terminal
)
747 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
749 /* There's not log file where we can dump the ringbuffer to. */
750 if (terminal
->log_fd
< 0)
753 used
= lxc_ringbuf_used(buf
);
757 ret
= lxc_terminal_truncate_log_file(terminal
);
761 /* Write as much as we can without exceeding the limit. */
762 if (terminal
->log_size
< used
)
763 used
= terminal
->log_size
;
765 r_addr
= lxc_ringbuf_get_read_addr(buf
);
766 ret
= lxc_write_nointr(terminal
->log_fd
, r_addr
, used
);
773 void lxc_terminal_delete(struct lxc_terminal
*terminal
)
777 ret
= lxc_terminal_write_ringbuffer(terminal
);
779 WARN("Failed to write terminal log to disk");
781 if (terminal
->tios
&& terminal
->peer
>= 0) {
782 ret
= tcsetattr(terminal
->peer
, TCSAFLUSH
, terminal
->tios
);
784 SYSWARN("Failed to set old terminal settings");
786 free(terminal
->tios
);
787 terminal
->tios
= NULL
;
789 if (terminal
->peer
>= 0)
790 close(terminal
->peer
);
793 if (terminal
->ptx
>= 0)
794 close(terminal
->ptx
);
797 if (terminal
->pty
>= 0)
798 close(terminal
->pty
);
801 terminal
->pty_nr
= -1;
803 if (terminal
->log_fd
>= 0)
804 close(terminal
->log_fd
);
805 terminal
->log_fd
= -1;
809 * Note that this function needs to run before the mainloop starts. Since we
810 * register a handler for the terminal's ptxfd when we create the mainloop
811 * the terminal handler needs to see an allocated ringbuffer.
813 static int lxc_terminal_create_ringbuf(struct lxc_terminal
*terminal
)
816 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
817 uint64_t size
= terminal
->buffer_size
;
819 /* no ringbuffer previously allocated and no ringbuffer requested */
820 if (!buf
->addr
&& size
<= 0)
823 /* ringbuffer allocated but no new ringbuffer requested */
824 if (buf
->addr
&& size
<= 0) {
825 lxc_ringbuf_release(buf
);
830 TRACE("Deallocated terminal ringbuffer");
837 /* check wether the requested size for the ringbuffer has changed */
838 if (buf
->addr
&& buf
->size
!= size
) {
839 TRACE("Terminal ringbuffer size changed from %" PRIu64
840 " to %" PRIu64
" bytes. Deallocating terminal ringbuffer",
842 lxc_ringbuf_release(buf
);
845 ret
= lxc_ringbuf_create(buf
, size
);
847 ERROR("Failed to setup %" PRIu64
" byte terminal ringbuffer", size
);
851 TRACE("Allocated %" PRIu64
" byte terminal ringbuffer", size
);
856 * This is the terminal log file. Please note that the terminal log file is
857 * (implementation wise not content wise) independent of the terminal ringbuffer.
859 int lxc_terminal_create_log_file(struct lxc_terminal
*terminal
)
861 if (!terminal
->log_path
)
864 terminal
->log_fd
= lxc_unpriv(open(terminal
->log_path
, O_CLOEXEC
| O_RDWR
| O_CREAT
| O_APPEND
, 0600));
865 if (terminal
->log_fd
< 0) {
866 SYSERROR("Failed to open terminal log file \"%s\"", terminal
->log_path
);
870 DEBUG("Using \"%s\" as terminal log file", terminal
->log_path
);
874 static int lxc_terminal_map_ids(struct lxc_conf
*c
, struct lxc_terminal
*terminal
)
878 if (list_empty(&c
->id_map
))
881 if (is_empty_string(terminal
->name
) && terminal
->pty
< 0)
884 if (terminal
->pty
>= 0)
885 ret
= userns_exec_mapped_root(NULL
, terminal
->pty
, c
);
887 ret
= userns_exec_mapped_root(terminal
->name
, -EBADF
, c
);
889 return log_error(-1, "Failed to chown terminal %d(%s)", terminal
->pty
,
890 !is_empty_string(terminal
->name
) ? terminal
->name
: "(null)");
892 TRACE("Chowned terminal %d(%s)", terminal
->pty
,
893 !is_empty_string(terminal
->name
) ? terminal
->name
: "(null)");
898 static int lxc_terminal_create_foreign(struct lxc_conf
*conf
, struct lxc_terminal
*terminal
)
902 ret
= openpty(&terminal
->ptx
, &terminal
->pty
, NULL
, NULL
, NULL
);
904 SYSERROR("Failed to open terminal");
908 ret
= lxc_terminal_map_ids(conf
, terminal
);
910 SYSERROR("Failed to change ownership of terminal multiplexer device");
914 ret
= ttyname_r(terminal
->pty
, terminal
->name
, sizeof(terminal
->name
));
916 SYSERROR("Failed to retrieve name of terminal pty");
920 ret
= fd_cloexec(terminal
->ptx
, true);
922 SYSERROR("Failed to set FD_CLOEXEC flag on terminal ptx");
926 ret
= fd_cloexec(terminal
->pty
, true);
928 SYSERROR("Failed to set FD_CLOEXEC flag on terminal pty");
932 ret
= lxc_terminal_peer_default(terminal
);
934 ERROR("Failed to allocate proxy terminal");
941 lxc_terminal_delete(terminal
);
945 int lxc_devpts_terminal(int devpts_fd
, int *ret_ptx
, int *ret_pty
,
946 int *ret_pty_nr
, bool require_tiocgptpeer
)
948 __do_close
int fd_devpts
= -EBADF
, fd_ptx
= -EBADF
,
949 fd_opath_pty
= -EBADF
, fd_pty
= -EBADF
;
954 * When we aren't told what devpts instance to allocate from we assume
955 * it is the one in the caller's mount namespace.
956 * This poses a slight complication, a lot of distros will change
957 * permissions on /dev/ptmx so it can be opened by unprivileged users
958 * but will not change permissions on /dev/pts/ptmx itself. In
959 * addition, /dev/ptmx can either be a symlink, a bind-mount, or a
960 * separate device node. So we need to allow for fairly lax lookup.
963 fd_ptx
= open_at(-EBADF
, "/dev/ptmx", PROTECT_OPEN_RW
& ~O_NOFOLLOW
,
964 PROTECT_LOOKUP_ABSOLUTE_XDEV_SYMLINKS
, 0);
966 fd_ptx
= open_beneath(devpts_fd
, "ptmx", O_RDWR
| O_NOCTTY
| O_CLOEXEC
);
969 return systrace("Exceeded number of allocatable terminals");
971 return syserror("Failed to open terminal multiplexer device");
975 fd_devpts
= open_at(-EBADF
, "/dev/pts", PROTECT_OPATH_DIRECTORY
,
976 PROTECT_LOOKUP_ABSOLUTE_XDEV
, 0);
978 return syserror("Failed to open devpts instance");
980 if (!same_device(fd_devpts
, "ptmx", fd_ptx
, ""))
981 return syserror("The acquired ptmx devices don't match");
982 devpts_fd
= fd_devpts
;
985 ret
= unlockpt(fd_ptx
);
987 return syswarn_set(-ENODEV
, "Failed to unlock multiplexer device device");
989 fd_pty
= ioctl(fd_ptx
, TIOCGPTPEER
, O_RDWR
| O_NOCTTY
| O_CLOEXEC
);
993 SYSTRACE("Pure fd-based terminal allocation not possible");
996 SYSTRACE("Exceeded number of allocatable terminals");
999 SYSWARN("Failed to allocate new pty device");
1003 /* The caller tells us that they trust the devpts instance. */
1004 if (require_tiocgptpeer
)
1005 return ret_errno(ENODEV
);
1008 ret
= ioctl(fd_ptx
, TIOCGPTN
, &pty_nr
);
1010 return syswarn_set(-ENODEV
, "Failed to retrieve name of terminal pty");
1014 * If we end up it means that TIOCGPTPEER isn't supported but
1015 * the caller told us they trust the devpts instance so we use
1016 * the pty nr to open the pty side.
1018 fd_pty
= open_at(devpts_fd
, fdstr(pty_nr
), PROTECT_OPEN_RW
,
1019 PROTECT_LOOKUP_ABSOLUTE_XDEV
, 0);
1021 return syswarn_set(-ENODEV
, "Failed to open terminal pty fd by path %d/%d",
1024 fd_opath_pty
= open_at(devpts_fd
, fdstr(pty_nr
), PROTECT_OPATH_FILE
,
1025 PROTECT_LOOKUP_ABSOLUTE_XDEV
, 0);
1026 if (fd_opath_pty
< 0)
1027 return syswarn_set(-ENODEV
, "Failed to open terminal pty fd by path %d/%d",
1030 if (!same_file_lax(fd_pty
, fd_opath_pty
))
1031 return syswarn_set(-ENODEV
, "Terminal file descriptor changed");
1034 *ret_ptx
= move_fd(fd_ptx
);
1035 *ret_pty
= move_fd(fd_pty
);
1036 *ret_pty_nr
= pty_nr
;
1040 int lxc_terminal_parent(struct lxc_conf
*conf
)
1042 struct lxc_terminal
*console
= &conf
->console
;
1045 if (!wants_console(&conf
->console
))
1048 /* Allocate console from the container's devpts. */
1049 if (conf
->pty_max
> 1)
1052 /* Allocate console for the container from the host's devpts. */
1053 ret
= lxc_devpts_terminal(-EBADF
, &console
->ptx
, &console
->pty
,
1054 &console
->pty_nr
, false);
1056 return syserror("Failed to allocate console");
1058 ret
= strnprintf(console
->name
, sizeof(console
->name
),
1059 "/dev/pts/%d", console
->pty_nr
);
1061 return syserror("Failed to create console path");
1063 return lxc_terminal_map_ids(conf
, &conf
->console
);
1066 static int lxc_terminal_create_native(const char *name
, const char *lxcpath
,
1067 struct lxc_terminal
*terminal
)
1069 __do_close
int devpts_fd
= -EBADF
;
1072 devpts_fd
= lxc_cmd_get_devpts_fd(name
, lxcpath
);
1074 return sysinfo("Failed to receive devpts fd");
1076 ret
= lxc_devpts_terminal(devpts_fd
, &terminal
->ptx
, &terminal
->pty
,
1077 &terminal
->pty_nr
, true);
1081 ret
= strnprintf(terminal
->name
, sizeof(terminal
->name
),
1082 "/dev/pts/%d", terminal
->pty_nr
);
1084 return syserror("Failed to create path");
1086 ret
= lxc_terminal_peer_default(terminal
);
1088 lxc_terminal_delete(terminal
);
1089 return syswarn_set(-ENODEV
, "Failed to allocate proxy terminal");
1095 int lxc_terminal_create(const char *name
, const char *lxcpath
,
1096 struct lxc_conf
*conf
, struct lxc_terminal
*terminal
)
1098 if (!lxc_terminal_create_native(name
, lxcpath
, terminal
))
1101 return lxc_terminal_create_foreign(conf
, terminal
);
1104 int lxc_terminal_setup(struct lxc_conf
*conf
)
1107 struct lxc_terminal
*terminal
= &conf
->console
;
1109 if (terminal
->path
&& strequal(terminal
->path
, "none"))
1110 return log_info(0, "No terminal requested");
1112 ret
= lxc_terminal_peer_default(terminal
);
1116 ret
= lxc_terminal_create_log_file(terminal
);
1120 ret
= lxc_terminal_create_ringbuf(terminal
);
1127 lxc_terminal_delete(terminal
);
1131 static bool __terminal_dup2(int duplicate
, int original
)
1135 if (!isatty(original
))
1138 ret
= dup2(duplicate
, original
);
1140 SYSERROR("Failed to dup2(%d, %d)", duplicate
, original
);
1147 int lxc_terminal_set_stdfds(int fd
)
1154 for (i
= 0; i
< 3; i
++)
1155 if (!__terminal_dup2(fd
, (int[]){STDIN_FILENO
, STDOUT_FILENO
,
1162 int lxc_terminal_stdin_cb(int fd
, uint32_t events
, void *cbdata
,
1163 struct lxc_async_descr
*descr
)
1167 struct lxc_terminal_state
*ts
= cbdata
;
1169 if (fd
!= ts
->stdinfd
)
1170 return LXC_MAINLOOP_CLOSE
;
1172 ret
= lxc_read_nointr(ts
->stdinfd
, &c
, 1);
1174 return LXC_MAINLOOP_CLOSE
;
1176 if (ts
->escape
>= 1) {
1177 /* we want to exit the terminal with Ctrl+a q */
1178 if (c
== ts
->escape
&& !ts
->saw_escape
) {
1180 return LXC_MAINLOOP_CONTINUE
;
1183 if (c
== 'q' && ts
->saw_escape
)
1184 return LXC_MAINLOOP_CLOSE
;
1189 ret
= lxc_write_nointr(ts
->ptxfd
, &c
, 1);
1191 return LXC_MAINLOOP_CLOSE
;
1193 return LXC_MAINLOOP_CONTINUE
;
1196 int lxc_terminal_ptx_cb(int fd
, uint32_t events
, void *cbdata
,
1197 struct lxc_async_descr
*descr
)
1200 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
1201 struct lxc_terminal_state
*ts
= cbdata
;
1203 if (fd
!= ts
->ptxfd
)
1204 return LXC_MAINLOOP_CLOSE
;
1206 r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
1208 return LXC_MAINLOOP_CLOSE
;
1210 w
= lxc_write_nointr(ts
->stdoutfd
, buf
, r
);
1211 if (w
<= 0 || w
!= r
)
1212 return LXC_MAINLOOP_CLOSE
;
1214 return LXC_MAINLOOP_CONTINUE
;
1217 int lxc_terminal_getfd(struct lxc_container
*c
, int *ttynum
, int *ptxfd
)
1219 return lxc_cmd_get_tty_fd(c
->name
, ttynum
, ptxfd
, c
->config_path
);
1222 int lxc_console(struct lxc_container
*c
, int ttynum
,
1223 int stdinfd
, int stdoutfd
, int stderrfd
,
1226 int ptxfd
, ret
, ttyfd
;
1227 struct lxc_async_descr descr
;
1228 struct termios oldtios
;
1229 struct lxc_terminal_state
*ts
;
1230 struct lxc_terminal terminal
= {
1235 ttyfd
= lxc_cmd_get_tty_fd(c
->name
, &ttynum
, &ptxfd
, c
->config_path
);
1241 TRACE("Process is already group leader");
1243 ts
= lxc_terminal_signal_init(stdinfd
, ptxfd
);
1248 terminal
.tty_state
= ts
;
1249 ts
->escape
= escape
;
1250 ts
->stdoutfd
= stdoutfd
;
1252 istty
= isatty(stdinfd
);
1254 lxc_terminal_winsz(stdinfd
, ptxfd
);
1255 lxc_terminal_winsz(ts
->stdinfd
, ts
->ptxfd
);
1257 INFO("File descriptor %d does not refer to a terminal", stdinfd
);
1260 ret
= lxc_mainloop_open(&descr
);
1262 ERROR("Failed to create mainloop");
1266 if (ts
->sigfd
!= -1) {
1267 ret
= lxc_mainloop_add_handler(&descr
, ts
->sigfd
,
1268 lxc_terminal_signalfd_cb
,
1269 default_cleanup_handler
,
1270 ts
, "lxc_terminal_signalfd_cb");
1272 ERROR("Failed to add signal handler to mainloop");
1273 goto close_mainloop
;
1277 ret
= lxc_mainloop_add_handler(&descr
, ts
->stdinfd
,
1278 lxc_terminal_stdin_cb
,
1279 default_cleanup_handler
,
1280 ts
, "lxc_terminal_stdin_cb");
1282 ERROR("Failed to add stdin handler");
1283 goto close_mainloop
;
1286 ret
= lxc_mainloop_add_handler(&descr
, ts
->ptxfd
,
1287 lxc_terminal_ptx_cb
,
1288 default_cleanup_handler
,
1289 ts
, "lxc_terminal_ptx_cb");
1291 ERROR("Failed to add ptx handler");
1292 goto close_mainloop
;
1295 if (ts
->escape
>= 1) {
1298 "Connected to tty %1$d\n"
1299 "Type <Ctrl+%2$c q> to exit the console, "
1300 "<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n",
1301 ttynum
, 'a' + escape
- 1);
1305 ret
= lxc_setup_tios(stdinfd
, &oldtios
);
1307 goto close_mainloop
;
1310 ret
= lxc_mainloop(&descr
, -1);
1312 ERROR("The mainloop returned an error");
1320 istty
= tcsetattr(stdinfd
, TCSAFLUSH
, &oldtios
);
1322 SYSWARN("Failed to restore terminal properties");
1326 lxc_mainloop_close(&descr
);
1329 lxc_terminal_signal_fini(&terminal
);
1338 int lxc_make_controlling_terminal(int fd
)
1344 ret
= ioctl(fd
, TIOCSCTTY
, (char *)NULL
);
1351 int lxc_terminal_prepare_login(int fd
)
1355 ret
= lxc_make_controlling_terminal(fd
);
1359 ret
= lxc_terminal_set_stdfds(fd
);
1363 if (fd
> STDERR_FILENO
)
1369 void lxc_terminal_info_init(struct lxc_terminal_info
*terminal
)
1371 terminal
->name
[0] = '\0';
1372 terminal
->ptx
= -EBADF
;
1373 terminal
->pty
= -EBADF
;
1374 terminal
->busy
= -1;
1377 void lxc_terminal_init(struct lxc_terminal
*terminal
)
1379 memset(terminal
, 0, sizeof(*terminal
));
1380 terminal
->pty_nr
= -1;
1381 terminal
->pty
= -EBADF
;
1382 terminal
->ptx
= -EBADF
;
1383 terminal
->peer
= -EBADF
;
1384 terminal
->log_fd
= -EBADF
;
1385 lxc_terminal_info_init(&terminal
->proxy
);
1388 void lxc_terminal_conf_free(struct lxc_terminal
*terminal
)
1390 free(terminal
->log_path
);
1391 free(terminal
->path
);
1392 if (terminal
->buffer_size
> 0 && terminal
->ringbuf
.addr
)
1393 lxc_ringbuf_release(&terminal
->ringbuf
);
1394 lxc_terminal_signal_fini(terminal
);