Line data Source code
1 : /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2 :
3 : /***
4 : This file is part of systemd.
5 :
6 : Copyright 2014 David Herrmann <dh.herrmann@gmail.com>
7 :
8 : systemd is free software; you can redistribute it and/or modify it
9 : under the terms of the GNU Lesser General Public License as published by
10 : the Free Software Foundation; either version 2.1 of the License, or
11 : (at your option) any later version.
12 :
13 : systemd is distributed in the hope that it will be useful, but
14 : WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : Lesser General Public License for more details.
17 :
18 : You should have received a copy of the GNU Lesser General Public License
19 : along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 : ***/
21 :
22 : /*
23 : * PTY
24 : * A PTY object represents a single PTY connection between a master and a
25 : * child. The child process is fork()ed so the caller controls what program
26 : * will be run.
27 : *
28 : * Programs like /bin/login tend to perform a vhangup() on their TTY
29 : * before running the login procedure. This also causes the pty master
30 : * to get a EPOLLHUP event as long as no client has the TTY opened.
31 : * This means, we cannot use the TTY connection as reliable way to track
32 : * the client. Instead, we _must_ rely on the PID of the client to track
33 : * them.
34 : * However, this has the side effect that if the client forks and the
35 : * parent exits, we loose them and restart the client. But this seems to
36 : * be the expected behavior so we implement it here.
37 : *
38 : * Unfortunately, epoll always polls for EPOLLHUP so as long as the
39 : * vhangup() is ongoing, we will _always_ get EPOLLHUP and cannot sleep.
40 : * This gets worse if the client closes the TTY but doesn't exit.
41 : * Therefore, the fd must be edge-triggered in the epoll-set so we
42 : * only get the events once they change.
43 : */
44 :
45 : #include <errno.h>
46 : #include <fcntl.h>
47 : #include <signal.h>
48 : #include <stdbool.h>
49 : #include <stdint.h>
50 : #include <stdlib.h>
51 : #include <sys/epoll.h>
52 : #include <sys/ioctl.h>
53 : #include <sys/uio.h>
54 : #include <sys/wait.h>
55 : #include <termios.h>
56 : #include <unistd.h>
57 :
58 : #include "barrier.h"
59 : #include "macro.h"
60 : #include "ring.h"
61 : #include "util.h"
62 : #include "signal-util.h"
63 : #include "pty.h"
64 :
65 : #define PTY_BUFSIZE 4096
66 :
67 : enum {
68 : PTY_ROLE_UNKNOWN,
69 : PTY_ROLE_PARENT,
70 : PTY_ROLE_CHILD,
71 : };
72 :
73 : struct Pty {
74 : unsigned long ref;
75 : Barrier barrier;
76 : int fd;
77 : pid_t child;
78 : sd_event_source *fd_source;
79 : sd_event_source *child_source;
80 :
81 : char in_buf[PTY_BUFSIZE];
82 : Ring out_buf;
83 :
84 : pty_event_t event_fn;
85 : void *event_fn_userdata;
86 :
87 : bool needs_requeue : 1;
88 : unsigned int role : 2;
89 : };
90 :
91 1000 : int pty_new(Pty **out) {
92 2000 : _pty_unref_ Pty *pty = NULL;
93 : int r;
94 :
95 1000 : assert_return(out, -EINVAL);
96 :
97 1000 : pty = new0(Pty, 1);
98 1000 : if (!pty)
99 0 : return -ENOMEM;
100 :
101 1000 : pty->ref = 1;
102 1000 : pty->fd = -1;
103 1000 : pty->barrier = (Barrier) BARRIER_NULL;
104 :
105 1000 : pty->fd = posix_openpt(O_RDWR | O_NOCTTY | O_CLOEXEC | O_NONBLOCK);
106 1000 : if (pty->fd < 0)
107 0 : return -errno;
108 :
109 : /*
110 : * The slave-node is initialized to uid/gid of the caller of
111 : * posix_openpt(). Only if devpts is mounted with fixed uid/gid this is
112 : * skipped. In that case, grantpt() can overwrite these, but then you
113 : * have to be root to use chown() (or a pt_chown helper has to be
114 : * present). In those cases grantpt() really does something,
115 : * otherwise it's a no-op. We call grantpt() here to try supporting
116 : * those cases, even though no-one uses that, I guess. If you need other
117 : * access-rights, set them yourself after this call returns (no, this is
118 : * not racy, it looks racy, but races regarding your own UID are never
119 : * important as an attacker could ptrace you; and the slave-pty is also
120 : * still locked).
121 : */
122 1000 : r = grantpt(pty->fd);
123 1000 : if (r < 0)
124 0 : return -errno;
125 :
126 1000 : r = barrier_create(&pty->barrier);
127 1000 : if (r < 0)
128 0 : return r;
129 :
130 1000 : *out = pty;
131 1000 : pty = NULL;
132 1000 : return 0;
133 : }
134 :
135 0 : Pty *pty_ref(Pty *pty) {
136 0 : if (!pty || pty->ref < 1)
137 0 : return NULL;
138 :
139 0 : ++pty->ref;
140 0 : return pty;
141 : }
142 :
143 1000 : Pty *pty_unref(Pty *pty) {
144 1000 : if (!pty || pty->ref < 1 || --pty->ref > 0)
145 0 : return NULL;
146 :
147 1000 : pty_close(pty);
148 1000 : pty->child_source = sd_event_source_unref(pty->child_source);
149 1000 : barrier_destroy(&pty->barrier);
150 1000 : ring_clear(&pty->out_buf);
151 1000 : free(pty);
152 :
153 1000 : return NULL;
154 : }
155 :
156 0 : Barrier *pty_get_barrier(Pty *pty) {
157 0 : assert(pty);
158 0 : return &pty->barrier;
159 : }
160 :
161 3000 : bool pty_is_unknown(Pty *pty) {
162 3000 : return pty && pty->role == PTY_ROLE_UNKNOWN;
163 : }
164 :
165 5817 : bool pty_is_parent(Pty *pty) {
166 5817 : return pty && pty->role == PTY_ROLE_PARENT;
167 : }
168 :
169 1000 : bool pty_is_child(Pty *pty) {
170 1000 : return pty && pty->role == PTY_ROLE_CHILD;
171 : }
172 :
173 2817 : bool pty_has_child(Pty *pty) {
174 2817 : return pty_is_parent(pty) && pty->child > 0;
175 : }
176 :
177 1817 : pid_t pty_get_child(Pty *pty) {
178 1817 : return pty_has_child(pty) ? pty->child : -ECHILD;
179 : }
180 :
181 10999 : bool pty_is_open(Pty *pty) {
182 10999 : return pty && pty->fd >= 0;
183 : }
184 :
185 3999 : int pty_get_fd(Pty *pty) {
186 3999 : assert_return(pty, -EINVAL);
187 :
188 3999 : return pty_is_open(pty) ? pty->fd : -EPIPE;
189 : }
190 :
191 1000 : int pty_make_child(Pty *pty) {
192 2000 : _cleanup_free_ char *slave_name = NULL;
193 : int r, fd;
194 :
195 1000 : assert_return(pty, -EINVAL);
196 1000 : assert_return(pty_is_unknown(pty), -EALREADY);
197 :
198 1000 : r = ptsname_malloc(pty->fd, &slave_name);
199 1000 : if (r < 0)
200 0 : return -errno;
201 :
202 1000 : fd = open(slave_name, O_RDWR | O_CLOEXEC | O_NOCTTY);
203 1000 : if (fd < 0)
204 0 : return -errno;
205 :
206 1000 : safe_close(pty->fd);
207 1000 : pty->fd = fd;
208 1000 : pty->child = getpid();
209 1000 : pty->role = PTY_ROLE_CHILD;
210 1000 : barrier_set_role(&pty->barrier, BARRIER_CHILD);
211 :
212 1000 : return 0;
213 : }
214 :
215 1000 : int pty_make_parent(Pty *pty, pid_t child) {
216 1000 : assert_return(pty, -EINVAL);
217 1000 : assert_return(pty_is_unknown(pty), -EALREADY);
218 :
219 1000 : pty->child = child;
220 1000 : pty->role = PTY_ROLE_PARENT;
221 :
222 1000 : return 0;
223 : }
224 :
225 1000 : int pty_unlock(Pty *pty) {
226 1000 : assert_return(pty, -EINVAL);
227 1000 : assert_return(pty_is_unknown(pty) || pty_is_parent(pty), -EINVAL);
228 1000 : assert_return(pty_is_open(pty), -ENODEV);
229 :
230 1000 : return unlockpt(pty->fd) < 0 ? -errno : 0;
231 : }
232 :
233 1000 : int pty_setup_child(Pty *pty) {
234 : struct termios attr;
235 : pid_t pid;
236 : int r;
237 :
238 1000 : assert_return(pty, -EINVAL);
239 1000 : assert_return(pty_is_child(pty), -EINVAL);
240 1000 : assert_return(pty_is_open(pty), -EALREADY);
241 :
242 1000 : r = reset_signal_mask();
243 1000 : if (r < 0)
244 0 : return r;
245 :
246 1000 : r = reset_all_signal_handlers();
247 1000 : if (r < 0)
248 0 : return r;
249 :
250 1000 : pid = setsid();
251 1000 : if (pid < 0 && errno != EPERM)
252 0 : return -errno;
253 :
254 1000 : r = ioctl(pty->fd, TIOCSCTTY, 0);
255 1000 : if (r < 0)
256 0 : return -errno;
257 :
258 1000 : r = tcgetattr(pty->fd, &attr);
259 1000 : if (r < 0)
260 0 : return -errno;
261 :
262 : /* erase character should be normal backspace, PLEASEEE! */
263 1000 : attr.c_cc[VERASE] = 010;
264 : /* always set UTF8 flag */
265 1000 : attr.c_iflag |= IUTF8;
266 :
267 1000 : r = tcsetattr(pty->fd, TCSANOW, &attr);
268 1000 : if (r < 0)
269 0 : return -errno;
270 :
271 2000 : if (dup2(pty->fd, STDIN_FILENO) != STDIN_FILENO ||
272 2000 : dup2(pty->fd, STDOUT_FILENO) != STDOUT_FILENO ||
273 1000 : dup2(pty->fd, STDERR_FILENO) != STDERR_FILENO)
274 0 : return -errno;
275 :
276 : /* only close FD if it's not a std-fd */
277 1000 : pty->fd = (pty->fd > 2) ? safe_close(pty->fd) : -1;
278 :
279 1000 : return 0;
280 : }
281 :
282 2000 : void pty_close(Pty *pty) {
283 2000 : if (!pty_is_open(pty))
284 1000 : return;
285 :
286 1000 : pty->fd_source = sd_event_source_unref(pty->fd_source);
287 1000 : pty->fd = safe_close(pty->fd);
288 : }
289 :
290 : /*
291 : * Drain input-queue and dispatch data via the event-handler. Returns <0 on
292 : * error, 0 if queue is empty and 1 if we couldn't empty the input queue fast
293 : * enough and there's still data left.
294 : */
295 2010 : static int pty_dispatch_read(Pty *pty) {
296 : unsigned int i;
297 : ssize_t len;
298 : int r;
299 :
300 : /*
301 : * We're edge-triggered, means we need to read the whole queue. This,
302 : * however, might cause us to stall if the writer is faster than we
303 : * are. Therefore, try reading as much as 8 times (32KiB) and only
304 : * bail out then.
305 : */
306 :
307 4009 : for (i = 0; i < 8; ++i) {
308 4009 : len = read(pty->fd, pty->in_buf, sizeof(pty->in_buf) - 1);
309 4009 : if (len < 0) {
310 2010 : if (errno == EINTR)
311 0 : continue;
312 :
313 2010 : return (errno == EAGAIN) ? 0 : -errno;
314 1999 : } else if (len == 0) {
315 0 : continue;
316 : }
317 :
318 : /* set terminating zero for debugging safety */
319 1999 : pty->in_buf[len] = 0;
320 1999 : r = pty->event_fn(pty, pty->event_fn_userdata, PTY_DATA, pty->in_buf, len);
321 1999 : if (r < 0)
322 0 : return r;
323 : }
324 :
325 : /* still data left, make sure we're queued again */
326 0 : pty->needs_requeue = true;
327 :
328 0 : return 1;
329 : }
330 :
331 : /*
332 : * Drain output-queue by writing data to the pty. Returns <0 on error, 0 if the
333 : * output queue is empty now and 1 if we couldn't empty the output queue fast
334 : * enough and there's still data left.
335 : */
336 4174 : static int pty_dispatch_write(Pty *pty) {
337 : struct iovec vec[2];
338 : unsigned int i;
339 : ssize_t len;
340 : size_t num;
341 :
342 : /*
343 : * Same as pty_dispatch_read(), we're edge-triggered so we need to call
344 : * write() until either all data is written or it returns EAGAIN. We
345 : * call it twice and if it still writes successfully, we reschedule.
346 : */
347 :
348 5174 : for (i = 0; i < 2; ++i) {
349 5174 : num = ring_peek(&pty->out_buf, vec);
350 5174 : if (num < 1)
351 4174 : return 0;
352 :
353 1000 : len = writev(pty->fd, vec, (int)num);
354 1000 : if (len < 0) {
355 0 : if (errno == EINTR)
356 0 : continue;
357 :
358 0 : return (errno == EAGAIN) ? 1 : -errno;
359 1000 : } else if (len == 0) {
360 0 : continue;
361 : }
362 :
363 1000 : ring_pull(&pty->out_buf, (size_t)len);
364 : }
365 :
366 : /* still data left, make sure we're queued again */
367 0 : if (ring_get_size(&pty->out_buf) > 0) {
368 0 : pty->needs_requeue = true;
369 0 : return 1;
370 : }
371 :
372 0 : return 0;
373 : }
374 :
375 4174 : static int pty_fd_fn(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
376 4174 : Pty *pty = userdata;
377 4174 : int r_hup = 0, r_write = 0, r_read = 0, r;
378 :
379 : /*
380 : * Whenever we encounter I/O errors, we have to make sure to drain the
381 : * input queue first, before we handle any HUP. A child might send us
382 : * a message and immediately close the queue. We must not handle the
383 : * HUP first or we loose data.
384 : * Therefore, if we read a message successfully, we always return
385 : * success and wait for the next event-loop iteration. Furthermore,
386 : * whenever there is a write-error, we must try reading from the input
387 : * queue even if EPOLLIN is not set. The input might have arrived in
388 : * between epoll_wait() and write(). Therefore, write-errors are only
389 : * ever handled if the input-queue is empty. In all other cases they
390 : * are ignored until either reading fails or the input queue is empty.
391 : */
392 :
393 4174 : if (revents & (EPOLLHUP | EPOLLERR))
394 997 : r_hup = -EPIPE;
395 :
396 4174 : if (revents & EPOLLOUT)
397 4174 : r_write = pty_dispatch_write(pty);
398 :
399 : /* Awesome! Kernel signals HUP without IN but queues are not empty.. */
400 4174 : if ((revents & EPOLLIN) || r_hup < 0 || r_write < 0) {
401 2010 : r_read = pty_dispatch_read(pty);
402 2010 : if (r_read > 0)
403 0 : return 0; /* still data left to fetch next round */
404 : }
405 :
406 4174 : if (r_hup < 0 || r_write < 0 || r_read < 0) {
407 : /* PTY closed and input-queue drained */
408 1000 : pty_close(pty);
409 1000 : r = pty->event_fn(pty, pty->event_fn_userdata, PTY_HUP, NULL, 0);
410 1000 : if (r < 0)
411 0 : return r;
412 : }
413 :
414 4174 : return 0;
415 : }
416 :
417 4357 : static int pty_fd_prepare_fn(sd_event_source *source, void *userdata) {
418 4357 : Pty *pty = userdata;
419 : int r;
420 :
421 4357 : if (pty->needs_requeue) {
422 : /*
423 : * We're edge-triggered. In case we couldn't handle all events
424 : * or in case new write-data is queued, we set needs_requeue.
425 : * Before going asleep, we set the io-events *again*. sd-event
426 : * notices that we're edge-triggered and forwards the call to
427 : * the kernel even if the events didn't change. The kernel will
428 : * check the events and re-queue us on the ready queue in case
429 : * an event is pending.
430 : */
431 1000 : r = sd_event_source_set_io_events(source, EPOLLHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLET);
432 1000 : if (r >= 0)
433 1000 : pty->needs_requeue = false;
434 : }
435 :
436 4357 : return 0;
437 : }
438 :
439 1000 : static int pty_child_fn(sd_event_source *source, const siginfo_t *si, void *userdata) {
440 1000 : Pty *pty = userdata;
441 : int r;
442 :
443 1000 : pty->child = 0;
444 :
445 1000 : r = pty->event_fn(pty, pty->event_fn_userdata, PTY_CHILD, si, sizeof(*si));
446 1000 : if (r < 0)
447 0 : return r;
448 :
449 1000 : return 0;
450 : }
451 :
452 1000 : int pty_attach_event(Pty *pty, sd_event *event, pty_event_t event_fn, void *event_fn_userdata) {
453 : int r;
454 :
455 1000 : assert_return(pty, -EINVAL);
456 1000 : assert_return(event, -EINVAL);
457 1000 : assert_return(event_fn, -EINVAL);
458 1000 : assert_return(pty_is_parent(pty), -EINVAL);
459 :
460 1000 : pty_detach_event(pty);
461 :
462 1000 : if (pty_is_open(pty)) {
463 1000 : r = sd_event_add_io(event,
464 : &pty->fd_source,
465 : pty->fd,
466 : EPOLLHUP | EPOLLERR | EPOLLIN | EPOLLOUT | EPOLLET,
467 : pty_fd_fn,
468 : pty);
469 1000 : if (r < 0)
470 0 : goto error;
471 :
472 1000 : r = sd_event_source_set_prepare(pty->fd_source, pty_fd_prepare_fn);
473 1000 : if (r < 0)
474 0 : goto error;
475 : }
476 :
477 1000 : if (pty_has_child(pty)) {
478 1000 : r = sd_event_add_child(event,
479 : &pty->child_source,
480 : pty->child,
481 : WEXITED,
482 : pty_child_fn,
483 : pty);
484 1000 : if (r < 0)
485 0 : goto error;
486 : }
487 :
488 1000 : pty->event_fn = event_fn;
489 1000 : pty->event_fn_userdata = event_fn_userdata;
490 :
491 1000 : return 0;
492 :
493 : error:
494 0 : pty_detach_event(pty);
495 0 : return r;
496 : }
497 :
498 1000 : void pty_detach_event(Pty *pty) {
499 1000 : if (!pty)
500 0 : return;
501 :
502 1000 : pty->child_source = sd_event_source_unref(pty->child_source);
503 1000 : pty->fd_source = sd_event_source_unref(pty->fd_source);
504 1000 : pty->event_fn = NULL;
505 1000 : pty->event_fn_userdata = NULL;
506 : }
507 :
508 1000 : int pty_write(Pty *pty, const void *buf, size_t size) {
509 : bool was_empty;
510 : int r;
511 :
512 1000 : assert_return(pty, -EINVAL);
513 1000 : assert_return(pty_is_open(pty), -ENODEV);
514 1000 : assert_return(pty_is_parent(pty), -ENODEV);
515 :
516 1000 : if (size < 1)
517 0 : return 0;
518 :
519 : /*
520 : * Push @buf[0..@size] into the output ring-buffer. In case the
521 : * ring-buffer wasn't empty beforehand, we're already waiting for
522 : * EPOLLOUT and we're done. If it was empty, we have to re-queue the
523 : * FD for EPOLLOUT as we're edge-triggered and wouldn't get any new
524 : * EPOLLOUT event.
525 : */
526 :
527 1000 : was_empty = ring_get_size(&pty->out_buf) < 1;
528 :
529 1000 : r = ring_push(&pty->out_buf, buf, size);
530 1000 : if (r < 0)
531 0 : return r;
532 :
533 1000 : if (was_empty)
534 1000 : pty->needs_requeue = true;
535 :
536 1000 : return 0;
537 : }
538 :
539 0 : int pty_signal(Pty *pty, int sig) {
540 0 : assert_return(pty, -EINVAL);
541 0 : assert_return(pty_is_open(pty), -ENODEV);
542 0 : assert_return(pty_is_parent(pty), -ENODEV);
543 :
544 0 : return ioctl(pty->fd, TIOCSIG, sig) < 0 ? -errno : 0;
545 : }
546 :
547 1000 : int pty_resize(Pty *pty, unsigned short term_width, unsigned short term_height) {
548 1000 : struct winsize ws = {
549 : .ws_col = term_width,
550 : .ws_row = term_height,
551 : };
552 :
553 1000 : assert_return(pty, -EINVAL);
554 1000 : assert_return(pty_is_open(pty), -ENODEV);
555 1000 : assert_return(pty_is_parent(pty), -ENODEV);
556 :
557 : /*
558 : * This will send SIGWINCH to the pty slave foreground process group.
559 : * We will also get one, but we don't need it.
560 : */
561 1000 : return ioctl(pty->fd, TIOCSWINSZ, &ws) < 0 ? -errno : 0;
562 : }
563 :
564 1000 : pid_t pty_fork(Pty **out, sd_event *event, pty_event_t event_fn, void *event_fn_userdata, unsigned short initial_term_width, unsigned short initial_term_height) {
565 3000 : _pty_unref_ Pty *pty = NULL;
566 : int r;
567 : pid_t pid;
568 :
569 1000 : assert_return(out, -EINVAL);
570 1000 : assert_return((event && event_fn) || (!event && !event_fn), -EINVAL);
571 :
572 1000 : r = pty_new(&pty);
573 1000 : if (r < 0)
574 0 : return r;
575 :
576 1000 : r = pty_unlock(pty);
577 1000 : if (r < 0)
578 0 : return r;
579 :
580 1000 : pid = fork();
581 2000 : if (pid < 0)
582 0 : return -errno;
583 :
584 2000 : if (pid == 0) {
585 : /* child */
586 :
587 1000 : r = pty_make_child(pty);
588 1000 : if (r < 0)
589 0 : _exit(-r);
590 :
591 1000 : r = pty_setup_child(pty);
592 1000 : if (r < 0)
593 0 : _exit(-r);
594 :
595 : /* sync with parent */
596 1000 : if (!barrier_place_and_sync(&pty->barrier))
597 0 : _exit(1);
598 :
599 : /* fallthrough and return the child's PTY object */
600 : } else {
601 : /* parent */
602 :
603 1000 : r = pty_make_parent(pty, pid);
604 1000 : if (r < 0)
605 0 : goto parent_error;
606 :
607 1000 : r = pty_resize(pty, initial_term_width, initial_term_height);
608 1000 : if (r < 0)
609 0 : goto parent_error;
610 :
611 1000 : if (event) {
612 1000 : r = pty_attach_event(pty, event, event_fn, event_fn_userdata);
613 1000 : if (r < 0)
614 0 : goto parent_error;
615 : }
616 :
617 : /* sync with child */
618 1000 : if (!barrier_place_and_sync(&pty->barrier)) {
619 0 : r = -ECHILD;
620 0 : goto parent_error;
621 : }
622 :
623 : /* fallthrough and return the parent's PTY object */
624 : }
625 :
626 2000 : *out = pty;
627 2000 : pty = NULL;
628 2000 : return pid;
629 :
630 : parent_error:
631 0 : barrier_abort(&pty->barrier);
632 0 : waitpid(pty->child, NULL, 0);
633 0 : pty->child = 0;
634 0 : return r;
635 : }
|