2 * Copyright (c) 2009-2010 Todd C. Miller <Todd.Miller@courtesan.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
20 #include <sys/param.h>
21 #ifdef HAVE_SYS_SYSMACROS_H
22 # include <sys/sysmacros.h>
24 #include <sys/socket.h>
32 #endif /* HAVE_TERMIOS_H */
33 #include <sys/ioctl.h>
34 #ifdef HAVE_SYS_SELECT_H
35 # include <sys/select.h>
36 #endif /* HAVE_SYS_SELECT_H */
45 #endif /* STDC_HEADERS */
48 #endif /* HAVE_STRING_H */
51 #endif /* HAVE_STRINGS_H */
54 #endif /* HAVE_UNISTD_H */
55 #if TIME_WITH_SYS_TIME
65 # include <selinux/selinux.h>
69 #include "sudo_exec.h"
71 /* Shared with exec_pty.c for use with handler(). */
74 #ifdef _PATH_SUDO_IO_LOGDIR
75 /* We keep a tailq of signals to forward to child. */
77 struct sigforward *prev, *next;
80 TQ_DECLARE(sigforward)
81 static struct sigforward_list sigfwd_list;
82 static void forward_signals __P((int fd));
83 static void schedule_signal __P((int signo));
85 #endif /* _PATH_SUDO_IO_LOGDIR */
87 static int handle_signals __P((int fd, pid_t child,
88 struct command_status *cstat));
91 * Like execve(2) but falls back to running through /bin/sh
92 * ala execvp(3) if we get ENOEXEC.
95 my_execve(path, argv, envp)
100 execve(path, argv, envp);
101 if (errno == ENOEXEC) {
102 argv--; /* at least one extra slot... */
104 argv[1] = (char *)path;
105 execve(_PATH_BSHELL, argv, envp);
111 * Fork and execute a command, returns the child's pid.
112 * Sends errno back on sv[1] if execve() fails.
114 static int fork_cmnd(path, argv, envp, sv, rbac_enabled)
121 struct command_status cstat;
125 zero_bytes(&sa, sizeof(sa));
126 sigemptyset(&sa.sa_mask);
127 sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
128 sa.sa_handler = handler;
129 sigaction(SIGCONT, &sa, NULL);
139 close(signal_pipe[0]);
140 close(signal_pipe[1]);
141 fcntl(sv[1], F_SETFD, FD_CLOEXEC);
143 if (exec_setup(rbac_enabled, user_ttypath, -1) == TRUE) {
144 /* headed for execve() */
145 closefrom(def_closefrom);
148 selinux_execve(path, argv, envp);
151 my_execve(path, argv, envp);
153 cstat.type = CMD_ERRNO;
155 send(sv[1], &cstat, sizeof(cstat), 0);
161 static struct signal_state {
164 } saved_signals[] = {
182 * Save signal handler state so it can be restored before exec.
187 struct signal_state *ss;
189 for (ss = saved_signals; ss->signo != -1; ss++)
190 sigaction(ss->signo, NULL, &ss->sa);
194 * Restore signal handlers to initial state.
199 struct signal_state *ss;
201 for (ss = saved_signals; ss->signo != -1; ss++)
202 sigaction(ss->signo, &ss->sa, NULL);
206 * Execute a command, potentially in a pty with I/O loggging.
207 * This is a little bit tricky due to how POSIX job control works and
208 * we fact that we have two different controlling terminals to deal with.
211 sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode)
216 struct command_status *cstat;
220 int maxfd, n, nready, sv[2];
221 int rbac_enabled = 0;
226 /* If running in background mode, fork and exit. */
230 cstat->type = CMD_ERRNO;
234 /* child continues */
242 #ifdef _PATH_SUDO_IO_LOGDIR
243 log_io = def_log_output || def_log_input || def_use_pty;
250 #endif /* _PATH_SUDO_IO_LOGDIR */
253 rbac_enabled = is_selinux_enabled() > 0 && user_role != NULL;
259 * If we don't need to wait for the command to finish, just exec it.
262 exec_setup(FALSE, NULL, -1);
263 closefrom(def_closefrom);
264 my_execve(path, argv, envp);
265 cstat->type = CMD_ERRNO;
271 * We communicate with the child over a bi-directional pair of sockets.
272 * Parent sends signal info to child and child sends back wait status.
274 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
275 error(1, "cannot create sockets");
278 * We use a pipe to atomically handle signal notification within
281 if (pipe_nonblock(signal_pipe) != 0)
282 error(1, "cannot create pipe");
284 zero_bytes(&sa, sizeof(sa));
285 sigemptyset(&sa.sa_mask);
288 * Signals for forward to the child process (excluding SIGCHLD).
289 * Note: HP-UX select() will not be interrupted if SA_RESTART set.
291 sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
292 sa.sa_handler = handler;
293 sigaction(SIGALRM, &sa, NULL);
294 sigaction(SIGCHLD, &sa, NULL);
295 sigaction(SIGHUP, &sa, NULL);
296 sigaction(SIGINT, &sa, NULL);
297 sigaction(SIGPIPE, &sa, NULL);
298 sigaction(SIGQUIT, &sa, NULL);
299 sigaction(SIGTERM, &sa, NULL);
300 sigaction(SIGUSR1, &sa, NULL);
301 sigaction(SIGUSR2, &sa, NULL);
303 /* Max fd we will be selecting on. */
304 maxfd = MAX(sv[0], signal_pipe[0]);
307 * Child will run the command in the pty, parent will pass data
308 * to and from pty. Adjusts maxfd as needed.
310 #ifdef _PATH_SUDO_IO_LOGDIR
312 child = fork_pty(path, argv, envp, sv, rbac_enabled, &maxfd);
315 child = fork_cmnd(path, argv, envp, sv, rbac_enabled);
318 #ifdef HAVE_SETLOCALE
320 * I/O logging must be in the C locale for floating point numbers
321 * to be logged consistently.
323 setlocale(LC_ALL, "C");
327 * In the event loop we pass input from user tty to master
328 * and pass output from master to stdout and IO plugin.
330 fdsr = (fd_set *)emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
331 fdsw = (fd_set *)emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
333 zero_bytes(fdsw, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
334 zero_bytes(fdsr, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
336 FD_SET(signal_pipe[0], fdsr);
338 #ifdef _PATH_SUDO_IO_LOGDIR
339 if (!tq_empty(&sigfwd_list))
342 fd_set_iobs(fdsr, fdsw); /* XXX - better name */
344 nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL);
348 error(1, "select failed");
350 #ifdef _PATH_SUDO_IO_LOGDIR
351 if (FD_ISSET(sv[0], fdsw)) {
352 forward_signals(sv[0]);
354 #endif /* _PATH_SUDO_IO_LOGDIR */
355 if (FD_ISSET(signal_pipe[0], fdsr)) {
356 n = handle_signals(signal_pipe[0], child, cstat);
358 /* Child has exited, cstat is set, we are done. */
362 /* Error reading signal_pipe[0], should not happen. */
365 /* Restart event loop so signals get sent to child immediately. */
368 if (FD_ISSET(sv[0], fdsr)) {
369 /* read child status */
370 n = recv(sv[0], cstat, sizeof(*cstat), 0);
374 #ifdef _PATH_SUDO_IO_LOGDIR
376 * If not logging I/O we will receive ECONNRESET when
377 * the command is executed. It is safe to ignore this.
379 if (log_io && errno != EAGAIN) {
380 cstat->type = CMD_ERRNO;
386 #ifdef _PATH_SUDO_IO_LOGDIR /* XXX */
387 if (cstat->type == CMD_WSTATUS) {
388 if (WIFSTOPPED(cstat->val)) {
389 /* Suspend parent and tell child how to resume on return. */
390 n = suspend_parent(WSTOPSIG(cstat->val));
394 /* Child exited or was killed, either way we are done. */
398 #endif /* _PATH_SUDO_IO_LOGDIR */
399 if (cstat->type == CMD_ERRNO) {
400 /* Child was unable to execute command or broken pipe. */
405 #ifdef _PATH_SUDO_IO_LOGDIR
406 if (perform_io(fdsr, fdsw, cstat) != 0) {
407 /* I/O error, kill child if still alive and finish. */
408 schedule_signal(SIGKILL);
409 forward_signals(sv[0]);
412 #endif /* _PATH_SUDO_IO_LOGDIR */
415 #ifdef _PATH_SUDO_IO_LOGDIR
417 /* Flush any remaining output and free pty-related memory. */
420 #endif /* _PATH_SUDO_IO_LOGDIR */
424 /* This is probably not needed in log_io mode. */
425 if (selinux_restore_tty() != 0)
426 warningx("unable to restore tty label");
433 #ifdef _PATH_SUDO_IO_LOGDIR
434 while (!tq_empty(&sigfwd_list)) {
435 struct sigforward *sigfwd = tq_first(&sigfwd_list);
436 tq_remove(&sigfwd_list, sigfwd);
439 #endif /* _PATH_SUDO_IO_LOGDIR */
441 return cstat->type == CMD_ERRNO ? -1 : 0;
445 * Read signals on fd written to by handler().
446 * Returns -1 on error, 0 on child exit, else 1.
449 handle_signals(fd, child, cstat)
452 struct command_status *cstat;
460 /* read signal pipe */
461 nread = read(signal_pipe[0], &signo, sizeof(signo));
463 /* It should not be possible to get EOF but just in case. */
466 /* Restart if interrupted by signal so the pipe doesn't fill. */
469 /* If pipe is empty, we are done. */
472 cstat->type = CMD_ERRNO;
476 if (signo == SIGCHLD) {
478 * If logging I/O, child is the intermediate process,
479 * otherwise it is the command itself.
483 pid = sudo_waitpid(child, &status, WUNTRACED|WNOHANG);
487 } while (pid == -1 && errno == EINTR);
489 /* If not logging I/O and child has exited we are done. */
490 #ifdef _PATH_SUDO_IO_LOGDIR
494 if (WIFSTOPPED(status)) {
496 * Save the controlling terminal's process group
497 * so we can restore it after we resume.
499 #ifdef HAVE_TCSETPGRP
500 pid_t saved_pgrp = (pid_t)-1;
501 int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
503 saved_pgrp = tcgetpgrp(fd);
504 #endif /* HAVE_TCSETPGRP */
505 if (kill(getpid(), WSTOPSIG(status)) != 0)
506 warning("kill(%d, %d)", getpid(), WSTOPSIG(status));
507 #ifdef HAVE_TCSETPGRP
509 if (saved_pgrp != (pid_t)-1)
510 (void)tcsetpgrp(fd, saved_pgrp);
513 #endif /* HAVE_TCSETPGRP */
515 /* Child has exited, we are done. */
516 cstat->type = CMD_WSTATUS;
521 /* Else we get ECONNRESET on sv[0] if child dies. */
524 #ifdef _PATH_SUDO_IO_LOGDIR
526 /* Schedule signo to be forwared to the child. */
527 schedule_signal(signo);
531 /* Nothing listening on sv[0], send directly. */
532 if (kill(child, signo) != 0)
533 warning("kill(%d, %d)", child, signo);
540 #ifdef _PATH_SUDO_IO_LOGDIR
542 * Forward signals in sigfwd_list to child listening on fd.
545 forward_signals(sock)
548 struct sigforward *sigfwd;
549 struct command_status cstat;
552 while (!tq_empty(&sigfwd_list)) {
553 sigfwd = tq_first(&sigfwd_list);
554 cstat.type = CMD_SIGNO;
555 cstat.val = sigfwd->signo;
557 nsent = send(sock, &cstat, sizeof(cstat), 0);
558 } while (nsent == -1 && errno == EINTR);
559 tq_remove(&sigfwd_list, sigfwd);
561 if (nsent != sizeof(cstat)) {
562 if (errno == EPIPE) {
563 /* Other end of socket gone, empty out sigfwd_list. */
564 while (!tq_empty(&sigfwd_list)) {
565 sigfwd = tq_first(&sigfwd_list);
566 tq_remove(&sigfwd_list, sigfwd);
576 * Schedule a signal to be forwared.
579 schedule_signal(signo)
582 struct sigforward *sigfwd;
584 sigfwd = emalloc(sizeof(*sigfwd));
585 sigfwd->prev = sigfwd;
587 sigfwd->signo = signo;
588 tq_append(&sigfwd_list, sigfwd);
590 #endif /* _PATH_SUDO_IO_LOGDIR */
593 * Generic handler for signals passed from parent -> child.
594 * The other end of signal_pipe is checked in the main event loop.
600 unsigned char signo = (unsigned char)s;
603 * The pipe is non-blocking, if we overflow the kernel's pipe
604 * buffer we drop the signal. This is not a problem in practice.
606 if (write(signal_pipe[1], &signo, sizeof(signo)) == -1)
611 * Open a pipe and make both ends non-blocking.
612 * Returns 0 on success and -1 on error.
622 flags = fcntl(fds[0], F_GETFL, 0);
623 if (flags != -1 && !ISSET(flags, O_NONBLOCK))
624 rval = fcntl(fds[0], F_SETFL, flags | O_NONBLOCK);
626 flags = fcntl(fds[1], F_GETFL, 0);
627 if (flags != -1 && !ISSET(flags, O_NONBLOCK))
628 rval = fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);