]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/terminal.c
terminal: fix integer comparisons
[mirror_lxc.git] / src / lxc / terminal.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef _GNU_SOURCE
4 #define _GNU_SOURCE 1
5 #endif
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <lxc/lxccontainer.h>
9 #include <pthread.h>
10 #include <signal.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <sys/epoll.h>
14 #include <sys/types.h>
15 #include <termios.h>
16 #include <unistd.h>
17
18 #include "af_unix.h"
19 #include "caps.h"
20 #include "commands.h"
21 #include "conf.h"
22 #include "config.h"
23 #include "log.h"
24 #include "lxclock.h"
25 #include "mainloop.h"
26 #include "memory_utils.h"
27 #include "start.h"
28 #include "syscall_wrappers.h"
29 #include "terminal.h"
30 #include "utils.h"
31
32 #if HAVE_OPENPTY
33 #include <pty.h>
34 #else
35 #include "openpty.h"
36 #endif
37
38 #define LXC_TERMINAL_BUFFER_SIZE 1024
39
40 lxc_log_define(terminal, lxc);
41
42 void lxc_terminal_winsz(int srcfd, int dstfd)
43 {
44 int ret;
45 struct winsize wsz;
46
47 if (!isatty(srcfd))
48 return;
49
50 ret = ioctl(srcfd, TIOCGWINSZ, &wsz);
51 if (ret < 0) {
52 WARN("Failed to get window size");
53 return;
54 }
55
56 ret = ioctl(dstfd, TIOCSWINSZ, &wsz);
57 if (ret < 0)
58 WARN("Failed to set window size");
59 else
60 DEBUG("Set window size to %d columns and %d rows", wsz.ws_col,
61 wsz.ws_row);
62
63 return;
64 }
65
66 static void lxc_terminal_winch(struct lxc_terminal_state *ts)
67 {
68 lxc_terminal_winsz(ts->stdinfd, ts->ptxfd);
69 }
70
71 int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
72 struct lxc_async_descr *descr)
73 {
74 ssize_t ret;
75 struct signalfd_siginfo siginfo;
76 struct lxc_terminal_state *ts = cbdata;
77
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;
82 }
83
84 if (siginfo.ssi_signo == SIGTERM) {
85 DEBUG("Received SIGTERM. Detaching from the terminal");
86 return LXC_MAINLOOP_CLOSE;
87 }
88
89 if (siginfo.ssi_signo == SIGWINCH)
90 lxc_terminal_winch(ts);
91
92 return LXC_MAINLOOP_CONTINUE;
93 }
94
95 struct lxc_terminal_state *lxc_terminal_signal_init(int srcfd, int dstfd)
96 {
97 __do_close int signal_fd = -EBADF;
98 __do_free struct lxc_terminal_state *ts = NULL;
99 int ret;
100 sigset_t mask;
101
102 ts = malloc(sizeof(*ts));
103 if (!ts)
104 return NULL;
105
106 memset(ts, 0, sizeof(*ts));
107 ts->stdinfd = srcfd;
108 ts->ptxfd = dstfd;
109 ts->sigfd = -1;
110
111 ret = sigemptyset(&mask);
112 if (ret < 0) {
113 SYSERROR("Failed to initialize an empty signal set");
114 return NULL;
115 }
116
117 if (isatty(srcfd)) {
118 ret = sigaddset(&mask, SIGWINCH);
119 if (ret < 0)
120 SYSNOTICE("Failed to add SIGWINCH to signal set");
121 } else {
122 INFO("fd %d does not refer to a tty device", srcfd);
123 }
124
125 /* Exit the mainloop cleanly on SIGTERM. */
126 ret = sigaddset(&mask, SIGTERM);
127 if (ret < 0) {
128 SYSERROR("Failed to add SIGWINCH to signal set");
129 return NULL;
130 }
131
132 ret = pthread_sigmask(SIG_BLOCK, &mask, &ts->oldmask);
133 if (ret < 0) {
134 WARN("Failed to block signals");
135 return NULL;
136 }
137
138 signal_fd = signalfd(-1, &mask, SFD_CLOEXEC);
139 if (signal_fd < 0) {
140 WARN("Failed to create signal fd");
141 (void)pthread_sigmask(SIG_SETMASK, &ts->oldmask, NULL);
142 return NULL;
143 }
144 ts->sigfd = move_fd(signal_fd);
145 TRACE("Created signal fd %d", ts->sigfd);
146
147 return move_ptr(ts);
148 }
149
150 int lxc_terminal_signal_sigmask_safe_blocked(struct lxc_terminal *terminal)
151 {
152 struct lxc_terminal_state *state = terminal->tty_state;
153
154 if (!state)
155 return 0;
156
157 return pthread_sigmask(SIG_SETMASK, &state->oldmask, NULL);
158 }
159
160 /**
161 * lxc_terminal_signal_fini: uninstall signal handler
162 *
163 * @terminal: terminal instance
164 *
165 * Restore the saved signal handler that was in effect at the time
166 * lxc_terminal_signal_init() was called.
167 */
168 static void lxc_terminal_signal_fini(struct lxc_terminal *terminal)
169 {
170 struct lxc_terminal_state *state = terminal->tty_state;
171
172 if (!terminal->tty_state)
173 return;
174
175 state = terminal->tty_state;
176 if (state->sigfd >= 0) {
177 close(state->sigfd);
178
179 if (pthread_sigmask(SIG_SETMASK, &state->oldmask, NULL) < 0)
180 SYSWARN("Failed to restore signal mask");
181 }
182
183 free(terminal->tty_state);
184 terminal->tty_state = NULL;
185 }
186
187 static int lxc_terminal_truncate_log_file(struct lxc_terminal *terminal)
188 {
189 /* be very certain things are kosher */
190 if (!terminal->log_path || terminal->log_fd < 0)
191 return -EBADF;
192
193 return lxc_unpriv(ftruncate(terminal->log_fd, 0));
194 }
195
196 static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal)
197 {
198 __do_free char *tmp = NULL;
199 int ret;
200 size_t len;
201
202 if (!terminal->log_path || terminal->log_rotate == 0)
203 return -EOPNOTSUPP;
204
205 /* be very certain things are kosher */
206 if (terminal->log_fd < 0)
207 return -EBADF;
208
209 len = strlen(terminal->log_path) + sizeof(".1");
210 tmp = must_realloc(NULL, len);
211
212 ret = strnprintf(tmp, len, "%s.1", terminal->log_path);
213 if (ret < 0)
214 return -EFBIG;
215
216 close(terminal->log_fd);
217 terminal->log_fd = -1;
218 ret = lxc_unpriv(rename(terminal->log_path, tmp));
219 if (ret < 0)
220 return ret;
221
222 return lxc_terminal_create_log_file(terminal);
223 }
224
225 static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf,
226 int bytes_read)
227 {
228 int ret;
229 struct stat st;
230 int64_t space_left = -1;
231
232 if (terminal->log_fd < 0)
233 return 0;
234
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
237 * be rotated or not.
238 */
239 if (terminal->log_size <= 0)
240 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
241
242 /* Get current size of the log file. */
243 ret = fstat(terminal->log_fd, &st);
244 if (ret < 0) {
245 SYSERROR("Failed to stat the terminal log file descriptor");
246 return -1;
247 }
248
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.
255 */
256 if (terminal->log_rotate > 0 || terminal->log_size > 0)
257 return -EINVAL;
258
259 /* I mean, sure log wherever you want to. */
260 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
261 }
262
263 space_left = terminal->log_size - st.st_size;
264
265 /* User doesn't want to rotate the log file and there's no more space
266 * left so simply truncate it.
267 */
268 if (space_left <= 0 && terminal->log_rotate <= 0) {
269 ret = lxc_terminal_truncate_log_file(terminal);
270 if (ret < 0)
271 return ret;
272
273 if ((uint64_t)bytes_read <= terminal->log_size)
274 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
275
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);
278 }
279
280 /* There's enough space left. */
281 if (bytes_read <= space_left)
282 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
283
284 /* There's not enough space left but at least write as much as we can
285 * into the old log file.
286 */
287 ret = lxc_write_nointr(terminal->log_fd, buf, space_left);
288 if (ret < 0)
289 return -1;
290
291 /* Calculate how many bytes we still need to write. */
292 bytes_read -= space_left;
293
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.
296 */
297 if (terminal->log_rotate > 0)
298 ret = lxc_terminal_rotate_log_file(terminal);
299 else
300 ret = lxc_terminal_truncate_log_file(terminal);
301 if (ret < 0)
302 return ret;
303
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.
314 */
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);
317 if (ret < 0)
318 return -1;
319 bytes_read -= ret;
320 return bytes_read;
321 }
322
323 /* Yay, we made it. */
324 ret = lxc_write_nointr(terminal->log_fd, buf, bytes_read);
325 if (ret < 0)
326 return -1;
327 bytes_read -= ret;
328 return bytes_read;
329 }
330
331 static int lxc_terminal_ptx_io(struct lxc_terminal *terminal)
332 {
333 char buf[LXC_TERMINAL_BUFFER_SIZE];
334 int r, w, w_log, w_rbuf;
335
336 w = r = lxc_read_nointr(terminal->ptx, buf, sizeof(buf));
337 if (r <= 0)
338 return -1;
339
340 w_rbuf = w_log = 0;
341 /* write to peer first */
342 if (terminal->peer >= 0)
343 w = lxc_write_nointr(terminal->peer, buf, r);
344
345 /* write to terminal ringbuffer */
346 if (terminal->buffer_size > 0)
347 w_rbuf = lxc_ringbuf_write(&terminal->ringbuf, buf, r);
348
349 /* write to terminal log */
350 if (terminal->log_fd >= 0)
351 w_log = lxc_terminal_write_log_file(terminal, buf, r);
352
353 if (w != r)
354 WARN("Short write on terminal r:%d != w:%d", r, w);
355
356 if (w_rbuf < 0) {
357 errno = -w_rbuf;
358 SYSTRACE("Failed to write %d bytes to terminal ringbuffer", r);
359 }
360
361 if (w_log < 0)
362 TRACE("Failed to write %d bytes to terminal log", r);
363
364 return 0;
365 }
366
367 static int lxc_terminal_peer_io(struct lxc_terminal *terminal)
368 {
369 char buf[LXC_TERMINAL_BUFFER_SIZE];
370 int r, w;
371
372 w = r = lxc_read_nointr(terminal->peer, buf, sizeof(buf));
373 if (r <= 0)
374 return -1;
375
376 w = lxc_write_nointr(terminal->ptx, buf, r);
377 if (w != r)
378 WARN("Short write on terminal r:%d != w:%d", r, w);
379
380 return 0;
381 }
382
383 static int lxc_terminal_ptx_io_handler(int fd, uint32_t events, void *data,
384 struct lxc_async_descr *descr)
385 {
386 struct lxc_terminal *terminal = data;
387 int ret;
388
389 ret = lxc_terminal_ptx_io(data);
390 if (ret < 0)
391 return log_info(LXC_MAINLOOP_CLOSE,
392 "Terminal client on fd %d has exited",
393 terminal->ptx);
394
395 return LXC_MAINLOOP_CONTINUE;
396 }
397
398 static int lxc_terminal_peer_io_handler(int fd, uint32_t events, void *data,
399 struct lxc_async_descr *descr)
400 {
401 struct lxc_terminal *terminal = data;
402 int ret;
403
404 ret = lxc_terminal_peer_io(data);
405 if (ret < 0)
406 return log_info(LXC_MAINLOOP_CLOSE,
407 "Terminal client on fd %d has exited",
408 terminal->peer);
409
410 return LXC_MAINLOOP_CONTINUE;
411 }
412
413 static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal)
414 {
415 int ret;
416
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");
422 if (ret < 0) {
423 WARN("Failed to add terminal peer handler to mainloop");
424 return -1;
425 }
426 }
427
428 if (!terminal->tty_state || terminal->tty_state->sigfd < 0)
429 return 0;
430
431 ret = lxc_mainloop_add_handler(terminal->descr,
432 terminal->tty_state->sigfd,
433 lxc_terminal_signalfd_cb,
434 default_cleanup_handler,
435 terminal->tty_state,
436 "lxc_terminal_signalfd_cb");
437 if (ret < 0) {
438 WARN("Failed to add signal handler to mainloop");
439 return -1;
440 }
441
442 return 0;
443 }
444
445 int lxc_terminal_mainloop_add(struct lxc_async_descr *descr,
446 struct lxc_terminal *terminal)
447 {
448 int ret;
449
450 if (terminal->ptx < 0) {
451 INFO("Terminal is not initialized");
452 return 0;
453 }
454
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");
459 if (ret < 0) {
460 ERROR("Failed to add handler for terminal ptx fd %d to mainloop", terminal->ptx);
461 return -1;
462 }
463
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().
466 */
467 terminal->descr = descr;
468
469 return lxc_terminal_mainloop_add_peer(terminal);
470 }
471
472 int lxc_setup_tios(int fd, struct termios *oldtios)
473 {
474 int ret;
475 struct termios newtios;
476
477 if (!isatty(fd)) {
478 ERROR("File descriptor %d does not refer to a terminal", fd);
479 return -1;
480 }
481
482 /* Get current termios. */
483 ret = tcgetattr(fd, oldtios);
484 if (ret < 0) {
485 SYSERROR("Failed to get current terminal settings");
486 return -1;
487 }
488
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.
493 */
494 signal (SIGTTIN, SIG_IGN);
495 signal (SIGTTOU, SIG_IGN);
496
497 newtios = *oldtios;
498
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);
502 #ifdef IUCLC
503 newtios.c_iflag &= ~IUCLC;
504 #endif
505 newtios.c_lflag &= ~(TOSTOP | ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
506 #ifdef IEXTEN
507 newtios.c_lflag &= ~IEXTEN;
508 #endif
509 newtios.c_oflag |= ONLCR;
510 newtios.c_oflag |= OPOST;
511 newtios.c_cc[VMIN] = 1;
512 newtios.c_cc[VTIME] = 0;
513
514 /* Set new attributes. */
515 ret = tcsetattr(fd, TCSAFLUSH, &newtios);
516 if (ret < 0) {
517 ERROR("Failed to set new terminal settings");
518 return -1;
519 }
520
521 return 0;
522 }
523
524 static void lxc_terminal_peer_proxy_free(struct lxc_terminal *terminal)
525 {
526 lxc_terminal_signal_fini(terminal);
527
528 close(terminal->proxy.ptx);
529 terminal->proxy.ptx = -1;
530
531 close(terminal->proxy.pty);
532 terminal->proxy.pty = -1;
533
534 terminal->proxy.busy = -1;
535
536 terminal->proxy.name[0] = '\0';
537
538 terminal->peer = -1;
539 }
540
541 static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal *terminal,
542 int sockfd)
543 {
544 int ret;
545 struct termios oldtermio;
546 struct lxc_terminal_state *ts;
547
548 if (terminal->ptx < 0) {
549 ERROR("Terminal not set up");
550 return -1;
551 }
552
553 if (terminal->proxy.busy != -1 || terminal->peer != -1) {
554 NOTICE("Terminal already in use");
555 return -1;
556 }
557
558 if (terminal->tty_state) {
559 ERROR("Terminal has already been initialized");
560 return -1;
561 }
562
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.
565 */
566 ret = openpty(&terminal->proxy.ptx, &terminal->proxy.pty, NULL,
567 NULL, NULL);
568 if (ret < 0) {
569 SYSERROR("Failed to open proxy terminal");
570 return -1;
571 }
572
573 ret = ttyname_r(terminal->proxy.pty, terminal->proxy.name,
574 sizeof(terminal->proxy.name));
575 if (ret < 0) {
576 SYSERROR("Failed to retrieve name of proxy terminal pty");
577 goto on_error;
578 }
579
580 ret = fd_cloexec(terminal->proxy.ptx, true);
581 if (ret < 0) {
582 SYSERROR("Failed to set FD_CLOEXEC flag on proxy terminal ptx");
583 goto on_error;
584 }
585
586 ret = fd_cloexec(terminal->proxy.pty, true);
587 if (ret < 0) {
588 SYSERROR("Failed to set FD_CLOEXEC flag on proxy terminal pty");
589 goto on_error;
590 }
591
592 ret = lxc_setup_tios(terminal->proxy.pty, &oldtermio);
593 if (ret < 0)
594 goto on_error;
595
596 ts = lxc_terminal_signal_init(terminal->proxy.ptx, terminal->ptx);
597 if (!ts)
598 goto on_error;
599
600 terminal->tty_state = ts;
601 terminal->peer = terminal->proxy.pty;
602 terminal->proxy.busy = sockfd;
603 ret = lxc_terminal_mainloop_add_peer(terminal);
604 if (ret < 0)
605 goto on_error;
606
607 NOTICE("Opened proxy terminal with ptx fd %d and pty fd %d",
608 terminal->proxy.ptx, terminal->proxy.pty);
609 return 0;
610
611 on_error:
612 lxc_terminal_peer_proxy_free(terminal);
613 return -1;
614 }
615
616 int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
617 {
618 size_t ttynum;
619 int ptxfd = -1;
620 struct lxc_tty_info *ttys = &conf->ttys;
621 struct lxc_terminal *terminal = &conf->console;
622
623 if (*ttyreq == 0) {
624 int ret;
625
626 ret = lxc_terminal_peer_proxy_alloc(terminal, sockfd);
627 if (ret < 0)
628 goto out;
629
630 ptxfd = terminal->proxy.ptx;
631 goto out;
632 }
633
634 if (*ttyreq > 0) {
635 if ((size_t)*ttyreq > ttys->max)
636 goto out;
637
638 if (ttys->tty[*ttyreq - 1].busy >= 0)
639 goto out;
640
641 /* The requested tty is available. */
642 ttynum = *ttyreq;
643 goto out_tty;
644 }
645
646 /* Search for next available tty, fixup index tty1 => [0]. */
647 for (ttynum = 1; ttynum <= ttys->max && ttys->tty[ttynum - 1].busy >= 0; ttynum++) {
648 ;
649 }
650
651 /* We didn't find any available slot for tty. */
652 if (ttynum > ttys->max)
653 goto out;
654
655 *ttyreq = (int)ttynum;
656
657 out_tty:
658 ttys->tty[ttynum - 1].busy = sockfd;
659 ptxfd = ttys->tty[ttynum - 1].ptx;
660
661 out:
662 return ptxfd;
663 }
664
665 void lxc_terminal_free(struct lxc_conf *conf, int fd)
666 {
667 struct lxc_tty_info *ttys = &conf->ttys;
668 struct lxc_terminal *terminal = &conf->console;
669
670 for (size_t i = 0; i < ttys->max; i++)
671 if (ttys->tty[i].busy == fd)
672 ttys->tty[i].busy = -1;
673
674 if (terminal->proxy.busy != fd)
675 return;
676
677 lxc_mainloop_del_handler(terminal->descr, terminal->proxy.pty);
678 lxc_terminal_peer_proxy_free(terminal);
679 }
680
681 static int lxc_terminal_peer_default(struct lxc_terminal *terminal)
682 {
683 struct lxc_terminal_state *ts;
684 const char *path;
685 int ret = 0;
686
687 if (terminal->path)
688 path = terminal->path;
689 else
690 path = "/dev/tty";
691
692 terminal->peer = lxc_unpriv(open(path, O_RDWR | O_CLOEXEC));
693 if (terminal->peer < 0) {
694 if (!terminal->path) {
695 errno = ENODEV;
696 SYSDEBUG("The process does not have a controlling terminal");
697 goto on_succes;
698 }
699
700 SYSERROR("Failed to open proxy terminal \"%s\"", path);
701 return -ENOTTY;
702 }
703 DEBUG("Using terminal \"%s\" as proxy", path);
704
705 if (!isatty(terminal->peer)) {
706 ERROR("File descriptor for \"%s\" does not refer to a terminal", path);
707 goto on_error_free_tios;
708 }
709
710 ts = lxc_terminal_signal_init(terminal->peer, terminal->ptx);
711 terminal->tty_state = ts;
712 if (!ts) {
713 WARN("Failed to install signal handler");
714 goto on_error_free_tios;
715 }
716
717 lxc_terminal_winsz(terminal->peer, terminal->ptx);
718
719 terminal->tios = malloc(sizeof(*terminal->tios));
720 if (!terminal->tios)
721 goto on_error_free_tios;
722
723 ret = lxc_setup_tios(terminal->peer, terminal->tios);
724 if (ret < 0)
725 goto on_error_close_peer;
726 else
727 goto on_succes;
728
729 on_error_free_tios:
730 free(terminal->tios);
731 terminal->tios = NULL;
732
733 on_error_close_peer:
734 close(terminal->peer);
735 terminal->peer = -1;
736 ret = -ENOTTY;
737
738 on_succes:
739 return ret;
740 }
741
742 int lxc_terminal_write_ringbuffer(struct lxc_terminal *terminal)
743 {
744 char *r_addr;
745 ssize_t ret;
746 uint64_t used;
747 struct lxc_ringbuf *buf = &terminal->ringbuf;
748
749 /* There's not log file where we can dump the ringbuffer to. */
750 if (terminal->log_fd < 0)
751 return 0;
752
753 used = lxc_ringbuf_used(buf);
754 if (used == 0)
755 return 0;
756
757 ret = lxc_terminal_truncate_log_file(terminal);
758 if (ret < 0)
759 return ret;
760
761 /* Write as much as we can without exceeding the limit. */
762 if (terminal->log_size < used)
763 used = terminal->log_size;
764
765 r_addr = lxc_ringbuf_get_read_addr(buf);
766 ret = lxc_write_nointr(terminal->log_fd, r_addr, used);
767 if (ret < 0)
768 return -EIO;
769
770 return 0;
771 }
772
773 void lxc_terminal_delete(struct lxc_terminal *terminal)
774 {
775 int ret;
776
777 ret = lxc_terminal_write_ringbuffer(terminal);
778 if (ret < 0)
779 WARN("Failed to write terminal log to disk");
780
781 if (terminal->tios && terminal->peer >= 0) {
782 ret = tcsetattr(terminal->peer, TCSAFLUSH, terminal->tios);
783 if (ret < 0)
784 SYSWARN("Failed to set old terminal settings");
785 }
786 free(terminal->tios);
787 terminal->tios = NULL;
788
789 if (terminal->peer >= 0)
790 close(terminal->peer);
791 terminal->peer = -1;
792
793 if (terminal->ptx >= 0)
794 close(terminal->ptx);
795 terminal->ptx = -1;
796
797 if (terminal->pty >= 0)
798 close(terminal->pty);
799 terminal->pty = -1;
800
801 terminal->pty_nr = -1;
802
803 if (terminal->log_fd >= 0)
804 close(terminal->log_fd);
805 terminal->log_fd = -1;
806 }
807
808 /**
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.
812 */
813 static int lxc_terminal_create_ringbuf(struct lxc_terminal *terminal)
814 {
815 int ret;
816 struct lxc_ringbuf *buf = &terminal->ringbuf;
817 uint64_t size = terminal->buffer_size;
818
819 /* no ringbuffer previously allocated and no ringbuffer requested */
820 if (!buf->addr && size <= 0)
821 return 0;
822
823 /* ringbuffer allocated but no new ringbuffer requested */
824 if (buf->addr && size <= 0) {
825 lxc_ringbuf_release(buf);
826 buf->addr = NULL;
827 buf->r_off = 0;
828 buf->w_off = 0;
829 buf->size = 0;
830 TRACE("Deallocated terminal ringbuffer");
831 return 0;
832 }
833
834 if (size <= 0)
835 return 0;
836
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",
841 buf->size, size);
842 lxc_ringbuf_release(buf);
843 }
844
845 ret = lxc_ringbuf_create(buf, size);
846 if (ret < 0) {
847 ERROR("Failed to setup %" PRIu64 " byte terminal ringbuffer", size);
848 return -1;
849 }
850
851 TRACE("Allocated %" PRIu64 " byte terminal ringbuffer", size);
852 return 0;
853 }
854
855 /**
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.
858 */
859 int lxc_terminal_create_log_file(struct lxc_terminal *terminal)
860 {
861 if (!terminal->log_path)
862 return 0;
863
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);
867 return -1;
868 }
869
870 DEBUG("Using \"%s\" as terminal log file", terminal->log_path);
871 return 0;
872 }
873
874 static int lxc_terminal_map_ids(struct lxc_conf *c, struct lxc_terminal *terminal)
875 {
876 int ret;
877
878 if (list_empty(&c->id_map))
879 return 0;
880
881 if (is_empty_string(terminal->name) && terminal->pty < 0)
882 return 0;
883
884 if (terminal->pty >= 0)
885 ret = userns_exec_mapped_root(NULL, terminal->pty, c);
886 else
887 ret = userns_exec_mapped_root(terminal->name, -EBADF, c);
888 if (ret < 0)
889 return log_error(-1, "Failed to chown terminal %d(%s)", terminal->pty,
890 !is_empty_string(terminal->name) ? terminal->name : "(null)");
891
892 TRACE("Chowned terminal %d(%s)", terminal->pty,
893 !is_empty_string(terminal->name) ? terminal->name : "(null)");
894
895 return 0;
896 }
897
898 static int lxc_terminal_create_foreign(struct lxc_conf *conf, struct lxc_terminal *terminal)
899 {
900 int ret;
901
902 ret = openpty(&terminal->ptx, &terminal->pty, NULL, NULL, NULL);
903 if (ret < 0) {
904 SYSERROR("Failed to open terminal");
905 return -1;
906 }
907
908 ret = lxc_terminal_map_ids(conf, terminal);
909 if (ret < 0) {
910 SYSERROR("Failed to change ownership of terminal multiplexer device");
911 goto err;
912 }
913
914 ret = ttyname_r(terminal->pty, terminal->name, sizeof(terminal->name));
915 if (ret < 0) {
916 SYSERROR("Failed to retrieve name of terminal pty");
917 goto err;
918 }
919
920 ret = fd_cloexec(terminal->ptx, true);
921 if (ret < 0) {
922 SYSERROR("Failed to set FD_CLOEXEC flag on terminal ptx");
923 goto err;
924 }
925
926 ret = fd_cloexec(terminal->pty, true);
927 if (ret < 0) {
928 SYSERROR("Failed to set FD_CLOEXEC flag on terminal pty");
929 goto err;
930 }
931
932 ret = lxc_terminal_peer_default(terminal);
933 if (ret < 0) {
934 ERROR("Failed to allocate proxy terminal");
935 goto err;
936 }
937
938 return 0;
939
940 err:
941 lxc_terminal_delete(terminal);
942 return -ENODEV;
943 }
944
945 int lxc_devpts_terminal(int devpts_fd, int *ret_ptx, int *ret_pty,
946 int *ret_pty_nr, bool require_tiocgptpeer)
947 {
948 __do_close int fd_devpts = -EBADF, fd_ptx = -EBADF,
949 fd_opath_pty = -EBADF, fd_pty = -EBADF;
950 int pty_nr = -1;
951 int ret;
952
953 /*
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.
961 */
962 if (devpts_fd < 0)
963 fd_ptx = open_at(-EBADF, "/dev/ptmx", PROTECT_OPEN_RW & ~O_NOFOLLOW,
964 PROTECT_LOOKUP_ABSOLUTE_XDEV_SYMLINKS, 0);
965 else
966 fd_ptx = open_beneath(devpts_fd, "ptmx", O_RDWR | O_NOCTTY | O_CLOEXEC);
967 if (fd_ptx < 0) {
968 if (errno == ENOSPC)
969 return systrace("Exceeded number of allocatable terminals");
970
971 return syserror("Failed to open terminal multiplexer device");
972 }
973
974 if (devpts_fd < 0) {
975 fd_devpts = open_at(-EBADF, "/dev/pts", PROTECT_OPATH_DIRECTORY,
976 PROTECT_LOOKUP_ABSOLUTE_XDEV, 0);
977 if (fd_devpts < 0)
978 return syserror("Failed to open devpts instance");
979
980 if (!same_device(fd_devpts, "ptmx", fd_ptx, ""))
981 return syserror("The acquired ptmx devices don't match");
982 devpts_fd = fd_devpts;
983 }
984
985 ret = unlockpt(fd_ptx);
986 if (ret < 0)
987 return syswarn_set(-ENODEV, "Failed to unlock multiplexer device device");
988
989 fd_pty = ioctl(fd_ptx, TIOCGPTPEER, O_RDWR | O_NOCTTY | O_CLOEXEC);
990 if (fd_pty < 0) {
991 switch (errno) {
992 case ENOTTY:
993 SYSTRACE("Pure fd-based terminal allocation not possible");
994 break;
995 case ENOSPC:
996 SYSTRACE("Exceeded number of allocatable terminals");
997 break;
998 default:
999 SYSWARN("Failed to allocate new pty device");
1000 return -errno;
1001 }
1002
1003 /* The caller tells us that they trust the devpts instance. */
1004 if (require_tiocgptpeer)
1005 return ret_errno(ENODEV);
1006 }
1007
1008 ret = ioctl(fd_ptx, TIOCGPTN, &pty_nr);
1009 if (ret)
1010 return syswarn_set(-ENODEV, "Failed to retrieve name of terminal pty");
1011
1012 if (fd_pty < 0) {
1013 /*
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.
1017 */
1018 fd_pty = open_at(devpts_fd, fdstr(pty_nr), PROTECT_OPEN_RW,
1019 PROTECT_LOOKUP_ABSOLUTE_XDEV, 0);
1020 if (fd_pty < 0)
1021 return syswarn_set(-ENODEV, "Failed to open terminal pty fd by path %d/%d",
1022 devpts_fd, pty_nr);
1023 } else {
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",
1028 devpts_fd, pty_nr);
1029
1030 if (!same_file_lax(fd_pty, fd_opath_pty))
1031 return syswarn_set(-ENODEV, "Terminal file descriptor changed");
1032 }
1033
1034 *ret_ptx = move_fd(fd_ptx);
1035 *ret_pty = move_fd(fd_pty);
1036 *ret_pty_nr = pty_nr;
1037 return 0;
1038 }
1039
1040 int lxc_terminal_parent(struct lxc_conf *conf)
1041 {
1042 struct lxc_terminal *console = &conf->console;
1043 int ret;
1044
1045 if (!wants_console(&conf->console))
1046 return 0;
1047
1048 /* Allocate console from the container's devpts. */
1049 if (conf->pty_max > 1)
1050 return 0;
1051
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);
1055 if (ret < 0)
1056 return syserror("Failed to allocate console");
1057
1058 ret = strnprintf(console->name, sizeof(console->name),
1059 "/dev/pts/%d", console->pty_nr);
1060 if (ret < 0)
1061 return syserror("Failed to create console path");
1062
1063 return lxc_terminal_map_ids(conf, &conf->console);
1064 }
1065
1066 static int lxc_terminal_create_native(const char *name, const char *lxcpath,
1067 struct lxc_terminal *terminal)
1068 {
1069 __do_close int devpts_fd = -EBADF;
1070 int ret;
1071
1072 devpts_fd = lxc_cmd_get_devpts_fd(name, lxcpath);
1073 if (devpts_fd < 0)
1074 return sysinfo("Failed to receive devpts fd");
1075
1076 ret = lxc_devpts_terminal(devpts_fd, &terminal->ptx, &terminal->pty,
1077 &terminal->pty_nr, true);
1078 if (ret < 0)
1079 return ret;
1080
1081 ret = strnprintf(terminal->name, sizeof(terminal->name),
1082 "/dev/pts/%d", terminal->pty_nr);
1083 if (ret < 0)
1084 return syserror("Failed to create path");
1085
1086 ret = lxc_terminal_peer_default(terminal);
1087 if (ret < 0) {
1088 lxc_terminal_delete(terminal);
1089 return syswarn_set(-ENODEV, "Failed to allocate proxy terminal");
1090 }
1091
1092 return 0;
1093 }
1094
1095 int lxc_terminal_create(const char *name, const char *lxcpath,
1096 struct lxc_conf *conf, struct lxc_terminal *terminal)
1097 {
1098 if (!lxc_terminal_create_native(name, lxcpath, terminal))
1099 return 0;
1100
1101 return lxc_terminal_create_foreign(conf, terminal);
1102 }
1103
1104 int lxc_terminal_setup(struct lxc_conf *conf)
1105 {
1106 int ret;
1107 struct lxc_terminal *terminal = &conf->console;
1108
1109 if (terminal->path && strequal(terminal->path, "none"))
1110 return log_info(0, "No terminal requested");
1111
1112 ret = lxc_terminal_peer_default(terminal);
1113 if (ret < 0)
1114 goto err;
1115
1116 ret = lxc_terminal_create_log_file(terminal);
1117 if (ret < 0)
1118 goto err;
1119
1120 ret = lxc_terminal_create_ringbuf(terminal);
1121 if (ret < 0)
1122 goto err;
1123
1124 return 0;
1125
1126 err:
1127 lxc_terminal_delete(terminal);
1128 return -ENODEV;
1129 }
1130
1131 static bool __terminal_dup2(int duplicate, int original)
1132 {
1133 int ret;
1134
1135 if (!isatty(original))
1136 return true;
1137
1138 ret = dup2(duplicate, original);
1139 if (ret < 0) {
1140 SYSERROR("Failed to dup2(%d, %d)", duplicate, original);
1141 return false;
1142 }
1143
1144 return true;
1145 }
1146
1147 int lxc_terminal_set_stdfds(int fd)
1148 {
1149 int i;
1150
1151 if (fd < 0)
1152 return 0;
1153
1154 for (i = 0; i < 3; i++)
1155 if (!__terminal_dup2(fd, (int[]){STDIN_FILENO, STDOUT_FILENO,
1156 STDERR_FILENO}[i]))
1157 return -1;
1158
1159 return 0;
1160 }
1161
1162 int lxc_terminal_stdin_cb(int fd, uint32_t events, void *cbdata,
1163 struct lxc_async_descr *descr)
1164 {
1165 int ret;
1166 char c;
1167 struct lxc_terminal_state *ts = cbdata;
1168
1169 if (fd != ts->stdinfd)
1170 return LXC_MAINLOOP_CLOSE;
1171
1172 ret = lxc_read_nointr(ts->stdinfd, &c, 1);
1173 if (ret <= 0)
1174 return LXC_MAINLOOP_CLOSE;
1175
1176 if (ts->escape >= 1) {
1177 /* we want to exit the terminal with Ctrl+a q */
1178 if (c == ts->escape && !ts->saw_escape) {
1179 ts->saw_escape = 1;
1180 return LXC_MAINLOOP_CONTINUE;
1181 }
1182
1183 if (c == 'q' && ts->saw_escape)
1184 return LXC_MAINLOOP_CLOSE;
1185
1186 ts->saw_escape = 0;
1187 }
1188
1189 ret = lxc_write_nointr(ts->ptxfd, &c, 1);
1190 if (ret <= 0)
1191 return LXC_MAINLOOP_CLOSE;
1192
1193 return LXC_MAINLOOP_CONTINUE;
1194 }
1195
1196 int lxc_terminal_ptx_cb(int fd, uint32_t events, void *cbdata,
1197 struct lxc_async_descr *descr)
1198 {
1199 int r, w;
1200 char buf[LXC_TERMINAL_BUFFER_SIZE];
1201 struct lxc_terminal_state *ts = cbdata;
1202
1203 if (fd != ts->ptxfd)
1204 return LXC_MAINLOOP_CLOSE;
1205
1206 r = lxc_read_nointr(fd, buf, sizeof(buf));
1207 if (r <= 0)
1208 return LXC_MAINLOOP_CLOSE;
1209
1210 w = lxc_write_nointr(ts->stdoutfd, buf, r);
1211 if (w <= 0 || w != r)
1212 return LXC_MAINLOOP_CLOSE;
1213
1214 return LXC_MAINLOOP_CONTINUE;
1215 }
1216
1217 int lxc_terminal_getfd(struct lxc_container *c, int *ttynum, int *ptxfd)
1218 {
1219 return lxc_cmd_get_tty_fd(c->name, ttynum, ptxfd, c->config_path);
1220 }
1221
1222 int lxc_console(struct lxc_container *c, int ttynum,
1223 int stdinfd, int stdoutfd, int stderrfd,
1224 int escape)
1225 {
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 = {
1231 .tty_state = NULL,
1232 };
1233 int istty = 0;
1234
1235 ttyfd = lxc_cmd_get_tty_fd(c->name, &ttynum, &ptxfd, c->config_path);
1236 if (ttyfd < 0)
1237 return -1;
1238
1239 ret = setsid();
1240 if (ret < 0)
1241 TRACE("Process is already group leader");
1242
1243 ts = lxc_terminal_signal_init(stdinfd, ptxfd);
1244 if (!ts) {
1245 ret = -1;
1246 goto close_fds;
1247 }
1248 terminal.tty_state = ts;
1249 ts->escape = escape;
1250 ts->stdoutfd = stdoutfd;
1251
1252 istty = isatty(stdinfd);
1253 if (istty) {
1254 lxc_terminal_winsz(stdinfd, ptxfd);
1255 lxc_terminal_winsz(ts->stdinfd, ts->ptxfd);
1256 } else {
1257 INFO("File descriptor %d does not refer to a terminal", stdinfd);
1258 }
1259
1260 ret = lxc_mainloop_open(&descr);
1261 if (ret) {
1262 ERROR("Failed to create mainloop");
1263 goto sigwinch_fini;
1264 }
1265
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");
1271 if (ret < 0) {
1272 ERROR("Failed to add signal handler to mainloop");
1273 goto close_mainloop;
1274 }
1275 }
1276
1277 ret = lxc_mainloop_add_handler(&descr, ts->stdinfd,
1278 lxc_terminal_stdin_cb,
1279 default_cleanup_handler,
1280 ts, "lxc_terminal_stdin_cb");
1281 if (ret < 0) {
1282 ERROR("Failed to add stdin handler");
1283 goto close_mainloop;
1284 }
1285
1286 ret = lxc_mainloop_add_handler(&descr, ts->ptxfd,
1287 lxc_terminal_ptx_cb,
1288 default_cleanup_handler,
1289 ts, "lxc_terminal_ptx_cb");
1290 if (ret < 0) {
1291 ERROR("Failed to add ptx handler");
1292 goto close_mainloop;
1293 }
1294
1295 if (ts->escape >= 1) {
1296 fprintf(stderr,
1297 "\n"
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);
1302 }
1303
1304 if (istty) {
1305 ret = lxc_setup_tios(stdinfd, &oldtios);
1306 if (ret < 0)
1307 goto close_mainloop;
1308 }
1309
1310 ret = lxc_mainloop(&descr, -1);
1311 if (ret < 0) {
1312 ERROR("The mainloop returned an error");
1313 goto restore_tios;
1314 }
1315
1316 ret = 0;
1317
1318 restore_tios:
1319 if (istty) {
1320 istty = tcsetattr(stdinfd, TCSAFLUSH, &oldtios);
1321 if (istty < 0)
1322 SYSWARN("Failed to restore terminal properties");
1323 }
1324
1325 close_mainloop:
1326 lxc_mainloop_close(&descr);
1327
1328 sigwinch_fini:
1329 lxc_terminal_signal_fini(&terminal);
1330
1331 close_fds:
1332 close(ptxfd);
1333 close(ttyfd);
1334
1335 return ret;
1336 }
1337
1338 int lxc_make_controlling_terminal(int fd)
1339 {
1340 int ret;
1341
1342 setsid();
1343
1344 ret = ioctl(fd, TIOCSCTTY, (char *)NULL);
1345 if (ret < 0)
1346 return -1;
1347
1348 return 0;
1349 }
1350
1351 int lxc_terminal_prepare_login(int fd)
1352 {
1353 int ret;
1354
1355 ret = lxc_make_controlling_terminal(fd);
1356 if (ret < 0)
1357 return -1;
1358
1359 ret = lxc_terminal_set_stdfds(fd);
1360 if (ret < 0)
1361 return -1;
1362
1363 if (fd > STDERR_FILENO)
1364 close(fd);
1365
1366 return 0;
1367 }
1368
1369 void lxc_terminal_info_init(struct lxc_terminal_info *terminal)
1370 {
1371 terminal->name[0] = '\0';
1372 terminal->ptx = -EBADF;
1373 terminal->pty = -EBADF;
1374 terminal->busy = -1;
1375 }
1376
1377 void lxc_terminal_init(struct lxc_terminal *terminal)
1378 {
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);
1386 }
1387
1388 void lxc_terminal_conf_free(struct lxc_terminal *terminal)
1389 {
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);
1395 }