Annotation of embedaddon/sudo/src/signal.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (c) 2009-2013 Todd C. Miller <Todd.Miller@courtesan.com>
! 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 <stdio.h>
! 21: #ifdef STDC_HEADERS
! 22: # include <stdlib.h>
! 23: # include <stddef.h>
! 24: #else
! 25: # ifdef HAVE_STDLIB_H
! 26: # include <stdlib.h>
! 27: # endif
! 28: #endif /* STDC_HEADERS */
! 29: #ifdef HAVE_STRING_H
! 30: # include <string.h>
! 31: #endif /* HAVE_STRING_H */
! 32: #ifdef HAVE_STRINGS_H
! 33: # include <strings.h>
! 34: #endif /* HAVE_STRINGS_H */
! 35: #ifdef HAVE_UNISTD_H
! 36: # include <unistd.h>
! 37: #endif /* HAVE_UNISTD_H */
! 38: #include <errno.h>
! 39: #include <signal.h>
! 40:
! 41: #include "sudo.h"
! 42:
! 43: int signal_pipe[2];
! 44:
! 45: static struct signal_state {
! 46: int signo;
! 47: int restore;
! 48: sigaction_t sa;
! 49: } saved_signals[] = {
! 50: { SIGALRM }, /* SAVED_SIGALRM */
! 51: { SIGCHLD }, /* SAVED_SIGCHLD */
! 52: { SIGCONT }, /* SAVED_SIGCONT */
! 53: { SIGHUP }, /* SAVED_SIGHUP */
! 54: { SIGINT }, /* SAVED_SIGINT */
! 55: { SIGPIPE }, /* SAVED_SIGPIPE */
! 56: { SIGQUIT }, /* SAVED_SIGQUIT */
! 57: { SIGTERM }, /* SAVED_SIGTERM */
! 58: { SIGTSTP }, /* SAVED_SIGTSTP */
! 59: { SIGTTIN }, /* SAVED_SIGTTIN */
! 60: { SIGTTOU }, /* SAVED_SIGTTOU */
! 61: { SIGUSR1 }, /* SAVED_SIGUSR1 */
! 62: { SIGUSR2 }, /* SAVED_SIGUSR2 */
! 63: { -1 }
! 64: };
! 65:
! 66: /*
! 67: * Save signal handler state so it can be restored before exec.
! 68: */
! 69: void
! 70: save_signals(void)
! 71: {
! 72: struct signal_state *ss;
! 73: debug_decl(save_signals, SUDO_DEBUG_MAIN)
! 74:
! 75: for (ss = saved_signals; ss->signo != -1; ss++)
! 76: sigaction(ss->signo, NULL, &ss->sa);
! 77:
! 78: debug_return;
! 79: }
! 80:
! 81: /*
! 82: * Restore signal handlers to initial state for exec.
! 83: */
! 84: void
! 85: restore_signals(void)
! 86: {
! 87: struct signal_state *ss;
! 88: debug_decl(restore_signals, SUDO_DEBUG_MAIN)
! 89:
! 90: for (ss = saved_signals; ss->signo != -1; ss++) {
! 91: if (ss->restore)
! 92: sigaction(ss->signo, &ss->sa, NULL);
! 93: }
! 94:
! 95: debug_return;
! 96: }
! 97:
! 98: static void
! 99: sudo_handler(int signo)
! 100: {
! 101: /*
! 102: * The pipe is non-blocking, if we overflow the kernel's pipe
! 103: * buffer we drop the signal. This is not a problem in practice.
! 104: */
! 105: ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
! 106: }
! 107:
! 108: /*
! 109: * Trap tty-generated (and other) signals so we can't be killed before
! 110: * calling the policy close function. The signal pipe will be drained
! 111: * in sudo_execute() before running the command and new handlers will
! 112: * be installed in the parent.
! 113: */
! 114: void
! 115: init_signals(void)
! 116: {
! 117: struct sigaction sa;
! 118: struct signal_state *ss;
! 119: debug_decl(init_signals, SUDO_DEBUG_MAIN)
! 120:
! 121: /*
! 122: * We use a pipe to atomically handle signal notification within
! 123: * the select() loop without races (we may not have pselect()).
! 124: */
! 125: if (pipe_nonblock(signal_pipe) != 0)
! 126: fatal(_("unable to create pipe"));
! 127:
! 128: memset(&sa, 0, sizeof(sa));
! 129: sigfillset(&sa.sa_mask);
! 130: sa.sa_flags = SA_RESTART;
! 131: sa.sa_handler = sudo_handler;
! 132:
! 133: for (ss = saved_signals; ss->signo > 0; ss++) {
! 134: switch (ss->signo) {
! 135: case SIGCHLD:
! 136: case SIGCONT:
! 137: case SIGPIPE:
! 138: case SIGTTIN:
! 139: case SIGTTOU:
! 140: /* Don't install these until exec time. */
! 141: break;
! 142: default:
! 143: if (ss->sa.sa_handler != SIG_IGN)
! 144: sigaction(ss->signo, &sa, NULL);
! 145: break;
! 146: }
! 147: }
! 148: debug_return;
! 149: }
! 150:
! 151: /*
! 152: * Like sigaction() but sets restore flag in saved_signals[]
! 153: * if needed.
! 154: */
! 155: int
! 156: sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa)
! 157: {
! 158: struct signal_state *ss;
! 159: int rval;
! 160: debug_decl(sudo_sigaction, SUDO_DEBUG_MAIN)
! 161:
! 162: for (ss = saved_signals; ss->signo > 0; ss++) {
! 163: if (ss->signo == signo) {
! 164: /* If signal was or now is ignored, restore old handler on exec. */
! 165: if (ss->sa.sa_handler == SIG_IGN || sa->sa_handler == SIG_IGN) {
! 166: sudo_debug_printf(SUDO_DEBUG_INFO,
! 167: "will restore signal %d on exec", signo);
! 168: ss->restore = true;
! 169: }
! 170: break;
! 171: }
! 172: }
! 173: rval = sigaction(signo, sa, osa);
! 174:
! 175: debug_return_int(rval);
! 176: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>