]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/terminal.c
fd: only add valid fd to mainloop
[mirror_lxc.git] / src / lxc / terminal.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #ifndef _GNU_SOURCE
25 #define _GNU_SOURCE 1
26 #endif
27 #include <errno.h>
28 #include <fcntl.h>
29 #include <lxc/lxccontainer.h>
30 #include <pthread.h>
31 #include <signal.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <sys/epoll.h>
35 #include <sys/types.h>
36 #include <termios.h>
37 #include <unistd.h>
38
39 #include "af_unix.h"
40 #include "caps.h"
41 #include "commands.h"
42 #include "conf.h"
43 #include "config.h"
44 #include "log.h"
45 #include "lxclock.h"
46 #include "mainloop.h"
47 #include "memory_utils.h"
48 #include "start.h"
49 #include "syscall_wrappers.h"
50 #include "terminal.h"
51 #include "utils.h"
52
53 #if HAVE_PTY_H
54 #include <pty.h>
55 #else
56 #include <../include/openpty.h>
57 #endif
58
59 #define LXC_TERMINAL_BUFFER_SIZE 1024
60
61 lxc_log_define(terminal, lxc);
62
63 void lxc_terminal_winsz(int srcfd, int dstfd)
64 {
65 int ret;
66 struct winsize wsz;
67
68 if (!isatty(srcfd))
69 return;
70
71 ret = ioctl(srcfd, TIOCGWINSZ, &wsz);
72 if (ret < 0) {
73 WARN("Failed to get window size");
74 return;
75 }
76
77 ret = ioctl(dstfd, TIOCSWINSZ, &wsz);
78 if (ret < 0)
79 WARN("Failed to set window size");
80 else
81 DEBUG("Set window size to %d columns and %d rows", wsz.ws_col,
82 wsz.ws_row);
83
84 return;
85 }
86
87 static void lxc_terminal_winch(struct lxc_terminal_state *ts)
88 {
89 lxc_terminal_winsz(ts->stdinfd, ts->masterfd);
90 }
91
92 int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
93 struct lxc_epoll_descr *descr)
94 {
95 ssize_t ret;
96 struct signalfd_siginfo siginfo;
97 struct lxc_terminal_state *ts = cbdata;
98
99 ret = lxc_read_nointr(fd, &siginfo, sizeof(siginfo));
100 if (ret < 0 || (size_t)ret < sizeof(siginfo)) {
101 ERROR("Failed to read signal info");
102 return LXC_MAINLOOP_ERROR;
103 }
104
105 if (siginfo.ssi_signo == SIGTERM) {
106 DEBUG("Received SIGTERM. Detaching from the terminal");
107 return LXC_MAINLOOP_CLOSE;
108 }
109
110 if (siginfo.ssi_signo == SIGWINCH)
111 lxc_terminal_winch(ts);
112
113 return LXC_MAINLOOP_CONTINUE;
114 }
115
116 struct lxc_terminal_state *lxc_terminal_signal_init(int srcfd, int dstfd)
117 {
118 __do_free struct lxc_terminal_state *ts = NULL;
119 bool istty = false;
120 int ret;
121 sigset_t mask;
122
123 ts = malloc(sizeof(*ts));
124 if (!ts)
125 return NULL;
126
127 memset(ts, 0, sizeof(*ts));
128 ts->stdinfd = srcfd;
129 ts->masterfd = dstfd;
130 ts->sigfd = -1;
131
132 ret = sigemptyset(&mask);
133 if (ret < 0) {
134 SYSERROR("Failed to initialize an empty signal set");
135 goto on_error;
136 }
137
138 istty = (isatty(srcfd) == 1);
139 if (!istty) {
140 INFO("fd %d does not refer to a tty device", srcfd);
141 } else {
142 ret = sigaddset(&mask, SIGWINCH);
143 if (ret < 0)
144 SYSNOTICE("Failed to add SIGWINCH to signal set");
145 }
146
147 /* Exit the mainloop cleanly on SIGTERM. */
148 ret = sigaddset(&mask, SIGTERM);
149 if (ret < 0) {
150 SYSERROR("Failed to add SIGWINCH to signal set");
151 goto on_error;
152 }
153
154 ret = pthread_sigmask(SIG_BLOCK, &mask, &ts->oldmask);
155 if (ret < 0) {
156 WARN("Failed to block signals");
157 goto on_error;
158 }
159
160 ts->sigfd = signalfd(-1, &mask, SFD_CLOEXEC);
161 if (ts->sigfd < 0) {
162 WARN("Failed to create signal fd");
163 (void)pthread_sigmask(SIG_SETMASK, &ts->oldmask, NULL);
164 goto on_error;
165 }
166
167 DEBUG("Created signal fd %d", ts->sigfd);
168 return ts;
169
170 on_error:
171 ERROR("Failed to create signal fd");
172 if (ts->sigfd >= 0) {
173 close(ts->sigfd);
174 ts->sigfd = -1;
175 }
176
177 return ts;
178 }
179
180 void lxc_terminal_signal_fini(struct lxc_terminal *terminal)
181 {
182 struct lxc_terminal_state *state = terminal->tty_state;
183
184 if (!terminal->tty_state)
185 return;
186
187 state = terminal->tty_state;
188 if (state->sigfd >= 0) {
189 close(state->sigfd);
190
191 if (pthread_sigmask(SIG_SETMASK, &state->oldmask, NULL) < 0)
192 SYSWARN("Failed to restore signal mask");
193 }
194
195 free(terminal->tty_state);
196 terminal->tty_state = NULL;
197 }
198
199 static int lxc_terminal_truncate_log_file(struct lxc_terminal *terminal)
200 {
201 /* be very certain things are kosher */
202 if (!terminal->log_path || terminal->log_fd < 0)
203 return -EBADF;
204
205 return lxc_unpriv(ftruncate(terminal->log_fd, 0));
206 }
207
208 static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal)
209 {
210 __do_free char *tmp = NULL;
211 int ret;
212 size_t len;
213
214 if (!terminal->log_path || terminal->log_rotate == 0)
215 return -EOPNOTSUPP;
216
217 /* be very certain things are kosher */
218 if (terminal->log_fd < 0)
219 return -EBADF;
220
221 len = strlen(terminal->log_path) + sizeof(".1");
222 tmp = must_realloc(NULL, len);
223
224 ret = snprintf(tmp, len, "%s.1", terminal->log_path);
225 if (ret < 0 || (size_t)ret >= len)
226 return -EFBIG;
227
228 close(terminal->log_fd);
229 terminal->log_fd = -1;
230 ret = lxc_unpriv(rename(terminal->log_path, tmp));
231 if (ret < 0)
232 return ret;
233
234 return lxc_terminal_create_log_file(terminal);
235 }
236
237 static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf,
238 int bytes_read)
239 {
240 int ret;
241 struct stat st;
242 int64_t space_left = -1;
243
244 if (terminal->log_fd < 0)
245 return 0;
246
247 /* A log size <= 0 means that there's no limit on the size of the log
248 * file at which point we simply ignore whether the log is supposed to
249 * be rotated or not.
250 */
251 if (terminal->log_size <= 0)
252 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
253
254 /* Get current size of the log file. */
255 ret = fstat(terminal->log_fd, &st);
256 if (ret < 0) {
257 SYSERROR("Failed to stat the terminal log file descriptor");
258 return -1;
259 }
260
261 /* handle non-regular files */
262 if ((st.st_mode & S_IFMT) != S_IFREG) {
263 /* This isn't a regular file. so rotating the file seems a
264 * dangerous thing to do, size limits are also very
265 * questionable. Let's not risk anything and tell the user that
266 * he's requesting us to do weird stuff.
267 */
268 if (terminal->log_rotate > 0 || terminal->log_size > 0)
269 return -EINVAL;
270
271 /* I mean, sure log wherever you want to. */
272 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
273 }
274
275 space_left = terminal->log_size - st.st_size;
276
277 /* User doesn't want to rotate the log file and there's no more space
278 * left so simply truncate it.
279 */
280 if (space_left <= 0 && terminal->log_rotate <= 0) {
281 ret = lxc_terminal_truncate_log_file(terminal);
282 if (ret < 0)
283 return ret;
284
285 if (bytes_read <= terminal->log_size)
286 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
287
288 /* Write as much as we can into the buffer and loose the rest. */
289 return lxc_write_nointr(terminal->log_fd, buf, terminal->log_size);
290 }
291
292 /* There's enough space left. */
293 if (bytes_read <= space_left)
294 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
295
296 /* There's not enough space left but at least write as much as we can
297 * into the old log file.
298 */
299 ret = lxc_write_nointr(terminal->log_fd, buf, space_left);
300 if (ret < 0)
301 return -1;
302
303 /* Calculate how many bytes we still need to write. */
304 bytes_read -= space_left;
305
306 /* There'd be more to write but we aren't instructed to rotate the log
307 * file so simply return. There's no error on our side here.
308 */
309 if (terminal->log_rotate > 0)
310 ret = lxc_terminal_rotate_log_file(terminal);
311 else
312 ret = lxc_terminal_truncate_log_file(terminal);
313 if (ret < 0)
314 return ret;
315
316 if (terminal->log_size < bytes_read) {
317 /* Well, this is unfortunate because it means that there is more
318 * to write than the user has granted us space. There are
319 * multiple ways to handle this but let's use the simplest one:
320 * write as much as we can, tell the user that there was more
321 * stuff to write and move on.
322 * Note that this scenario shouldn't actually happen with the
323 * standard pty-based terminal that LXC allocates since it will
324 * be switched into raw mode. In raw mode only 1 byte at a time
325 * should be read and written.
326 */
327 WARN("Size of terminal log file is smaller than the bytes to write");
328 ret = lxc_write_nointr(terminal->log_fd, buf, terminal->log_size);
329 if (ret < 0)
330 return -1;
331 bytes_read -= ret;
332 return bytes_read;
333 }
334
335 /* Yay, we made it. */
336 ret = lxc_write_nointr(terminal->log_fd, buf, bytes_read);
337 if (ret < 0)
338 return -1;
339 bytes_read -= ret;
340 return bytes_read;
341 }
342
343 int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
344 struct lxc_epoll_descr *descr)
345 {
346 struct lxc_terminal *terminal = data;
347 char buf[LXC_TERMINAL_BUFFER_SIZE];
348 int r, w, w_log, w_rbuf;
349
350 w = r = lxc_read_nointr(fd, buf, sizeof(buf));
351 if (r <= 0) {
352 INFO("Terminal client on fd %d has exited", fd);
353 lxc_mainloop_del_handler(descr, fd);
354
355 if (fd == terminal->master) {
356 terminal->master = -EBADF;
357 } else if (fd == terminal->peer) {
358 lxc_terminal_signal_fini(terminal);
359 terminal->peer = -EBADF;
360 } else {
361 ERROR("Handler received unexpected file descriptor");
362 }
363 close(fd);
364
365 return LXC_MAINLOOP_CLOSE;
366 }
367
368 if (fd == terminal->peer)
369 w = lxc_write_nointr(terminal->master, buf, r);
370
371 w_rbuf = w_log = 0;
372 if (fd == terminal->master) {
373 /* write to peer first */
374 if (terminal->peer >= 0)
375 w = lxc_write_nointr(terminal->peer, buf, r);
376
377 /* write to terminal ringbuffer */
378 if (terminal->buffer_size > 0)
379 w_rbuf = lxc_ringbuf_write(&terminal->ringbuf, buf, r);
380
381 /* write to terminal log */
382 if (terminal->log_fd >= 0)
383 w_log = lxc_terminal_write_log_file(terminal, buf, r);
384 }
385
386 if (w != r)
387 WARN("Short write on terminal r:%d != w:%d", r, w);
388
389 if (w_rbuf < 0) {
390 errno = -w_rbuf;
391 SYSTRACE("Failed to write %d bytes to terminal ringbuffer", r);
392 }
393
394 if (w_log < 0)
395 TRACE("Failed to write %d bytes to terminal log", r);
396
397 return LXC_MAINLOOP_CONTINUE;
398 }
399
400 static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal)
401 {
402 int ret;
403
404 if (terminal->peer >= 0) {
405 ret = lxc_mainloop_add_handler(terminal->descr, terminal->peer,
406 lxc_terminal_io_cb, terminal);
407 if (ret < 0) {
408 WARN("Failed to add terminal peer handler to mainloop");
409 return -1;
410 }
411 }
412
413 if (!terminal->tty_state || terminal->tty_state->sigfd < 0)
414 return 0;
415
416 ret = lxc_mainloop_add_handler(terminal->descr, terminal->tty_state->sigfd,
417 lxc_terminal_signalfd_cb, terminal->tty_state);
418 if (ret < 0) {
419 WARN("Failed to add signal handler to mainloop");
420 return -1;
421 }
422
423 return 0;
424 }
425
426 int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr,
427 struct lxc_terminal *terminal)
428 {
429 int ret;
430
431 if (terminal->master < 0) {
432 INFO("Terminal is not initialized");
433 return 0;
434 }
435
436 ret = lxc_mainloop_add_handler(descr, terminal->master,
437 lxc_terminal_io_cb, terminal);
438 if (ret < 0) {
439 ERROR("Failed to add handler for terminal master fd %d to "
440 "mainloop", terminal->master);
441 return -1;
442 }
443
444 /* We cache the descr so that we can add an fd to it when someone
445 * does attach to it in lxc_terminal_allocate().
446 */
447 terminal->descr = descr;
448
449 return lxc_terminal_mainloop_add_peer(terminal);
450 }
451
452 int lxc_setup_tios(int fd, struct termios *oldtios)
453 {
454 int ret;
455 struct termios newtios;
456
457 if (!isatty(fd)) {
458 ERROR("File descriptor %d does not refer to a terminal", fd);
459 return -1;
460 }
461
462 /* Get current termios. */
463 ret = tcgetattr(fd, oldtios);
464 if (ret < 0) {
465 SYSERROR("Failed to get current terminal settings");
466 return -1;
467 }
468
469 /* ensure we don't end up in an endless loop:
470 * The kernel might fire SIGTTOU while an
471 * ioctl() in tcsetattr() is executed. When the ioctl()
472 * is resumed and retries, the signal handler interrupts it again.
473 */
474 signal (SIGTTIN, SIG_IGN);
475 signal (SIGTTOU, SIG_IGN);
476
477 newtios = *oldtios;
478
479 /* We use the same settings that ssh does. */
480 newtios.c_iflag |= IGNPAR;
481 newtios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
482 #ifdef IUCLC
483 newtios.c_iflag &= ~IUCLC;
484 #endif
485 newtios.c_lflag &= ~(TOSTOP | ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
486 #ifdef IEXTEN
487 newtios.c_lflag &= ~IEXTEN;
488 #endif
489 newtios.c_oflag &= ~ONLCR;
490 newtios.c_oflag |= OPOST;
491 newtios.c_cc[VMIN] = 1;
492 newtios.c_cc[VTIME] = 0;
493
494 /* Set new attributes. */
495 ret = tcsetattr(fd, TCSAFLUSH, &newtios);
496 if (ret < 0) {
497 ERROR("Failed to set new terminal settings");
498 return -1;
499 }
500
501 return 0;
502 }
503
504 static void lxc_terminal_peer_proxy_free(struct lxc_terminal *terminal)
505 {
506 lxc_terminal_signal_fini(terminal);
507
508 close(terminal->proxy.master);
509 terminal->proxy.master = -1;
510
511 close(terminal->proxy.slave);
512 terminal->proxy.slave = -1;
513
514 terminal->proxy.busy = -1;
515
516 terminal->proxy.name[0] = '\0';
517
518 terminal->peer = -1;
519 }
520
521 static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal *terminal,
522 int sockfd)
523 {
524 int ret;
525 struct termios oldtermio;
526 struct lxc_terminal_state *ts;
527
528 if (terminal->master < 0) {
529 ERROR("Terminal not set up");
530 return -1;
531 }
532
533 if (terminal->proxy.busy != -1 || terminal->peer != -1) {
534 NOTICE("Terminal already in use");
535 return -1;
536 }
537
538 if (terminal->tty_state) {
539 ERROR("Terminal has already been initialized");
540 return -1;
541 }
542
543 /* This is the proxy terminal that will be given to the client, and
544 * that the real terminal master will send to / recv from.
545 */
546 ret = openpty(&terminal->proxy.master, &terminal->proxy.slave, NULL,
547 NULL, NULL);
548 if (ret < 0) {
549 SYSERROR("Failed to open proxy terminal");
550 return -1;
551 }
552
553 ret = ttyname_r(terminal->proxy.slave, terminal->proxy.name,
554 sizeof(terminal->proxy.name));
555 if (ret < 0) {
556 SYSERROR("Failed to retrieve name of proxy terminal slave");
557 goto on_error;
558 }
559
560 ret = fd_cloexec(terminal->proxy.master, true);
561 if (ret < 0) {
562 SYSERROR("Failed to set FD_CLOEXEC flag on proxy terminal master");
563 goto on_error;
564 }
565
566 ret = fd_cloexec(terminal->proxy.slave, true);
567 if (ret < 0) {
568 SYSERROR("Failed to set FD_CLOEXEC flag on proxy terminal slave");
569 goto on_error;
570 }
571
572 ret = lxc_setup_tios(terminal->proxy.slave, &oldtermio);
573 if (ret < 0)
574 goto on_error;
575
576 ts = lxc_terminal_signal_init(terminal->proxy.master, terminal->master);
577 if (!ts)
578 goto on_error;
579
580 terminal->tty_state = ts;
581 terminal->peer = terminal->proxy.slave;
582 terminal->proxy.busy = sockfd;
583 ret = lxc_terminal_mainloop_add_peer(terminal);
584 if (ret < 0)
585 goto on_error;
586
587 NOTICE("Opened proxy terminal with master fd %d and slave fd %d",
588 terminal->proxy.master, terminal->proxy.slave);
589 return 0;
590
591 on_error:
592 lxc_terminal_peer_proxy_free(terminal);
593 return -1;
594 }
595
596 int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
597 {
598 int ttynum;
599 int masterfd = -1;
600 struct lxc_tty_info *ttys = &conf->ttys;
601 struct lxc_terminal *terminal = &conf->console;
602
603 if (*ttyreq == 0) {
604 int ret;
605
606 ret = lxc_terminal_peer_proxy_alloc(terminal, sockfd);
607 if (ret < 0)
608 goto out;
609
610 masterfd = terminal->proxy.master;
611 goto out;
612 }
613
614 if (*ttyreq > 0) {
615 if (*ttyreq > ttys->max)
616 goto out;
617
618 if (ttys->tty[*ttyreq - 1].busy)
619 goto out;
620
621 /* The requested tty is available. */
622 ttynum = *ttyreq;
623 goto out_tty;
624 }
625
626 /* Search for next available tty, fixup index tty1 => [0]. */
627 for (ttynum = 1; ttynum <= ttys->max && ttys->tty[ttynum - 1].busy; ttynum++) {
628 ;
629 }
630
631 /* We didn't find any available slot for tty. */
632 if (ttynum > ttys->max)
633 goto out;
634
635 *ttyreq = ttynum;
636
637 out_tty:
638 ttys->tty[ttynum - 1].busy = sockfd;
639 masterfd = ttys->tty[ttynum - 1].master;
640
641 out:
642 return masterfd;
643 }
644
645 void lxc_terminal_free(struct lxc_conf *conf, int fd)
646 {
647 int i;
648 struct lxc_tty_info *ttys = &conf->ttys;
649 struct lxc_terminal *terminal = &conf->console;
650
651 for (i = 0; i < ttys->max; i++)
652 if (ttys->tty[i].busy == fd)
653 ttys->tty[i].busy = 0;
654
655 if (terminal->proxy.busy != fd)
656 return;
657
658 lxc_mainloop_del_handler(terminal->descr, terminal->proxy.slave);
659 lxc_terminal_peer_proxy_free(terminal);
660 }
661
662 static int lxc_terminal_peer_default(struct lxc_terminal *terminal)
663 {
664 struct lxc_terminal_state *ts;
665 const char *path;
666 int ret = 0;
667
668 if (terminal->path)
669 path = terminal->path;
670 else
671 path = "/dev/tty";
672
673 terminal->peer = lxc_unpriv(open(path, O_RDWR | O_CLOEXEC));
674 if (terminal->peer < 0) {
675 if (!terminal->path) {
676 errno = ENODEV;
677 SYSDEBUG("The process does not have a controlling terminal");
678 goto on_succes;
679 }
680
681 SYSERROR("Failed to open proxy terminal \"%s\"", path);
682 return -ENOTTY;
683 }
684 DEBUG("Using terminal \"%s\" as proxy", path);
685
686 if (!isatty(terminal->peer)) {
687 ERROR("File descriptor for \"%s\" does not refer to a terminal", path);
688 goto on_error_free_tios;
689 }
690
691 ts = lxc_terminal_signal_init(terminal->peer, terminal->master);
692 terminal->tty_state = ts;
693 if (!ts) {
694 WARN("Failed to install signal handler");
695 goto on_error_free_tios;
696 }
697
698 lxc_terminal_winsz(terminal->peer, terminal->master);
699
700 terminal->tios = malloc(sizeof(*terminal->tios));
701 if (!terminal->tios)
702 goto on_error_free_tios;
703
704 ret = lxc_setup_tios(terminal->peer, terminal->tios);
705 if (ret < 0)
706 goto on_error_close_peer;
707 else
708 goto on_succes;
709
710 on_error_free_tios:
711 free(terminal->tios);
712 terminal->tios = NULL;
713
714 on_error_close_peer:
715 close(terminal->peer);
716 terminal->peer = -1;
717 ret = -ENOTTY;
718
719 on_succes:
720 return ret;
721 }
722
723 int lxc_terminal_write_ringbuffer(struct lxc_terminal *terminal)
724 {
725 char *r_addr;
726 ssize_t ret;
727 uint64_t used;
728 struct lxc_ringbuf *buf = &terminal->ringbuf;
729
730 /* There's not log file where we can dump the ringbuffer to. */
731 if (terminal->log_fd < 0)
732 return 0;
733
734 used = lxc_ringbuf_used(buf);
735 if (used == 0)
736 return 0;
737
738 ret = lxc_terminal_truncate_log_file(terminal);
739 if (ret < 0)
740 return ret;
741
742 /* Write as much as we can without exceeding the limit. */
743 if (terminal->log_size < used)
744 used = terminal->log_size;
745
746 r_addr = lxc_ringbuf_get_read_addr(buf);
747 ret = lxc_write_nointr(terminal->log_fd, r_addr, used);
748 if (ret < 0)
749 return -EIO;
750
751 return 0;
752 }
753
754 void lxc_terminal_delete(struct lxc_terminal *terminal)
755 {
756 int ret;
757
758 ret = lxc_terminal_write_ringbuffer(terminal);
759 if (ret < 0)
760 WARN("Failed to write terminal log to disk");
761
762 if (terminal->tios && terminal->peer >= 0) {
763 ret = tcsetattr(terminal->peer, TCSAFLUSH, terminal->tios);
764 if (ret < 0)
765 SYSWARN("Failed to set old terminal settings");
766 }
767 free(terminal->tios);
768 terminal->tios = NULL;
769
770 if (terminal->peer >= 0)
771 close(terminal->peer);
772 terminal->peer = -1;
773
774 if (terminal->master >= 0)
775 close(terminal->master);
776 terminal->master = -1;
777
778 if (terminal->slave >= 0)
779 close(terminal->slave);
780 terminal->slave = -1;
781
782 if (terminal->log_fd >= 0)
783 close(terminal->log_fd);
784 terminal->log_fd = -1;
785 }
786
787 /**
788 * Note that this function needs to run before the mainloop starts. Since we
789 * register a handler for the terminal's masterfd when we create the mainloop
790 * the terminal handler needs to see an allocated ringbuffer.
791 */
792 static int lxc_terminal_create_ringbuf(struct lxc_terminal *terminal)
793 {
794 int ret;
795 struct lxc_ringbuf *buf = &terminal->ringbuf;
796 uint64_t size = terminal->buffer_size;
797
798 /* no ringbuffer previously allocated and no ringbuffer requested */
799 if (!buf->addr && size <= 0)
800 return 0;
801
802 /* ringbuffer allocated but no new ringbuffer requested */
803 if (buf->addr && size <= 0) {
804 lxc_ringbuf_release(buf);
805 buf->addr = NULL;
806 buf->r_off = 0;
807 buf->w_off = 0;
808 buf->size = 0;
809 TRACE("Deallocated terminal ringbuffer");
810 return 0;
811 }
812
813 if (size <= 0)
814 return 0;
815
816 /* check wether the requested size for the ringbuffer has changed */
817 if (buf->addr && buf->size != size) {
818 TRACE("Terminal ringbuffer size changed from %" PRIu64
819 " to %" PRIu64 " bytes. Deallocating terminal ringbuffer",
820 buf->size, size);
821 lxc_ringbuf_release(buf);
822 }
823
824 ret = lxc_ringbuf_create(buf, size);
825 if (ret < 0) {
826 ERROR("Failed to setup %" PRIu64 " byte terminal ringbuffer", size);
827 return -1;
828 }
829
830 TRACE("Allocated %" PRIu64 " byte terminal ringbuffer", size);
831 return 0;
832 }
833
834 /**
835 * This is the terminal log file. Please note that the terminal log file is
836 * (implementation wise not content wise) independent of the terminal ringbuffer.
837 */
838 int lxc_terminal_create_log_file(struct lxc_terminal *terminal)
839 {
840 if (!terminal->log_path)
841 return 0;
842
843 terminal->log_fd = lxc_unpriv(open(terminal->log_path, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600));
844 if (terminal->log_fd < 0) {
845 SYSERROR("Failed to open terminal log file \"%s\"", terminal->log_path);
846 return -1;
847 }
848
849 DEBUG("Using \"%s\" as terminal log file", terminal->log_path);
850 return 0;
851 }
852
853 int lxc_terminal_create(struct lxc_terminal *terminal)
854 {
855 int ret;
856
857 ret = openpty(&terminal->master, &terminal->slave, NULL, NULL, NULL);
858 if (ret < 0) {
859 SYSERROR("Failed to open terminal");
860 return -1;
861 }
862
863 ret = ttyname_r(terminal->slave, terminal->name, sizeof(terminal->name));
864 if (ret < 0) {
865 SYSERROR("Failed to retrieve name of terminal slave");
866 goto err;
867 }
868
869 ret = fd_cloexec(terminal->master, true);
870 if (ret < 0) {
871 SYSERROR("Failed to set FD_CLOEXEC flag on terminal master");
872 goto err;
873 }
874
875 ret = fd_cloexec(terminal->slave, true);
876 if (ret < 0) {
877 SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave");
878 goto err;
879 }
880
881 ret = lxc_terminal_peer_default(terminal);
882 if (ret < 0) {
883 ERROR("Failed to allocate proxy terminal");
884 goto err;
885 }
886
887 return 0;
888
889 err:
890 lxc_terminal_delete(terminal);
891 return -ENODEV;
892 }
893
894 int lxc_terminal_setup(struct lxc_conf *conf)
895 {
896 int ret;
897 struct lxc_terminal *terminal = &conf->console;
898
899 if (terminal->path && strcmp(terminal->path, "none") == 0) {
900 INFO("No terminal requested");
901 return 0;
902 }
903
904 ret = lxc_terminal_create(terminal);
905 if (ret < 0)
906 return -1;
907
908 ret = lxc_terminal_create_log_file(terminal);
909 if (ret < 0)
910 goto err;
911
912 ret = lxc_terminal_create_ringbuf(terminal);
913 if (ret < 0)
914 goto err;
915
916 return 0;
917
918 err:
919 lxc_terminal_delete(terminal);
920 return -ENODEV;
921 }
922
923 static bool __terminal_dup2(int duplicate, int original)
924 {
925 int ret;
926
927 if (!isatty(original))
928 return true;
929
930 ret = dup2(duplicate, original);
931 if (ret < 0) {
932 SYSERROR("Failed to dup2(%d, %d)", duplicate, original);
933 return false;
934 }
935
936 return true;
937 }
938
939 int lxc_terminal_set_stdfds(int fd)
940 {
941 int i;
942
943 if (fd < 0)
944 return 0;
945
946 for (i = 0; i < 3; i++)
947 if (!__terminal_dup2(fd, (int[]){STDIN_FILENO, STDOUT_FILENO,
948 STDERR_FILENO}[i]))
949 return -1;
950
951 return 0;
952 }
953
954 int lxc_terminal_stdin_cb(int fd, uint32_t events, void *cbdata,
955 struct lxc_epoll_descr *descr)
956 {
957 int ret;
958 char c;
959 struct lxc_terminal_state *ts = cbdata;
960
961 if (fd != ts->stdinfd)
962 return LXC_MAINLOOP_CLOSE;
963
964 ret = lxc_read_nointr(ts->stdinfd, &c, 1);
965 if (ret <= 0)
966 return LXC_MAINLOOP_CLOSE;
967
968 if (ts->escape >= 1) {
969 /* we want to exit the terminal with Ctrl+a q */
970 if (c == ts->escape && !ts->saw_escape) {
971 ts->saw_escape = 1;
972 return LXC_MAINLOOP_CONTINUE;
973 }
974
975 if (c == 'q' && ts->saw_escape)
976 return LXC_MAINLOOP_CLOSE;
977
978 ts->saw_escape = 0;
979 }
980
981 ret = lxc_write_nointr(ts->masterfd, &c, 1);
982 if (ret <= 0)
983 return LXC_MAINLOOP_CLOSE;
984
985 return LXC_MAINLOOP_CONTINUE;
986 }
987
988 int lxc_terminal_master_cb(int fd, uint32_t events, void *cbdata,
989 struct lxc_epoll_descr *descr)
990 {
991 int r, w;
992 char buf[LXC_TERMINAL_BUFFER_SIZE];
993 struct lxc_terminal_state *ts = cbdata;
994
995 if (fd != ts->masterfd)
996 return LXC_MAINLOOP_CLOSE;
997
998 r = lxc_read_nointr(fd, buf, sizeof(buf));
999 if (r <= 0)
1000 return LXC_MAINLOOP_CLOSE;
1001
1002 w = lxc_write_nointr(ts->stdoutfd, buf, r);
1003 if (w <= 0 || w != r)
1004 return LXC_MAINLOOP_CLOSE;
1005
1006 return LXC_MAINLOOP_CONTINUE;
1007 }
1008
1009 int lxc_terminal_getfd(struct lxc_container *c, int *ttynum, int *masterfd)
1010 {
1011 return lxc_cmd_console(c->name, ttynum, masterfd, c->config_path);
1012 }
1013
1014 int lxc_console(struct lxc_container *c, int ttynum,
1015 int stdinfd, int stdoutfd, int stderrfd,
1016 int escape)
1017 {
1018 int masterfd, ret, ttyfd;
1019 struct lxc_epoll_descr descr;
1020 struct termios oldtios;
1021 struct lxc_terminal_state *ts;
1022 struct lxc_terminal terminal = {
1023 .tty_state = NULL,
1024 };
1025 int istty = 0;
1026
1027 ttyfd = lxc_cmd_console(c->name, &ttynum, &masterfd, c->config_path);
1028 if (ttyfd < 0)
1029 return -1;
1030
1031 ret = setsid();
1032 if (ret < 0)
1033 TRACE("Process is already group leader");
1034
1035 ts = lxc_terminal_signal_init(stdinfd, masterfd);
1036 if (!ts) {
1037 ret = -1;
1038 goto close_fds;
1039 }
1040 terminal.tty_state = ts;
1041 ts->escape = escape;
1042 ts->stdoutfd = stdoutfd;
1043
1044 istty = isatty(stdinfd);
1045 if (istty) {
1046 lxc_terminal_winsz(stdinfd, masterfd);
1047 lxc_terminal_winsz(ts->stdinfd, ts->masterfd);
1048 } else {
1049 INFO("File descriptor %d does not refer to a terminal", stdinfd);
1050 }
1051
1052 ret = lxc_mainloop_open(&descr);
1053 if (ret) {
1054 ERROR("Failed to create mainloop");
1055 goto sigwinch_fini;
1056 }
1057
1058 if (ts->sigfd != -1) {
1059 ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
1060 lxc_terminal_signalfd_cb, ts);
1061 if (ret < 0) {
1062 ERROR("Failed to add signal handler to mainloop");
1063 goto close_mainloop;
1064 }
1065 }
1066
1067 ret = lxc_mainloop_add_handler(&descr, ts->stdinfd,
1068 lxc_terminal_stdin_cb, ts);
1069 if (ret < 0) {
1070 ERROR("Failed to add stdin handler");
1071 goto close_mainloop;
1072 }
1073
1074 ret = lxc_mainloop_add_handler(&descr, ts->masterfd,
1075 lxc_terminal_master_cb, ts);
1076 if (ret < 0) {
1077 ERROR("Failed to add master handler");
1078 goto close_mainloop;
1079 }
1080
1081 if (ts->escape >= 1) {
1082 fprintf(stderr,
1083 "\n"
1084 "Connected to tty %1$d\n"
1085 "Type <Ctrl+%2$c q> to exit the console, "
1086 "<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n",
1087 ttynum, 'a' + escape - 1);
1088 }
1089
1090 if (istty) {
1091 ret = lxc_setup_tios(stdinfd, &oldtios);
1092 if (ret < 0)
1093 goto close_mainloop;
1094 }
1095
1096 ret = lxc_mainloop(&descr, -1);
1097 if (ret < 0) {
1098 ERROR("The mainloop returned an error");
1099 goto restore_tios;
1100 }
1101
1102 ret = 0;
1103
1104 restore_tios:
1105 if (istty) {
1106 istty = tcsetattr(stdinfd, TCSAFLUSH, &oldtios);
1107 if (istty < 0)
1108 SYSWARN("Failed to restore terminal properties");
1109 }
1110
1111 close_mainloop:
1112 lxc_mainloop_close(&descr);
1113
1114 sigwinch_fini:
1115 lxc_terminal_signal_fini(&terminal);
1116
1117 close_fds:
1118 close(masterfd);
1119 close(ttyfd);
1120
1121 return ret;
1122 }
1123
1124 int lxc_make_controlling_terminal(int fd)
1125 {
1126 int ret;
1127
1128 setsid();
1129
1130 ret = ioctl(fd, TIOCSCTTY, (char *)NULL);
1131 if (ret < 0)
1132 return -1;
1133
1134 return 0;
1135 }
1136
1137 int lxc_terminal_prepare_login(int fd)
1138 {
1139 int ret;
1140
1141 ret = lxc_make_controlling_terminal(fd);
1142 if (ret < 0)
1143 return -1;
1144
1145 ret = lxc_terminal_set_stdfds(fd);
1146 if (ret < 0)
1147 return -1;
1148
1149 if (fd > STDERR_FILENO)
1150 close(fd);
1151
1152 return 0;
1153 }
1154
1155 void lxc_terminal_info_init(struct lxc_terminal_info *terminal)
1156 {
1157 terminal->name[0] = '\0';
1158 terminal->master = -EBADF;
1159 terminal->slave = -EBADF;
1160 terminal->busy = -1;
1161 }
1162
1163 void lxc_terminal_init(struct lxc_terminal *terminal)
1164 {
1165 memset(terminal, 0, sizeof(*terminal));
1166 terminal->slave = -EBADF;
1167 terminal->master = -EBADF;
1168 terminal->peer = -EBADF;
1169 terminal->log_fd = -EBADF;
1170 lxc_terminal_info_init(&terminal->proxy);
1171 }
1172
1173 void lxc_terminal_conf_free(struct lxc_terminal *terminal)
1174 {
1175 free(terminal->log_path);
1176 free(terminal->path);
1177 if (terminal->buffer_size > 0 && terminal->ringbuf.addr)
1178 lxc_ringbuf_release(&terminal->ringbuf);
1179 lxc_terminal_signal_fini(terminal);
1180 }
1181
1182 int lxc_terminal_map_ids(struct lxc_conf *c, struct lxc_terminal *terminal)
1183 {
1184 int ret;
1185
1186 if (lxc_list_empty(&c->id_map))
1187 return 0;
1188
1189 if (strcmp(terminal->name, "") == 0)
1190 return 0;
1191
1192 ret = chown_mapped_root(terminal->name, c);
1193 if (ret < 0) {
1194 ERROR("Failed to chown terminal \"%s\"", terminal->name);
1195 return -1;
1196 }
1197
1198 TRACE("Chowned terminal \"%s\"", terminal->name);
1199
1200 return 0;
1201 }