2 * Copyright (c) 2009-2013 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>
28 #endif /* STDC_HEADERS */
31 #endif /* HAVE_STRING_H */
34 #endif /* HAVE_STRINGS_H */
37 #endif /* HAVE_UNISTD_H */
45 static struct signal_state {
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 */
67 * Save signal handler state so it can be restored before exec.
72 struct signal_state *ss;
73 debug_decl(save_signals, SUDO_DEBUG_MAIN)
75 for (ss = saved_signals; ss->signo != -1; ss++)
76 sigaction(ss->signo, NULL, &ss->sa);
82 * Restore signal handlers to initial state for exec.
87 struct signal_state *ss;
88 debug_decl(restore_signals, SUDO_DEBUG_MAIN)
90 for (ss = saved_signals; ss->signo != -1; ss++) {
92 sigaction(ss->signo, &ss->sa, NULL);
99 sudo_handler(int signo)
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.
105 ignore_result(write(signal_pipe[1], &signo, sizeof(signo)));
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.
118 struct signal_state *ss;
119 debug_decl(init_signals, SUDO_DEBUG_MAIN)
122 * We use a pipe to atomically handle signal notification within
123 * the select() loop without races (we may not have pselect()).
125 if (pipe_nonblock(signal_pipe) != 0)
126 fatal(_("unable to create pipe"));
128 memset(&sa, 0, sizeof(sa));
129 sigfillset(&sa.sa_mask);
130 sa.sa_flags = SA_RESTART;
131 sa.sa_handler = sudo_handler;
133 for (ss = saved_signals; ss->signo > 0; ss++) {
140 /* Don't install these until exec time. */
143 if (ss->sa.sa_handler != SIG_IGN)
144 sigaction(ss->signo, &sa, NULL);
152 * Like sigaction() but sets restore flag in saved_signals[]
156 sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa)
158 struct signal_state *ss;
160 debug_decl(sudo_sigaction, SUDO_DEBUG_MAIN)
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);
173 rval = sigaction(signo, sa, osa);
175 debug_return_int(rval);