Annotation of embedaddon/sudo/src/exec.c, revision 1.1.1.3
1.1 misho 1: /*
1.1.1.2 misho 2: * Copyright (c) 2009-2012 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/param.h>
21: #ifdef HAVE_SYS_SYSMACROS_H
22: # include <sys/sysmacros.h>
23: #endif
24: #include <sys/socket.h>
25: #include <sys/stat.h>
26: #include <sys/time.h>
27: #include <sys/wait.h>
28: #include <sys/ioctl.h>
29: #ifdef HAVE_SYS_SELECT_H
30: # include <sys/select.h>
31: #endif /* HAVE_SYS_SELECT_H */
32: #include <stdio.h>
33: #ifdef STDC_HEADERS
34: # include <stdlib.h>
35: # include <stddef.h>
36: #else
37: # ifdef HAVE_STDLIB_H
38: # include <stdlib.h>
39: # endif
40: #endif /* STDC_HEADERS */
41: #ifdef HAVE_STRING_H
42: # include <string.h>
43: #endif /* HAVE_STRING_H */
44: #ifdef HAVE_STRINGS_H
45: # include <strings.h>
46: #endif /* HAVE_STRINGS_H */
47: #ifdef HAVE_UNISTD_H
48: # include <unistd.h>
49: #endif /* HAVE_UNISTD_H */
50: #if TIME_WITH_SYS_TIME
51: # include <time.h>
52: #endif
53: #ifdef HAVE_SETLOCALE
54: # include <locale.h>
55: #endif
56: #include <errno.h>
57: #include <fcntl.h>
58: #include <signal.h>
59: #include <termios.h>
60:
61: #include "sudo.h"
62: #include "sudo_exec.h"
63: #include "sudo_plugin.h"
64: #include "sudo_plugin_int.h"
65:
66: /* Shared with exec_pty.c for use with handler(). */
67: int signal_pipe[2];
68:
69: /* We keep a tailq of signals to forward to child. */
70: struct sigforward {
71: struct sigforward *prev, *next;
72: int signo;
73: };
74: TQ_DECLARE(sigforward)
75: static struct sigforward_list sigfwd_list;
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.2 misho 80: static int handle_signals(int sv[2], pid_t child, int log_io,
1.1 misho 81: struct command_status *cstat);
82: static void forward_signals(int fd);
83: static void schedule_signal(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 misho 113: zero_bytes(&sa, sizeof(sa));
114: sigemptyset(&sa.sa_mask);
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 misho 122: sigaction(SIGCONT, &sa, NULL);
1.1.1.3 ! misho 123: #ifdef SA_SIGINFO
! 124: sa.sa_sigaction = handler_user_only;
! 125: #endif
! 126: 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)
133: errorx(1, _("policy plugin failed session initialization"));
134:
1.1.1.3 ! misho 135: cmnd_pid = sudo_debug_fork();
! 136: switch (cmnd_pid) {
1.1 misho 137: case -1:
138: error(1, _("unable to fork"));
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);
146: restore_signals();
1.1.1.2 misho 147: if (exec_setup(details, NULL, -1) == true) {
1.1 misho 148: /* headed for execve() */
1.1.1.2 misho 149: sudo_debug_execve(SUDO_DEBUG_INFO, details->command,
150: details->argv, details->envp);
151: if (details->closefrom >= 0) {
152: int maxfd = details->closefrom;
153: dup2(sv[1], maxfd);
154: (void)fcntl(maxfd, F_SETFD, FD_CLOEXEC);
155: sv[1] = maxfd++;
156: if (sudo_debug_fd_set(maxfd) != -1)
157: maxfd++;
158: closefrom(maxfd);
159: }
1.1 misho 160: #ifdef HAVE_SELINUX
1.1.1.2 misho 161: if (ISSET(details->flags, CD_RBAC_ENABLED)) {
162: selinux_execve(details->command, details->argv, details->envp,
163: ISSET(details->flags, CD_NOEXEC));
164: } else
1.1 misho 165: #endif
1.1.1.2 misho 166: {
167: sudo_execve(details->command, details->argv, details->envp,
168: ISSET(details->flags, CD_NOEXEC));
169: }
170: sudo_debug_printf(SUDO_DEBUG_ERROR, "unable to exec %s: %s",
171: details->command, strerror(errno));
1.1 misho 172: }
173: cstat.type = CMD_ERRNO;
174: cstat.val = errno;
175: send(sv[1], &cstat, sizeof(cstat), 0);
1.1.1.2 misho 176: sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, 1);
1.1 misho 177: _exit(1);
178: }
1.1.1.3 ! misho 179: sudo_debug_printf(SUDO_DEBUG_INFO, "executed %s, pid %d", details->command,
! 180: (int)cmnd_pid);
! 181: debug_return_int(cmnd_pid);
1.1 misho 182: }
183:
184: static struct signal_state {
185: int signo;
186: sigaction_t sa;
187: } saved_signals[] = {
188: { SIGALRM },
189: { SIGCHLD },
190: { SIGCONT },
191: { SIGHUP },
192: { SIGINT },
193: { SIGPIPE },
194: { SIGQUIT },
195: { SIGTERM },
196: { SIGTSTP },
197: { SIGTTIN },
198: { SIGTTOU },
199: { SIGUSR1 },
200: { SIGUSR2 },
201: { -1 }
202: };
203:
204: /*
205: * Save signal handler state so it can be restored before exec.
206: */
207: void
208: save_signals(void)
209: {
210: struct signal_state *ss;
1.1.1.2 misho 211: debug_decl(save_signals, SUDO_DEBUG_EXEC)
1.1 misho 212:
213: for (ss = saved_signals; ss->signo != -1; ss++)
214: sigaction(ss->signo, NULL, &ss->sa);
1.1.1.2 misho 215:
216: debug_return;
1.1 misho 217: }
218:
219: /*
220: * Restore signal handlers to initial state.
221: */
222: void
223: restore_signals(void)
224: {
225: struct signal_state *ss;
1.1.1.2 misho 226: debug_decl(restore_signals, SUDO_DEBUG_EXEC)
1.1 misho 227:
228: for (ss = saved_signals; ss->signo != -1; ss++)
229: sigaction(ss->signo, &ss->sa, NULL);
1.1.1.2 misho 230:
231: debug_return;
1.1 misho 232: }
233:
234: /*
235: * Execute a command, potentially in a pty with I/O loggging.
236: * This is a little bit tricky due to how POSIX job control works and
237: * we fact that we have two different controlling terminals to deal with.
238: */
239: int
1.1.1.2 misho 240: sudo_execute(struct command_details *details, struct command_status *cstat)
1.1 misho 241: {
1.1.1.2 misho 242: int maxfd, n, nready, sv[2];
1.1 misho 243: const char *utmp_user = NULL;
1.1.1.2 misho 244: bool log_io = false;
1.1 misho 245: fd_set *fdsr, *fdsw;
246: sigaction_t sa;
1.1.1.3 ! misho 247: sigset_t omask;
1.1 misho 248: pid_t child;
1.1.1.2 misho 249: debug_decl(sudo_execute, SUDO_DEBUG_EXEC)
1.1 misho 250:
251: /* If running in background mode, fork and exit. */
252: if (ISSET(details->flags, CD_BACKGROUND)) {
1.1.1.2 misho 253: switch (sudo_debug_fork()) {
1.1 misho 254: case -1:
255: cstat->type = CMD_ERRNO;
256: cstat->val = errno;
1.1.1.2 misho 257: debug_return_int(-1);
1.1 misho 258: case 0:
259: /* child continues without controlling terminal */
260: (void)setpgid(0, 0);
261: break;
262: default:
263: /* parent exits (but does not flush buffers) */
1.1.1.2 misho 264: sudo_debug_exit_int(__func__, __FILE__, __LINE__,
265: sudo_debug_subsys, 0);
1.1 misho 266: _exit(0);
267: }
268: }
269:
270: /*
271: * If we have an I/O plugin or the policy plugin has requested one, we
272: * need to allocate a pty. It is OK to set log_io in the pty-only case
273: * as the io plugin tailqueue will be empty and no I/O logging will occur.
274: */
275: if (!tq_empty(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) {
1.1.1.2 misho 276: log_io = true;
1.1 misho 277: if (ISSET(details->flags, CD_SET_UTMP))
278: utmp_user = details->utmp_user ? details->utmp_user : user_details.username;
1.1.1.2 misho 279: sudo_debug_printf(SUDO_DEBUG_INFO, "allocate pty for I/O logging");
1.1 misho 280: pty_setup(details->euid, user_details.tty, utmp_user);
281: }
282:
283: /*
284: * We communicate with the child over a bi-directional pair of sockets.
285: * Parent sends signal info to child and child sends back wait status.
286: */
287: if (socketpair(PF_UNIX, SOCK_DGRAM, 0, sv) == -1)
288: error(1, _("unable to create sockets"));
289:
290: /*
291: * We use a pipe to atomically handle signal notification within
292: * the select() loop.
293: */
294: if (pipe_nonblock(signal_pipe) != 0)
295: error(1, _("unable to create pipe"));
296:
297: zero_bytes(&sa, sizeof(sa));
298: sigemptyset(&sa.sa_mask);
299:
300: /*
1.1.1.2 misho 301: * Signals to forward to the child process (excluding SIGALRM and SIGCHLD).
1.1 misho 302: * Note: HP-UX select() will not be interrupted if SA_RESTART set.
303: */
304: sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */
1.1.1.3 ! misho 305: #ifdef SA_SIGINFO
! 306: sa.sa_flags |= SA_SIGINFO;
! 307: sa.sa_sigaction = handler;
! 308: #else
1.1 misho 309: sa.sa_handler = handler;
1.1.1.3 ! misho 310: #endif
1.1 misho 311: sigaction(SIGALRM, &sa, NULL);
312: sigaction(SIGCHLD, &sa, NULL);
313: sigaction(SIGPIPE, &sa, NULL);
314: sigaction(SIGTERM, &sa, NULL);
315: sigaction(SIGUSR1, &sa, NULL);
316: sigaction(SIGUSR2, &sa, NULL);
317:
1.1.1.2 misho 318: /*
319: * When not running the command in a pty, we do not want to
320: * forward signals generated by the kernel that the child will
321: * already have received either by virtue of being in the
322: * controlling tty's process group (SIGINT, SIGQUIT) or because
323: * the session is terminating (SIGHUP).
324: */
325: #ifdef SA_SIGINFO
326: if (!log_io) {
327: sa.sa_flags |= SA_SIGINFO;
1.1.1.3 ! misho 328: sa.sa_sigaction = handler_user_only;
1.1.1.2 misho 329: }
330: #endif
331: sigaction(SIGHUP, &sa, NULL);
332: sigaction(SIGINT, &sa, NULL);
333: sigaction(SIGQUIT, &sa, NULL);
334:
1.1 misho 335: /* Max fd we will be selecting on. */
336: maxfd = MAX(sv[0], signal_pipe[0]);
337:
338: /*
339: * Child will run the command in the pty, parent will pass data
340: * to and from pty. Adjusts maxfd as needed.
341: */
342: if (log_io)
1.1.1.3 ! misho 343: child = fork_pty(details, sv, &maxfd, &omask);
1.1 misho 344: else
345: child = fork_cmnd(details, sv);
346: close(sv[1]);
347:
348: /* Set command timeout if specified. */
349: if (ISSET(details->flags, CD_SET_TIMEOUT))
350: alarm(details->timeout);
351:
352: #ifdef HAVE_SETLOCALE
353: /*
354: * I/O logging must be in the C locale for floating point numbers
355: * to be logged consistently.
356: */
357: setlocale(LC_ALL, "C");
358: #endif
359:
360: /*
361: * In the event loop we pass input from user tty to master
362: * and pass output from master to stdout and IO plugin.
363: */
1.1.1.2 misho 364: fdsr = emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
365: fdsw = emalloc2(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask));
1.1 misho 366: for (;;) {
1.1.1.2 misho 367: memset(fdsw, 0, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
368: memset(fdsr, 0, howmany(maxfd + 1, NFDBITS) * sizeof(fd_mask));
1.1 misho 369:
370: FD_SET(signal_pipe[0], fdsr);
371: FD_SET(sv[0], fdsr);
372: if (!tq_empty(&sigfwd_list))
373: FD_SET(sv[0], fdsw);
374: if (log_io)
375: fd_set_iobs(fdsr, fdsw); /* XXX - better name */
376: nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL);
1.1.1.2 misho 377: sudo_debug_printf(SUDO_DEBUG_DEBUG, "select returns %d", nready);
1.1 misho 378: if (nready == -1) {
1.1.1.2 misho 379: if (errno == EINTR || errno == ENOMEM)
1.1 misho 380: continue;
1.1.1.2 misho 381: if (errno == EBADF || errno == EIO) {
382: /* One of the ttys must have gone away. */
383: goto do_tty_io;
384: }
385: warning(_("select failed"));
386: sudo_debug_printf(SUDO_DEBUG_ERROR,
387: "select failure, terminating child");
388: schedule_signal(SIGKILL);
389: forward_signals(sv[0]);
390: break;
1.1 misho 391: }
392: if (FD_ISSET(sv[0], fdsw)) {
393: forward_signals(sv[0]);
394: }
395: if (FD_ISSET(signal_pipe[0], fdsr)) {
1.1.1.2 misho 396: n = handle_signals(sv, child, log_io, cstat);
1.1 misho 397: if (n == 0) {
398: /* Child has exited, cstat is set, we are done. */
1.1.1.2 misho 399: break;
1.1 misho 400: }
401: if (n == -1) {
402: /* Error reading signal_pipe[0], should not happen. */
403: break;
404: }
405: /* Restart event loop so signals get sent to child immediately. */
406: continue;
407: }
408: if (FD_ISSET(sv[0], fdsr)) {
409: /* read child status */
410: n = recv(sv[0], cstat, sizeof(*cstat), 0);
1.1.1.2 misho 411: if (n != sizeof(*cstat)) {
412: if (n == -1) {
413: if (errno == EINTR)
414: continue;
415: /*
416: * If not logging I/O we may receive ECONNRESET when
417: * the command is executed and sv is closed.
418: * It is safe to ignore this.
419: */
420: if (log_io && errno != EAGAIN) {
421: cstat->type = CMD_ERRNO;
422: cstat->val = errno;
423: break;
424: }
425: sudo_debug_printf(SUDO_DEBUG_ERROR,
426: "failed to read child status: %s", strerror(errno));
427: } else {
428: /* Short read or EOF. */
429: sudo_debug_printf(SUDO_DEBUG_ERROR,
430: "failed to read child status: %s",
431: n ? "short read" : "EOF");
432: /* XXX - should set cstat */
1.1 misho 433: break;
434: }
435: }
1.1.1.3 ! misho 436: if (cstat->type == CMD_PID) {
! 437: /*
! 438: * Once we know the command's pid we can unblock
! 439: * signals which ere blocked in fork_pty(). This
! 440: * avoids a race between exec of the command and
! 441: * receipt of a fatal signal from it.
! 442: */
! 443: cmnd_pid = cstat->val;
! 444: sudo_debug_printf(SUDO_DEBUG_INFO, "executed %s, pid %d",
! 445: details->command, (int)cmnd_pid);
! 446: if (log_io)
! 447: sigprocmask(SIG_SETMASK, &omask, NULL);
! 448: } else if (cstat->type == CMD_WSTATUS) {
1.1 misho 449: if (WIFSTOPPED(cstat->val)) {
450: /* Suspend parent and tell child how to resume on return. */
1.1.1.2 misho 451: sudo_debug_printf(SUDO_DEBUG_INFO,
452: "child stopped, suspending parent");
1.1 misho 453: n = suspend_parent(WSTOPSIG(cstat->val));
454: schedule_signal(n);
455: continue;
456: } else {
457: /* Child exited or was killed, either way we are done. */
1.1.1.2 misho 458: sudo_debug_printf(SUDO_DEBUG_INFO, "child exited or was killed");
1.1 misho 459: break;
460: }
461: } else if (cstat->type == CMD_ERRNO) {
462: /* Child was unable to execute command or broken pipe. */
1.1.1.2 misho 463: sudo_debug_printf(SUDO_DEBUG_INFO, "errno from child: %s",
464: strerror(cstat->val));
1.1 misho 465: break;
466: }
467: }
1.1.1.2 misho 468: do_tty_io:
1.1 misho 469: if (perform_io(fdsr, fdsw, cstat) != 0) {
470: /* I/O error, kill child if still alive and finish. */
1.1.1.2 misho 471: sudo_debug_printf(SUDO_DEBUG_ERROR, "I/O error, terminating child");
1.1 misho 472: schedule_signal(SIGKILL);
473: forward_signals(sv[0]);
474: break;
475: }
476: }
477:
478: if (log_io) {
479: /* Flush any remaining output and free pty-related memory. */
480: pty_close(cstat);
481: }
482:
483: #ifdef HAVE_SELINUX
484: if (ISSET(details->flags, CD_RBAC_ENABLED)) {
485: /* This is probably not needed in log_io mode. */
486: if (selinux_restore_tty() != 0)
487: warningx(_("unable to restore tty label"));
488: }
489: #endif
490:
491: efree(fdsr);
492: efree(fdsw);
493: while (!tq_empty(&sigfwd_list)) {
494: struct sigforward *sigfwd = tq_first(&sigfwd_list);
495: tq_remove(&sigfwd_list, sigfwd);
496: efree(sigfwd);
497: }
498:
1.1.1.2 misho 499: debug_return_int(cstat->type == CMD_ERRNO ? -1 : 0);
1.1 misho 500: }
501:
502: /*
503: * Read signals on fd written to by handler().
504: * Returns -1 on error, 0 on child exit, else 1.
505: */
506: static int
1.1.1.2 misho 507: handle_signals(int sv[2], pid_t child, int log_io, struct command_status *cstat)
1.1 misho 508: {
1.1.1.3 ! misho 509: char signame[SIG2STR_MAX];
1.1 misho 510: unsigned char signo;
511: ssize_t nread;
512: int status;
513: pid_t pid;
1.1.1.2 misho 514: debug_decl(handle_signals, SUDO_DEBUG_EXEC)
1.1 misho 515:
516: for (;;) {
517: /* read signal pipe */
518: nread = read(signal_pipe[0], &signo, sizeof(signo));
519: if (nread <= 0) {
520: /* It should not be possible to get EOF but just in case. */
521: if (nread == 0)
522: errno = ECONNRESET;
523: /* Restart if interrupted by signal so the pipe doesn't fill. */
524: if (errno == EINTR)
525: continue;
526: /* If pipe is empty, we are done. */
527: if (errno == EAGAIN)
528: break;
1.1.1.2 misho 529: sudo_debug_printf(SUDO_DEBUG_ERROR, "error reading signal pipe %s",
530: strerror(errno));
1.1 misho 531: cstat->type = CMD_ERRNO;
532: cstat->val = errno;
1.1.1.2 misho 533: debug_return_int(-1);
1.1 misho 534: }
1.1.1.3 ! misho 535: if (sig2str(signo, signame) == -1)
! 536: snprintf(signame, sizeof(signame), "%d", signo);
! 537: sudo_debug_printf(SUDO_DEBUG_DIAG, "received SIG%s", signame);
1.1 misho 538: if (signo == SIGCHLD) {
539: /*
540: * If logging I/O, child is the intermediate process,
541: * otherwise it is the command itself.
542: */
543: do {
544: pid = waitpid(child, &status, WUNTRACED|WNOHANG);
545: } while (pid == -1 && errno == EINTR);
546: if (pid == child) {
1.1.1.2 misho 547: if (log_io) {
548: /*
549: * On BSD we get ECONNRESET on sv[0] if monitor dies
550: * and select() will return with sv[0] readable.
551: * On Linux that doesn't appear to happen so if the
552: * monitor dies, shut down the socketpair to force a
553: * select() notification.
554: */
555: (void) shutdown(sv[0], SHUT_WR);
556: } else {
1.1 misho 557: if (WIFSTOPPED(status)) {
558: /*
559: * Save the controlling terminal's process group
1.1.1.3 ! misho 560: * so we can restore it after we resume, if needed.
! 561: * Most well-behaved shells change the pgrp back to
! 562: * its original value before suspending so we must
! 563: * not try to restore in that case, lest we race with
! 564: * the child upon resume, potentially stopping sudo
! 565: * with SIGTTOU while the command continues to run.
1.1 misho 566: */
1.1.1.3 ! misho 567: sigaction_t sa, osa;
1.1 misho 568: pid_t saved_pgrp = (pid_t)-1;
1.1.1.3 ! misho 569: int signo = WSTOPSIG(status);
1.1 misho 570: int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0);
1.1.1.3 ! misho 571: if (fd != -1) {
! 572: if ((saved_pgrp = tcgetpgrp(fd)) == ppgrp)
! 573: saved_pgrp = -1;
! 574: }
! 575: if (signo == SIGTSTP) {
! 576: zero_bytes(&sa, sizeof(sa));
! 577: sigemptyset(&sa.sa_mask);
! 578: sa.sa_handler = SIG_DFL;
! 579: sigaction(SIGTSTP, &sa, &osa);
1.1 misho 580: }
1.1.1.3 ! misho 581: if (kill(getpid(), signo) != 0)
! 582: warning("kill(%d, SIG%s)", (int)getpid(), signame);
! 583: if (signo == SIGTSTP)
! 584: sigaction(SIGTSTP, &osa, NULL);
1.1 misho 585: if (fd != -1) {
1.1.1.3 ! misho 586: /*
! 587: * Restore command's process group if different.
! 588: * Otherwise, we cannot resume some shells.
! 589: */
1.1 misho 590: if (saved_pgrp != (pid_t)-1)
591: (void)tcsetpgrp(fd, saved_pgrp);
592: close(fd);
593: }
594: } else {
595: /* Child has exited, we are done. */
596: cstat->type = CMD_WSTATUS;
597: cstat->val = status;
1.1.1.2 misho 598: debug_return_int(0);
1.1 misho 599: }
600: }
601: }
602: } else {
603: if (log_io) {
604: /* Schedule signo to be forwared to the child. */
605: schedule_signal(signo);
606: } else {
607: /* Nothing listening on sv[0], send directly. */
608: if (signo == SIGALRM)
1.1.1.3 ! misho 609: terminate_command(child, false);
1.1 misho 610: else if (kill(child, signo) != 0)
1.1.1.3 ! misho 611: warning("kill(%d, SIG%s)", (int)child, signame);
1.1 misho 612: }
613: }
614: }
1.1.1.2 misho 615: debug_return_int(1);
1.1 misho 616: }
617:
618: /*
619: * Forward signals in sigfwd_list to child listening on fd.
620: */
621: static void
622: forward_signals(int sock)
623: {
1.1.1.3 ! misho 624: char signame[SIG2STR_MAX];
1.1 misho 625: struct sigforward *sigfwd;
626: struct command_status cstat;
627: ssize_t nsent;
1.1.1.2 misho 628: debug_decl(forward_signals, SUDO_DEBUG_EXEC)
1.1 misho 629:
630: while (!tq_empty(&sigfwd_list)) {
631: sigfwd = tq_first(&sigfwd_list);
1.1.1.3 ! misho 632: if (sig2str(sigfwd->signo, signame) == -1)
! 633: snprintf(signame, sizeof(signame), "%d", sigfwd->signo);
1.1.1.2 misho 634: sudo_debug_printf(SUDO_DEBUG_INFO,
1.1.1.3 ! misho 635: "sending SIG%s to child over backchannel", signame);
1.1 misho 636: cstat.type = CMD_SIGNO;
637: cstat.val = sigfwd->signo;
638: do {
639: nsent = send(sock, &cstat, sizeof(cstat), 0);
640: } while (nsent == -1 && errno == EINTR);
641: tq_remove(&sigfwd_list, sigfwd);
642: efree(sigfwd);
643: if (nsent != sizeof(cstat)) {
644: if (errno == EPIPE) {
1.1.1.2 misho 645: sudo_debug_printf(SUDO_DEBUG_ERROR,
646: "broken pipe writing to child over backchannel");
1.1 misho 647: /* Other end of socket gone, empty out sigfwd_list. */
648: while (!tq_empty(&sigfwd_list)) {
649: sigfwd = tq_first(&sigfwd_list);
650: tq_remove(&sigfwd_list, sigfwd);
651: efree(sigfwd);
652: }
1.1.1.2 misho 653: /* XXX - child (monitor) is dead, we should exit too? */
1.1 misho 654: }
655: break;
656: }
657: }
1.1.1.2 misho 658: debug_return;
1.1 misho 659: }
660:
661: /*
662: * Schedule a signal to be forwared.
663: */
664: static void
665: schedule_signal(int signo)
666: {
667: struct sigforward *sigfwd;
1.1.1.3 ! misho 668: char signame[SIG2STR_MAX];
1.1.1.2 misho 669: debug_decl(schedule_signal, SUDO_DEBUG_EXEC)
1.1 misho 670:
1.1.1.3 ! misho 671: if (sig2str(signo, signame) == -1)
! 672: snprintf(signame, sizeof(signame), "%d", signo);
! 673: sudo_debug_printf(SUDO_DEBUG_DIAG, "forwarding SIG%s to child", signame);
1.1.1.2 misho 674:
675: sigfwd = ecalloc(1, sizeof(*sigfwd));
1.1 misho 676: sigfwd->prev = sigfwd;
1.1.1.2 misho 677: /* sigfwd->next = NULL; */
1.1 misho 678: sigfwd->signo = signo;
679: tq_append(&sigfwd_list, sigfwd);
1.1.1.2 misho 680:
681: debug_return;
1.1 misho 682: }
683:
684: /*
685: * Generic handler for signals passed from parent -> child.
686: * The other end of signal_pipe is checked in the main event loop.
687: */
1.1.1.3 ! misho 688: #ifdef SA_SIGINFO
! 689: void
! 690: handler(int s, siginfo_t *info, void *context)
! 691: {
! 692: unsigned char signo = (unsigned char)s;
! 693:
! 694: /*
! 695: * If the signal came from the command we ran, just ignore
! 696: * it since we don't want the child to indirectly kill itself.
! 697: * This can happen with, e.g. BSD-derived versions of reboot
! 698: * that call kill(-1, SIGTERM) to kill all other processes.
! 699: */
! 700: if (info != NULL && info->si_code == SI_USER && info->si_pid == cmnd_pid)
! 701: return;
! 702:
! 703: /*
! 704: * The pipe is non-blocking, if we overflow the kernel's pipe
! 705: * buffer we drop the signal. This is not a problem in practice.
! 706: */
! 707: ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
! 708: }
! 709: #else
1.1 misho 710: void
711: handler(int s)
712: {
713: unsigned char signo = (unsigned char)s;
714:
715: /*
716: * The pipe is non-blocking, if we overflow the kernel's pipe
717: * buffer we drop the signal. This is not a problem in practice.
718: */
1.1.1.2 misho 719: ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
720: }
1.1.1.3 ! misho 721: #endif
1.1.1.2 misho 722:
723: #ifdef SA_SIGINFO
724: /*
725: * Generic handler for signals passed from parent -> child.
726: * The other end of signal_pipe is checked in the main event loop.
727: * This version is for the non-pty case and does not forward
728: * signals that are generated by the kernel.
729: */
730: static void
1.1.1.3 ! misho 731: handler_user_only(int s, siginfo_t *info, void *context)
1.1.1.2 misho 732: {
733: unsigned char signo = (unsigned char)s;
734:
735: /* Only forward user-generated signals. */
1.1.1.3 ! misho 736: if (info != NULL && info->si_code == SI_USER) {
1.1.1.2 misho 737: /*
738: * The pipe is non-blocking, if we overflow the kernel's pipe
739: * buffer we drop the signal. This is not a problem in practice.
740: */
741: ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
742: }
1.1 misho 743: }
1.1.1.2 misho 744: #endif /* SA_SIGINFO */
1.1 misho 745:
746: /*
747: * Open a pipe and make both ends non-blocking.
748: * Returns 0 on success and -1 on error.
749: */
750: int
751: pipe_nonblock(int fds[2])
752: {
753: int flags, rval;
1.1.1.2 misho 754: debug_decl(pipe_nonblock, SUDO_DEBUG_EXEC)
1.1 misho 755:
756: rval = pipe(fds);
757: if (rval != -1) {
758: flags = fcntl(fds[0], F_GETFL, 0);
759: if (flags != -1 && !ISSET(flags, O_NONBLOCK))
760: rval = fcntl(fds[0], F_SETFL, flags | O_NONBLOCK);
761: if (rval != -1) {
762: flags = fcntl(fds[1], F_GETFL, 0);
763: if (flags != -1 && !ISSET(flags, O_NONBLOCK))
764: rval = fcntl(fds[1], F_SETFL, flags | O_NONBLOCK);
765: }
766: if (rval == -1) {
767: close(fds[0]);
768: close(fds[1]);
769: }
770: }
771:
1.1.1.2 misho 772: debug_return_int(rval);
1.1 misho 773: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>