Annotation of embedaddon/sudo/src/exec.c, revision 1.1.1.6
1.1 misho 1: /*
1.1.1.6 ! misho 2: * Copyright (c) 2009-2014 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 misho 3: *
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.
7: *
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.
15: */
16:
17: #include <config.h>
18:
19: #include <sys/types.h>
20: #include <sys/socket.h>
21: #include <sys/stat.h>
22: #include <sys/time.h>
23: #include <sys/wait.h>
24: #include <sys/ioctl.h>
25: #include <stdio.h>
26: #ifdef STDC_HEADERS
27: # include <stdlib.h>
28: # include <stddef.h>
29: #else
30: # ifdef HAVE_STDLIB_H
31: # include <stdlib.h>
32: # endif
33: #endif /* STDC_HEADERS */
34: #ifdef HAVE_STRING_H
35: # include <string.h>
36: #endif /* HAVE_STRING_H */
37: #ifdef HAVE_STRINGS_H
38: # include <strings.h>
39: #endif /* HAVE_STRINGS_H */
40: #ifdef HAVE_UNISTD_H
41: # include <unistd.h>
42: #endif /* HAVE_UNISTD_H */
1.1.1.6 ! misho 43: #ifdef TIME_WITH_SYS_TIME
1.1 misho 44: # include <time.h>
45: #endif
46: #include <errno.h>
47: #include <fcntl.h>
48: #include <signal.h>
49: #include <termios.h>
50:
51: #include "sudo.h"
52: #include "sudo_exec.h"
1.1.1.6 ! misho 53: #include "sudo_event.h"
1.1 misho 54: #include "sudo_plugin.h"
55: #include "sudo_plugin_int.h"
56:
1.1.1.6 ! misho 57: struct exec_closure {
! 58: pid_t child;
! 59: bool log_io;
! 60: sigset_t omask;
! 61: struct command_status *cstat;
! 62: struct command_details *details;
! 63: struct sudo_event_base *evbase;
! 64: };
! 65:
1.1 misho 66: /* We keep a tailq of signals to forward to child. */
67: struct sigforward {
1.1.1.6 ! misho 68: TAILQ_ENTRY(sigforward) entries;
1.1 misho 69: int signo;
70: };
1.1.1.6 ! misho 71: TAILQ_HEAD(sigfwd_list, sigforward);
! 72: static struct sigfwd_list sigfwd_list = TAILQ_HEAD_INITIALIZER(sigfwd_list);
! 73: static struct sudo_event *signal_event;
! 74: static struct sudo_event *sigfwd_event;
! 75: static struct sudo_event *backchannel_event;
1.1.1.3 misho 76: static pid_t ppgrp = -1;
77:
78: volatile pid_t cmnd_pid = -1;
1.1 misho 79:
1.1.1.6 ! misho 80: static void signal_pipe_cb(int fd, int what, void *v);
1.1.1.4 misho 81: static int dispatch_pending_signals(struct command_status *cstat);
1.1.1.6 ! misho 82: static void forward_signals(int fd, int what, void *v);
! 83: static void schedule_signal(struct sudo_event_base *evbase, int signo);
1.1.1.2 misho 84: #ifdef SA_SIGINFO
1.1.1.3 misho 85: static void handler_user_only(int s, siginfo_t *info, void *context);
1.1.1.2 misho 86: #endif
1.1 misho 87:
88: /*
89: * Fork and execute a command, returns the child's pid.
90: * Sends errno back on sv[1] if execve() fails.
91: */
92: static int fork_cmnd(struct command_details *details, int sv[2])
93: {
94: struct command_status cstat;
95: sigaction_t sa;
1.1.1.2 misho 96: debug_decl(fork_cmnd, SUDO_DEBUG_EXEC)
1.1 misho 97:
1.1.1.3 misho 98: ppgrp = getpgrp(); /* parent's process group */
99:
100: /*
101: * Handle suspend/restore of sudo and the command.
102: * In most cases, the command will be in the same process group as
103: * sudo and job control will "just work". However, if the command
104: * changes its process group ID and does not change it back (or is
105: * kill by SIGSTOP which is not catchable), we need to resume the
106: * command manually. Also, if SIGTSTP is sent directly to sudo,
107: * we need to suspend the command, and then suspend ourself, restoring
108: * the default SIGTSTP handler temporarily.
109: *
110: * XXX - currently we send SIGCONT upon resume in some cases where
111: * we don't need to (e.g. command pgrp == parent pgrp).
112: */
1.1.1.4 misho 113: memset(&sa, 0, sizeof(sa));
114: sigfillset(&sa.sa_mask);
1.1 misho 115: sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
1.1.1.3 misho 116: #ifdef SA_SIGINFO
117: sa.sa_flags |= SA_SIGINFO;
118: sa.sa_sigaction = handler;
119: #else
1.1 misho 120: sa.sa_handler = handler;
1.1.1.3 misho 121: #endif
1.1.1.4 misho 122: sudo_sigaction(SIGCONT, &sa, NULL);
1.1.1.3 misho 123: #ifdef SA_SIGINFO
124: sa.sa_sigaction = handler_user_only;
125: #endif
1.1.1.4 misho 126: sudo_sigaction(SIGTSTP, &sa, NULL);
1.1 misho 127:
1.1.1.2 misho 128: /*
129: * The policy plugin's session init must be run before we fork
130: * or certain pam modules won't be able to track their state.
131: */
132: if (policy_init_session(details) != true)
1.1.1.6 ! misho 133: fatalx(U_("policy plugin failed session initialization"));
1.1.1.2 misho 134:
1.1.1.3 misho 135: cmnd_pid = sudo_debug_fork();
136: switch (cmnd_pid) {
1.1 misho 137: case -1:
1.1.1.6 ! misho 138: fatal(U_("unable to fork"));
1.1 misho 139: break;
140: case 0:
141: /* child */
142: close(sv[0]);
143: close(signal_pipe[0]);
144: close(signal_pipe[1]);
145: fcntl(sv[1], F_SETFD, FD_CLOEXEC);
1.1.1.6 ! misho 146: exec_cmnd(details, &cstat, sv[1]);
1.1 misho 147: send(sv[1], &cstat, sizeof(cstat), 0);
1.1.1.2 misho 148: sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 1);
1.1 misho 149: _exit(1);
150: }
1.1.1.3 misho 151: sudo_debug_printf(SUDO_DEBUG_INFO, "executed %s, pid %d", details->command,
152: (int)cmnd_pid);
153: debug_return_int(cmnd_pid);
1.1 misho 154: }
155:
156: /*
1.1.1.4 misho 157: * Setup the execution environment and execute the command.
158: * If SELinux is enabled, run the command via sesh, otherwise
159: * execute it directly.
160: * If the exec fails, cstat is filled in with the value of errno.
1.1 misho 161: */
162: void
1.1.1.4 misho 163: exec_cmnd(struct command_details *details, struct command_status *cstat,
1.1.1.6 ! misho 164: int errfd)
1.1 misho 165: {
1.1.1.4 misho 166: debug_decl(exec_cmnd, SUDO_DEBUG_EXEC)
1.1.1.2 misho 167:
1.1.1.4 misho 168: restore_signals();
169: if (exec_setup(details, NULL, -1) == true) {
170: /* headed for execve() */
171: sudo_debug_execve(SUDO_DEBUG_INFO, details->command,
172: details->argv, details->envp);
173: if (details->closefrom >= 0) {
1.1.1.6 ! misho 174: /* Preserve debug fd and error pipe as needed. */
! 175: int debug_fd = sudo_debug_fd_get();
! 176: if (debug_fd != -1)
! 177: add_preserved_fd(&details->preserved_fds, debug_fd);
! 178: if (errfd != -1)
! 179: add_preserved_fd(&details->preserved_fds, errfd);
! 180:
! 181: /* Close all fds except those explicitly preserved. */
! 182: closefrom_except(details->closefrom, &details->preserved_fds);
1.1.1.4 misho 183: }
184: #ifdef HAVE_SELINUX
185: if (ISSET(details->flags, CD_RBAC_ENABLED)) {
186: selinux_execve(details->command, details->argv, details->envp,
187: ISSET(details->flags, CD_NOEXEC));
188: } else
189: #endif
190: {
191: sudo_execve(details->command, details->argv, details->envp,
192: ISSET(details->flags, CD_NOEXEC));
193: }
194: cstat->type = CMD_ERRNO;
195: cstat->val = errno;
196: sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s",
197: details->command, strerror(errno));
198: }
1.1.1.2 misho 199: debug_return;
1.1 misho 200: }
201:
1.1.1.6 ! misho 202: static void
! 203: backchannel_cb(int fd, int what, void *v)
! 204: {
! 205: struct exec_closure *ec = v;
! 206: ssize_t n;
! 207: debug_decl(backchannel_cb, SUDO_DEBUG_EXEC)
! 208:
! 209: /* read child status */
! 210: n = recv(fd, ec->cstat, sizeof(struct command_status), MSG_WAITALL);
! 211: if (n != sizeof(struct command_status)) {
! 212: if (n == -1) {
! 213: switch (errno) {
! 214: case EINTR:
! 215: /* got a signal, restart loop to service it. */
! 216: sudo_ev_loopcontinue(ec->evbase);
! 217: break;
! 218: case EAGAIN:
! 219: /* not ready after all... */
! 220: break;
! 221: default:
! 222: ec->cstat->type = CMD_ERRNO;
! 223: ec->cstat->val = errno;
! 224: sudo_debug_printf(SUDO_DEBUG_ERROR,
! 225: "failed to read child status: %s", strerror(errno));
! 226: sudo_ev_loopbreak(ec->evbase);
! 227: break;
! 228: }
! 229: } else {
! 230: /* Short read or EOF. */
! 231: sudo_debug_printf(SUDO_DEBUG_ERROR,
! 232: "failed to read child status: %s", n ? "short read" : "EOF");
! 233: if (!ec->log_io && n == 0) {
! 234: /*
! 235: * If not logging I/O we may get EOF when the command is
! 236: * executed and the other end of the backchannel is closed.
! 237: * Just remove the event in this case.
! 238: */
! 239: (void)sudo_ev_del(ec->evbase, backchannel_event);
! 240: } else {
! 241: /* XXX - need new CMD_ type for monitor errors. */
! 242: errno = n ? EIO : ECONNRESET;
! 243: ec->cstat->type = CMD_ERRNO;
! 244: ec->cstat->val = errno;
! 245: sudo_ev_loopbreak(ec->evbase);
! 246: }
! 247: }
! 248: debug_return;
! 249: }
! 250: switch (ec->cstat->type) {
! 251: case CMD_PID:
! 252: /*
! 253: * Once we know the command's pid we can unblock
! 254: * signals which ere blocked in fork_pty(). This
! 255: * avoids a race between exec of the command and
! 256: * receipt of a fatal signal from it.
! 257: */
! 258: cmnd_pid = ec->cstat->val;
! 259: sudo_debug_printf(SUDO_DEBUG_INFO, "executed %s, pid %d",
! 260: ec->details->command, (int)cmnd_pid);
! 261: if (ec->log_io)
! 262: sigprocmask(SIG_SETMASK, &ec->omask, NULL);
! 263: break;
! 264: case CMD_WSTATUS:
! 265: if (WIFSTOPPED(ec->cstat->val)) {
! 266: /* Suspend parent and tell child how to resume on return. */
! 267: sudo_debug_printf(SUDO_DEBUG_INFO,
! 268: "child stopped, suspending parent");
! 269: n = suspend_parent(WSTOPSIG(ec->cstat->val));
! 270: schedule_signal(ec->evbase, n);
! 271: /* Re-enable I/O events and restart event loop to service signal. */
! 272: add_io_events(ec->evbase);
! 273: sudo_ev_loopcontinue(ec->evbase);
! 274: } else {
! 275: /* Child exited or was killed, either way we are done. */
! 276: sudo_debug_printf(SUDO_DEBUG_INFO, "child exited or was killed");
! 277: sudo_ev_loopexit(ec->evbase);
! 278: }
! 279: break;
! 280: case CMD_ERRNO:
! 281: /* Child was unable to execute command or broken pipe. */
! 282: sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s",
! 283: strerror(ec->cstat->val));
! 284: sudo_ev_loopbreak(ec->evbase);
! 285: break;
! 286: }
! 287: debug_return;
! 288: }
! 289:
! 290: /*
! 291: * Setup initial exec events.
! 292: * Allocates events for the signal pipe and backchannel.
! 293: * Forwarded signals on the backchannel are enabled on demand.
! 294: */
! 295: static struct sudo_event_base *
! 296: exec_event_setup(int backchannel, struct exec_closure *ec)
! 297: {
! 298: struct sudo_event_base *evbase;
! 299: debug_decl(exec_event_setup, SUDO_DEBUG_EXEC)
! 300:
! 301: evbase = sudo_ev_base_alloc();
! 302: if (evbase == NULL)
! 303: fatal(NULL);
! 304:
! 305: /* Event for incoming signals via signal_pipe. */
! 306: signal_event = sudo_ev_alloc(signal_pipe[0],
! 307: SUDO_EV_READ|SUDO_EV_PERSIST, signal_pipe_cb, ec);
! 308: if (signal_event == NULL)
! 309: fatal(NULL);
! 310: if (sudo_ev_add(evbase, signal_event, NULL, false) == -1)
! 311: fatal(U_("unable to add event to queue"));
! 312:
! 313: /* Event for command status via backchannel. */
! 314: backchannel_event = sudo_ev_alloc(backchannel,
! 315: SUDO_EV_READ|SUDO_EV_PERSIST, backchannel_cb, ec);
! 316: if (backchannel_event == NULL)
! 317: fatal(NULL);
! 318: if (sudo_ev_add(evbase, backchannel_event, NULL, false) == -1)
! 319: fatal(U_("unable to add event to queue"));
! 320:
! 321: /* The signal forwarding event gets added on demand. */
! 322: sigfwd_event = sudo_ev_alloc(backchannel,
! 323: SUDO_EV_WRITE, forward_signals, NULL);
! 324: if (sigfwd_event == NULL)
! 325: fatal(NULL);
! 326:
! 327: sudo_debug_printf(SUDO_DEBUG_INFO, "signal pipe fd %d\n", signal_pipe[0]);
! 328: sudo_debug_printf(SUDO_DEBUG_INFO, "backchannel fd %d\n", backchannel);
! 329:
! 330: debug_return_ptr(evbase);
! 331: }
! 332:
1.1 misho 333: /*
1.1.1.4 misho 334: * Execute a command, potentially in a pty with I/O loggging, and
335: * wait for it to finish.
1.1 misho 336: * This is a little bit tricky due to how POSIX job control works and
337: * we fact that we have two different controlling terminals to deal with.
338: */
339: int
1.1.1.2 misho 340: sudo_execute(struct command_details *details, struct command_status *cstat)
1.1 misho 341: {
1.1.1.6 ! misho 342: struct sigforward *sigfwd, *sigfwd_next;
1.1 misho 343: const char *utmp_user = NULL;
1.1.1.6 ! misho 344: struct sudo_event_base *evbase;
! 345: struct exec_closure ec;
1.1.1.2 misho 346: bool log_io = false;
1.1 misho 347: sigaction_t sa;
348: pid_t child;
1.1.1.6 ! misho 349: int sv[2];
1.1.1.2 misho 350: debug_decl(sudo_execute, SUDO_DEBUG_EXEC)
1.1 misho 351:
1.1.1.4 misho 352: dispatch_pending_signals(cstat);
353:
1.1 misho 354: /* If running in background mode, fork and exit. */
355: if (ISSET(details->flags, CD_BACKGROUND)) {
1.1.1.2 misho 356: switch (sudo_debug_fork()) {
1.1 misho 357: case -1:
358: cstat->type = CMD_ERRNO;
359: cstat->val = errno;
1.1.1.2 misho 360: debug_return_int(-1);
1.1 misho 361: case 0:
362: /* child continues without controlling terminal */
363: (void)setpgid(0, 0);
364: break;
365: default:
366: /* parent exits (but does not flush buffers) */
1.1.1.2 misho 367: sudo_debug_exit_int(__func__, __FILE__, __LINE__,
368: sudo_debug_subsys, 0);
1.1 misho 369: _exit(0);
370: }
371: }
372:
373: /*
374: * If we have an I/O plugin or the policy plugin has requested one, we
375: * need to allocate a pty. It is OK to set log_io in the pty-only case
376: * as the io plugin tailqueue will be empty and no I/O logging will occur.
377: */
1.1.1.6 ! misho 378: if (!TAILQ_EMPTY(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) {
1.1.1.2 misho 379: log_io = true;
1.1 misho 380: if (ISSET(details->flags, CD_SET_UTMP))
381: utmp_user = details->utmp_user ? details->utmp_user : user_details.username;
1.1.1.2 misho 382: sudo_debug_printf(SUDO_DEBUG_INFO, "allocate pty for I/O logging");
1.1 misho 383: pty_setup(details->euid, user_details.tty, utmp_user);
1.1.1.6 ! misho 384: } else if (!ISSET(details->flags, CD_SET_TIMEOUT|CD_SUDOEDIT) &&
1.1.1.4 misho 385: policy_plugin.u.policy->close == NULL) {
1.1.1.6 ! misho 386: /*
! 387: * If there is no policy close function, no I/O logging or pty,
! 388: * and we were not invoked as sudoedit, just exec directly.
! 389: */
! 390: exec_cmnd(details, cstat, -1);
1.1.1.4 misho 391: goto done;
1.1 misho 392: }
393:
394: /*
395: * We communicate with the child over a bi-directional pair of sockets.
396: * Parent sends signal info to child and child sends back wait status.
397: */
1.1.1.6 ! misho 398: if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1)
! 399: fatal(U_("unable to create sockets"));
1.1 misho 400:
401: /*
1.1.1.2 misho 402: * Signals to forward to the child process (excluding SIGALRM and SIGCHLD).
1.1.1.4 misho 403: * We block all other signals while running the signal handler.
1.1 misho 404: * Note: HP-UX select() will not be interrupted if SA_RESTART set.
405: */
1.1.1.4 misho 406: memset(&sa, 0, sizeof(sa));
407: sigfillset(&sa.sa_mask);
1.1 misho 408: sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
1.1.1.3 misho 409: #ifdef SA_SIGINFO
410: sa.sa_flags |= SA_SIGINFO;
411: sa.sa_sigaction = handler;
412: #else
1.1 misho 413: sa.sa_handler = handler;
1.1.1.3 misho 414: #endif
1.1.1.4 misho 415: sudo_sigaction(SIGTERM, &sa, NULL);
416: sudo_sigaction(SIGALRM, &sa, NULL); /* XXX - only if there is a timeout */
417: sudo_sigaction(SIGCHLD, &sa, NULL);
418: sudo_sigaction(SIGPIPE, &sa, NULL);
419: sudo_sigaction(SIGUSR1, &sa, NULL);
420: sudo_sigaction(SIGUSR2, &sa, NULL);
1.1 misho 421:
1.1.1.2 misho 422: /*
423: * When not running the command in a pty, we do not want to
424: * forward signals generated by the kernel that the child will
425: * already have received either by virtue of being in the
426: * controlling tty's process group (SIGINT, SIGQUIT) or because
427: * the session is terminating (SIGHUP).
428: */
429: #ifdef SA_SIGINFO
430: if (!log_io) {
431: sa.sa_flags |= SA_SIGINFO;
1.1.1.3 misho 432: sa.sa_sigaction = handler_user_only;
1.1.1.2 misho 433: }
434: #endif
1.1.1.4 misho 435: sudo_sigaction(SIGHUP, &sa, NULL);
436: sudo_sigaction(SIGINT, &sa, NULL);
437: sudo_sigaction(SIGQUIT, &sa, NULL);
1.1.1.2 misho 438:
1.1 misho 439: /*
440: * Child will run the command in the pty, parent will pass data
1.1.1.6 ! misho 441: * to and from pty.
1.1 misho 442: */
443: if (log_io)
1.1.1.6 ! misho 444: child = fork_pty(details, sv, &ec.omask);
1.1 misho 445: else
446: child = fork_cmnd(details, sv);
447: close(sv[1]);
448:
449: /* Set command timeout if specified. */
450: if (ISSET(details->flags, CD_SET_TIMEOUT))
451: alarm(details->timeout);
452:
453: /*
454: * I/O logging must be in the C locale for floating point numbers
455: * to be logged consistently.
456: */
457: setlocale(LC_ALL, "C");
458:
459: /*
1.1.1.6 ! misho 460: * Allocate event base and two persistent events:
! 461: * the signal pipe and the child process's backchannel.
! 462: */
! 463: evbase = exec_event_setup(sv[0], &ec);
! 464:
! 465: /*
! 466: * Generic exec closure used for signal_pipe and backchannel callbacks.
! 467: * Note ec.omask is set earlier.
! 468: */
! 469: ec.child = child;
! 470: ec.log_io = log_io;
! 471: ec.cstat = cstat;
! 472: ec.evbase = evbase;
! 473: ec.details = details;
! 474:
! 475: /*
1.1 misho 476: * In the event loop we pass input from user tty to master
477: * and pass output from master to stdout and IO plugin.
478: */
1.1.1.6 ! misho 479: if (log_io)
! 480: add_io_events(evbase);
! 481: if (sudo_ev_loop(evbase, 0) == -1)
! 482: warning(U_("error in event loop"));
! 483: if (sudo_ev_got_break(evbase)) {
! 484: /* error from callback */
! 485: sudo_debug_printf(SUDO_DEBUG_ERROR, "event loop exited prematurely");
! 486: /* kill command if still running and not I/O logging */
! 487: if (!log_io && kill(child, 0) == 0)
! 488: terminate_command(child, true);
1.1 misho 489: }
490:
491: if (log_io) {
492: /* Flush any remaining output and free pty-related memory. */
493: pty_close(cstat);
494: }
495:
496: #ifdef HAVE_SELINUX
497: if (ISSET(details->flags, CD_RBAC_ENABLED)) {
498: /* This is probably not needed in log_io mode. */
499: if (selinux_restore_tty() != 0)
1.1.1.6 ! misho 500: warningx(U_("unable to restore tty label"));
1.1 misho 501: }
502: #endif
503:
1.1.1.6 ! misho 504: /* Free things up. */
! 505: sudo_ev_base_free(evbase);
! 506: sudo_ev_free(sigfwd_event);
! 507: sudo_ev_free(signal_event);
! 508: sudo_ev_free(backchannel_event);
! 509: TAILQ_FOREACH_SAFE(sigfwd, &sigfwd_list, entries, sigfwd_next) {
1.1 misho 510: efree(sigfwd);
511: }
1.1.1.6 ! misho 512: TAILQ_INIT(&sigfwd_list);
1.1.1.4 misho 513: done:
1.1.1.2 misho 514: debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0);
1.1 misho 515: }
516:
517: /*
1.1.1.6 ! misho 518: * Forward a signal to the command (non-pty version).
1.1 misho 519: */
520: static int
1.1.1.6 ! misho 521: dispatch_signal(struct sudo_event_base *evbase, pid_t child,
! 522: int signo, char *signame, struct command_status *cstat)
1.1 misho 523: {
1.1.1.6 ! misho 524: int rc = 1;
! 525: debug_decl(dispatch_signal, SUDO_DEBUG_EXEC)
! 526:
! 527: sudo_debug_printf(SUDO_DEBUG_INFO,
! 528: "%s: evbase %p, child: %d, signo %s(%d), cstat %p",
! 529: __func__, evbase, (int)child, signame, signo, cstat);
! 530:
! 531: if (signo == SIGCHLD) {
! 532: pid_t pid;
! 533: int status;
! 534: /*
! 535: * The command stopped or exited.
! 536: */
! 537: do {
! 538: pid = waitpid(child, &status, WUNTRACED|WNOHANG);
! 539: } while (pid == -1 && errno == EINTR);
! 540: if (pid == child) {
! 541: if (WIFSTOPPED(status)) {
! 542: /*
! 543: * Save the controlling terminal's process group
! 544: * so we can restore it after we resume, if needed.
! 545: * Most well-behaved shells change the pgrp back to
! 546: * its original value before suspending so we must
! 547: * not try to restore in that case, lest we race with
! 548: * the child upon resume, potentially stopping sudo
! 549: * with SIGTTOU while the command continues to run.
! 550: */
! 551: sigaction_t sa, osa;
! 552: pid_t saved_pgrp = (pid_t)-1;
! 553: int signo = WSTOPSIG(status);
! 554: int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
! 555: if (fd != -1) {
! 556: saved_pgrp = tcgetpgrp(fd);
! 557: /*
! 558: * Child was stopped trying to access controlling
! 559: * terminal. If the child has a different pgrp
! 560: * and we own the controlling terminal, give it
! 561: * to the child's pgrp and let it continue.
! 562: */
! 563: if (signo == SIGTTOU || signo == SIGTTIN) {
! 564: if (saved_pgrp == ppgrp) {
! 565: pid_t child_pgrp = getpgid(child);
! 566: if (child_pgrp != ppgrp) {
! 567: if (tcsetpgrp(fd, child_pgrp) == 0) {
! 568: if (killpg(child_pgrp, SIGCONT) != 0) {
! 569: warning("kill(%d, SIGCONT)",
! 570: (int)child_pgrp);
! 571: }
! 572: close(fd);
! 573: goto done;
! 574: }
! 575: }
! 576: }
! 577: }
! 578: }
! 579: if (signo == SIGTSTP) {
! 580: memset(&sa, 0, sizeof(sa));
! 581: sigemptyset(&sa.sa_mask);
! 582: sa.sa_flags = SA_RESTART;
! 583: sa.sa_handler = SIG_DFL;
! 584: sudo_sigaction(SIGTSTP, &sa, &osa);
! 585: }
! 586: if (kill(getpid(), signo) != 0)
! 587: warning("kill(%d, SIG%s)", (int)getpid(), signame);
! 588: if (signo == SIGTSTP)
! 589: sudo_sigaction(SIGTSTP, &osa, NULL);
! 590: if (fd != -1) {
! 591: /*
! 592: * Restore command's process group if different.
! 593: * Otherwise, we cannot resume some shells.
! 594: */
! 595: if (saved_pgrp != ppgrp)
! 596: (void)tcsetpgrp(fd, saved_pgrp);
! 597: close(fd);
! 598: }
! 599: } else {
! 600: /* Child has exited or been killed, we are done. */
! 601: cstat->type = CMD_WSTATUS;
! 602: cstat->val = status;
! 603: sudo_ev_loopexit(evbase);
! 604: goto done;
! 605: }
! 606: }
! 607: } else {
! 608: /* Send signal to child. */
! 609: if (signo == SIGALRM) {
! 610: terminate_command(child, false);
! 611: } else if (kill(child, signo) != 0) {
! 612: warning("kill(%d, SIG%s)", (int)child, signame);
! 613: }
! 614: }
! 615: rc = 0;
! 616: done:
! 617: debug_return_int(rc);
! 618: }
! 619:
! 620: /*
! 621: * Forward a signal to the monitory (pty version).
! 622: */
! 623: static int
! 624: dispatch_signal_pty(struct sudo_event_base *evbase, pid_t child,
! 625: int signo, char *signame, struct command_status *cstat)
! 626: {
! 627: int rc = 1;
! 628: debug_decl(dispatch_signal_pty, SUDO_DEBUG_EXEC)
! 629:
! 630: sudo_debug_printf(SUDO_DEBUG_INFO,
! 631: "%s: evbase %p, child: %d, signo %s(%d), cstat %p",
! 632: __func__, evbase, (int)child, signame, signo, cstat);
! 633:
! 634: if (signo == SIGCHLD) {
! 635: int n, status;
! 636: pid_t pid;
! 637: /*
! 638: * Monitor process was signaled; wait for it as needed.
! 639: */
! 640: do {
! 641: pid = waitpid(child, &status, WUNTRACED|WNOHANG);
! 642: } while (pid == -1 && errno == EINTR);
! 643: if (pid == child) {
! 644: /*
! 645: * If the monitor dies we get notified via backchannel_cb().
! 646: * If it was stopped, we should stop too (the command keeps
! 647: * running in its pty) and continue it when we come back.
! 648: */
! 649: if (WIFSTOPPED(status)) {
! 650: sudo_debug_printf(SUDO_DEBUG_INFO,
! 651: "monitor stopped, suspending parent");
! 652: n = suspend_parent(WSTOPSIG(status));
! 653: kill(pid, SIGCONT);
! 654: schedule_signal(evbase, n);
! 655: /* Re-enable I/O events and restart event loop. */
! 656: add_io_events(evbase);
! 657: sudo_ev_loopcontinue(evbase);
! 658: goto done;
! 659: } else if (WIFSIGNALED(status)) {
! 660: sudo_debug_printf(SUDO_DEBUG_INFO,
! 661: "monitor killed, signal %d", WTERMSIG(status));
! 662: } else {
! 663: sudo_debug_printf(SUDO_DEBUG_INFO,
! 664: "monitor exited, status %d", WEXITSTATUS(status));
! 665: }
! 666: }
! 667: } else {
! 668: /* Schedule signo to be forwared to the child. */
! 669: schedule_signal(evbase, signo);
! 670: /* Restart event loop to service signal immediately. */
! 671: sudo_ev_loopcontinue(evbase);
! 672: }
! 673: rc = 0;
! 674: done:
! 675: debug_return_int(rc);
! 676: }
! 677:
! 678: /* Signal pipe callback */
! 679: static void
! 680: signal_pipe_cb(int fd, int what, void *v)
! 681: {
! 682: struct exec_closure *ec = v;
1.1.1.3 misho 683: char signame[SIG2STR_MAX];
1.1 misho 684: unsigned char signo;
685: ssize_t nread;
1.1.1.6 ! misho 686: int rc = 0;
! 687: debug_decl(signal_pipe_cb, SUDO_DEBUG_EXEC)
1.1 misho 688:
1.1.1.6 ! misho 689: do {
1.1 misho 690: /* read signal pipe */
1.1.1.6 ! misho 691: nread = read(fd, &signo, sizeof(signo));
1.1 misho 692: if (nread <= 0) {
1.1.1.6 ! misho 693: /* It should not be possible to get EOF but just in case... */
1.1 misho 694: if (nread == 0)
695: errno = ECONNRESET;
696: /* Restart if interrupted by signal so the pipe doesn't fill. */
697: if (errno == EINTR)
698: continue;
1.1.1.6 ! misho 699: /* On error, store errno and break out of the event loop. */
! 700: if (errno != EAGAIN) {
! 701: sudo_debug_printf(SUDO_DEBUG_ERROR,
! 702: "error reading signal pipe %s", strerror(errno));
! 703: ec->cstat->type = CMD_ERRNO;
! 704: ec->cstat->val = errno;
! 705: sudo_ev_loopbreak(ec->evbase);
! 706: }
! 707: break;
1.1 misho 708: }
1.1.1.3 misho 709: if (sig2str(signo, signame) == -1)
710: snprintf(signame, sizeof(signame), "%d", signo);
711: sudo_debug_printf(SUDO_DEBUG_DIAG, "received SIG%s", signame);
1.1.1.6 ! misho 712: if (ec->log_io) {
! 713: rc = dispatch_signal_pty(ec->evbase, ec->child, signo, signame,
! 714: ec->cstat);
1.1 misho 715: } else {
1.1.1.6 ! misho 716: rc = dispatch_signal(ec->evbase, ec->child, signo, signame,
! 717: ec->cstat);
1.1 misho 718: }
1.1.1.6 ! misho 719: } while (rc == 0);
! 720: debug_return;
1.1 misho 721: }
722:
723: /*
1.1.1.4 misho 724: * Drain pending signals from signale_pipe written by sudo_handler().
725: * Handles the case where the signal was sent to us before
726: * we have executed the command.
727: * Returns 1 if we should terminate, else 0.
728: */
729: static int
730: dispatch_pending_signals(struct command_status *cstat)
731: {
732: ssize_t nread;
733: struct sigaction sa;
734: unsigned char signo = 0;
735: int rval = 0;
736: debug_decl(dispatch_pending_signals, SUDO_DEBUG_EXEC)
737:
738: for (;;) {
739: nread = read(signal_pipe[0], &signo, sizeof(signo));
740: if (nread <= 0) {
741: /* It should not be possible to get EOF but just in case. */
742: if (nread == 0)
743: errno = ECONNRESET;
744: /* Restart if interrupted by signal so the pipe doesn't fill. */
745: if (errno == EINTR)
746: continue;
747: /* If pipe is empty, we are done. */
748: if (errno == EAGAIN)
749: break;
750: sudo_debug_printf(SUDO_DEBUG_ERROR, "error reading signal pipe %s",
751: strerror(errno));
752: cstat->type = CMD_ERRNO;
753: cstat->val = errno;
754: rval = 1;
755: break;
756: }
757: /* Take the first terminal signal. */
758: if (signo == SIGINT || signo == SIGQUIT) {
759: cstat->type = CMD_WSTATUS;
760: cstat->val = signo + 128;
761: rval = 1;
762: break;
763: }
764: }
765: /* Only stop if we haven't already been terminated. */
766: if (signo == SIGTSTP)
767: {
768: memset(&sa, 0, sizeof(sa));
769: sigemptyset(&sa.sa_mask);
770: sa.sa_flags = SA_RESTART;
771: sa.sa_handler = SIG_DFL;
772: sudo_sigaction(SIGTSTP, &sa, NULL);
773: if (kill(getpid(), SIGTSTP) != 0)
774: warning("kill(%d, SIGTSTP)", (int)getpid());
775: /* No need to reinstall SIGTSTP handler. */
776: }
777: debug_return_int(rval);
778: }
779:
780: /*
1.1 misho 781: * Forward signals in sigfwd_list to child listening on fd.
782: */
783: static void
1.1.1.6 ! misho 784: forward_signals(int sock, int what, void *v)
1.1 misho 785: {
1.1.1.3 misho 786: char signame[SIG2STR_MAX];
1.1 misho 787: struct sigforward *sigfwd;
788: struct command_status cstat;
789: ssize_t nsent;
1.1.1.2 misho 790: debug_decl(forward_signals, SUDO_DEBUG_EXEC)
1.1 misho 791:
1.1.1.6 ! misho 792: while (!TAILQ_EMPTY(&sigfwd_list)) {
! 793: sigfwd = TAILQ_FIRST(&sigfwd_list);
1.1.1.4 misho 794: if (sigfwd->signo == SIGCONT_FG)
795: strlcpy(signame, "CONT_FG", sizeof(signame));
796: else if (sigfwd->signo == SIGCONT_BG)
797: strlcpy(signame, "CONT_BG", sizeof(signame));
798: else if (sig2str(sigfwd->signo, signame) == -1)
1.1.1.3 misho 799: snprintf(signame, sizeof(signame), "%d", sigfwd->signo);
1.1.1.2 misho 800: sudo_debug_printf(SUDO_DEBUG_INFO,
1.1.1.3 misho 801: "sending SIG%s to child over backchannel", signame);
1.1 misho 802: cstat.type = CMD_SIGNO;
803: cstat.val = sigfwd->signo;
804: do {
805: nsent = send(sock, &cstat, sizeof(cstat), 0);
806: } while (nsent == -1 && errno == EINTR);
1.1.1.6 ! misho 807: TAILQ_REMOVE(&sigfwd_list, sigfwd, entries);
1.1 misho 808: efree(sigfwd);
809: if (nsent != sizeof(cstat)) {
810: if (errno == EPIPE) {
1.1.1.6 ! misho 811: struct sigforward *sigfwd_next;
1.1.1.2 misho 812: sudo_debug_printf(SUDO_DEBUG_ERROR,
813: "broken pipe writing to child over backchannel");
1.1 misho 814: /* Other end of socket gone, empty out sigfwd_list. */
1.1.1.6 ! misho 815: TAILQ_FOREACH_SAFE(sigfwd, &sigfwd_list, entries, sigfwd_next) {
1.1 misho 816: efree(sigfwd);
817: }
1.1.1.6 ! misho 818: TAILQ_INIT(&sigfwd_list);
1.1.1.2 misho 819: /* XXX - child (monitor) is dead, we should exit too? */
1.1 misho 820: }
821: break;
822: }
823: }
824: }
825:
826: /*
1.1.1.6 ! misho 827: * Schedule a signal to be forwarded.
1.1 misho 828: */
829: static void
1.1.1.6 ! misho 830: schedule_signal(struct sudo_event_base *evbase, int signo)
1.1 misho 831: {
832: struct sigforward *sigfwd;
1.1.1.3 misho 833: char signame[SIG2STR_MAX];
1.1.1.2 misho 834: debug_decl(schedule_signal, SUDO_DEBUG_EXEC)
1.1 misho 835:
1.1.1.4 misho 836: if (signo == SIGCONT_FG)
837: strlcpy(signame, "CONT_FG", sizeof(signame));
838: else if (signo == SIGCONT_BG)
839: strlcpy(signame, "CONT_BG", sizeof(signame));
840: else if (sig2str(signo, signame) == -1)
1.1.1.3 misho 841: snprintf(signame, sizeof(signame), "%d", signo);
1.1.1.4 misho 842: sudo_debug_printf(SUDO_DEBUG_DIAG, "scheduled SIG%s for child", signame);
1.1.1.2 misho 843:
844: sigfwd = ecalloc(1, sizeof(*sigfwd));
1.1 misho 845: sigfwd->signo = signo;
1.1.1.6 ! misho 846: TAILQ_INSERT_TAIL(&sigfwd_list, sigfwd, entries);
! 847:
! 848: if (sudo_ev_add(evbase, sigfwd_event, NULL, true) == -1)
! 849: fatal(U_("unable to add event to queue"));
1.1.1.2 misho 850:
851: debug_return;
1.1 misho 852: }
853:
854: /*
855: * Generic handler for signals passed from parent -> child.
856: * The other end of signal_pipe is checked in the main event loop.
857: */
1.1.1.3 misho 858: #ifdef SA_SIGINFO
859: void
860: handler(int s, siginfo_t *info, void *context)
861: {
862: unsigned char signo = (unsigned char)s;
863:
864: /*
865: * If the signal came from the command we ran, just ignore
866: * it since we don't want the child to indirectly kill itself.
867: * This can happen with, e.g. BSD-derived versions of reboot
868: * that call kill(-1, SIGTERM) to kill all other processes.
869: */
870: if (info != NULL && info->si_code == SI_USER && info->si_pid == cmnd_pid)
871: return;
872:
873: /*
874: * The pipe is non-blocking, if we overflow the kernel's pipe
875: * buffer we drop the signal. This is not a problem in practice.
876: */
877: ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
878: }
879: #else
1.1 misho 880: void
881: handler(int s)
882: {
883: unsigned char signo = (unsigned char)s;
884:
885: /*
886: * The pipe is non-blocking, if we overflow the kernel's pipe
887: * buffer we drop the signal. This is not a problem in practice.
888: */
1.1.1.2 misho 889: ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
890: }
1.1.1.3 misho 891: #endif
1.1.1.2 misho 892:
893: #ifdef SA_SIGINFO
894: /*
895: * Generic handler for signals passed from parent -> child.
896: * The other end of signal_pipe is checked in the main event loop.
897: * This version is for the non-pty case and does not forward
898: * signals that are generated by the kernel.
899: */
900: static void
1.1.1.3 misho 901: handler_user_only(int s, siginfo_t *info, void *context)
1.1.1.2 misho 902: {
903: unsigned char signo = (unsigned char)s;
904:
905: /* Only forward user-generated signals. */
1.1.1.3 misho 906: if (info != NULL && info->si_code == SI_USER) {
1.1.1.2 misho 907: /*
908: * The pipe is non-blocking, if we overflow the kernel's pipe
909: * buffer we drop the signal. This is not a problem in practice.
910: */
911: ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
912: }
1.1 misho 913: }
1.1.1.2 misho 914: #endif /* SA_SIGINFO */
1.1 misho 915:
916: /*
917: * Open a pipe and make both ends non-blocking.
918: * Returns 0 on success and -1 on error.
919: */
920: int
921: pipe_nonblock(int fds[2])
922: {
923: int flags, rval;
1.1.1.2 misho 924: debug_decl(pipe_nonblock, SUDO_DEBUG_EXEC)
1.1 misho 925:
926: rval = pipe(fds);
927: if (rval != -1) {
928: flags = fcntl(fds[0], F_GETFL, 0);
929: if (flags != -1 && !ISSET(flags, O_NONBLOCK))
930: rval = fcntl(fds[0], F_SETFL, flags | O_NONBLOCK);
931: if (rval != -1) {
932: flags = fcntl(fds[1], F_GETFL, 0);
933: if (flags != -1 && !ISSET(flags, O_NONBLOCK))
934: rval = fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
935: }
936: if (rval == -1) {
937: close(fds[0]);
938: close(fds[1]);
939: }
940: }
941:
1.1.1.2 misho 942: debug_return_int(rval);
1.1 misho 943: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>