Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/src/signal.c
1532 views
1
/*
2
* SPDX-License-Identifier: ISC
3
*
4
* Copyright (c) 2009-2016 Todd C. Miller <[email protected]>
5
*
6
* Permission to use, copy, modify, and distribute this software for any
7
* purpose with or without fee is hereby granted, provided that the above
8
* copyright notice and this permission notice appear in all copies.
9
*
10
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
*/
18
19
#include <config.h>
20
#include <string.h>
21
#include <errno.h>
22
#include <signal.h>
23
24
#include <sudo.h>
25
#include <sudo_exec.h>
26
27
static struct signal_state {
28
int signo;
29
int restore;
30
struct sigaction sa;
31
} saved_signals[] = {
32
{ SIGALRM }, /* SAVED_SIGALRM */
33
{ SIGCHLD }, /* SAVED_SIGCHLD */
34
{ SIGCONT }, /* SAVED_SIGCONT */
35
{ SIGHUP }, /* SAVED_SIGHUP */
36
{ SIGINT }, /* SAVED_SIGINT */
37
{ SIGPIPE }, /* SAVED_SIGPIPE */
38
{ SIGQUIT }, /* SAVED_SIGQUIT */
39
{ SIGTERM }, /* SAVED_SIGTERM */
40
{ SIGTSTP }, /* SAVED_SIGTSTP */
41
{ SIGTTIN }, /* SAVED_SIGTTIN */
42
{ SIGTTOU }, /* SAVED_SIGTTOU */
43
{ SIGUSR1 }, /* SAVED_SIGUSR1 */
44
{ SIGUSR2 }, /* SAVED_SIGUSR2 */
45
{ -1 }
46
};
47
48
static sig_atomic_t pending_signals[NSIG];
49
50
static void
51
sudo_handler(int signo)
52
{
53
/* Mark signal as pending. */
54
pending_signals[signo] = 1;
55
}
56
57
bool
58
signal_pending(int signo)
59
{
60
return pending_signals[signo] == 1;
61
}
62
63
/*
64
* Save signal handler state so it can be restored before exec.
65
*/
66
void
67
save_signals(void)
68
{
69
struct signal_state *ss;
70
debug_decl(save_signals, SUDO_DEBUG_MAIN);
71
72
for (ss = saved_signals; ss->signo != -1; ss++) {
73
if (sigaction(ss->signo, NULL, &ss->sa) != 0)
74
sudo_warn(U_("unable to save handler for signal %d"), ss->signo);
75
}
76
77
debug_return;
78
}
79
80
/*
81
* Restore signal handlers to initial state for exec.
82
*/
83
void
84
restore_signals(void)
85
{
86
struct signal_state *ss;
87
debug_decl(restore_signals, SUDO_DEBUG_MAIN);
88
89
for (ss = saved_signals; ss->signo != -1; ss++) {
90
if (ss->restore) {
91
sudo_debug_printf(SUDO_DEBUG_INFO,
92
"restoring handler for signal %d: %s", ss->signo,
93
ss->sa.sa_handler == SIG_IGN ? "SIG_IGN" :
94
ss->sa.sa_handler == SIG_DFL ? "SIG_DFL" : "???");
95
if (sigaction(ss->signo, &ss->sa, NULL) != 0) {
96
sudo_warn(U_("unable to restore handler for signal %d"),
97
ss->signo);
98
}
99
}
100
}
101
102
debug_return;
103
}
104
105
/*
106
* Trap tty-generated (and other) signals so we can't be killed before
107
* calling the policy close function. The signal pipe will be drained
108
* in sudo_execute() before running the command and new handlers will
109
* be installed in the parent.
110
*/
111
void
112
init_signals(void)
113
{
114
struct sigaction sa;
115
struct signal_state *ss;
116
debug_decl(init_signals, SUDO_DEBUG_MAIN);
117
118
memset(&sa, 0, sizeof(sa));
119
sigfillset(&sa.sa_mask);
120
sa.sa_flags = SA_RESTART;
121
sa.sa_handler = sudo_handler;
122
123
for (ss = saved_signals; ss->signo > 0; ss++) {
124
switch (ss->signo) {
125
case SIGCONT:
126
case SIGPIPE:
127
case SIGTTIN:
128
case SIGTTOU:
129
/* Don't install these until exec time. */
130
break;
131
case SIGCHLD:
132
/* Sudo needs to be able to catch SIGCHLD. */
133
if (ss->sa.sa_handler == SIG_IGN) {
134
sudo_debug_printf(SUDO_DEBUG_INFO,
135
"will restore signal %d on exec", SIGCHLD);
136
ss->restore = true;
137
}
138
if (sigaction(SIGCHLD, &sa, NULL) != 0) {
139
sudo_warn(U_("unable to set handler for signal %d"),
140
SIGCHLD);
141
}
142
break;
143
default:
144
if (ss->sa.sa_handler != SIG_IGN) {
145
if (sigaction(ss->signo, &sa, NULL) != 0) {
146
sudo_warn(U_("unable to set handler for signal %d"),
147
ss->signo);
148
}
149
}
150
break;
151
}
152
}
153
/* Ignore SIGPIPE until exec. */
154
if (saved_signals[SAVED_SIGPIPE].sa.sa_handler != SIG_IGN) {
155
sudo_debug_printf(SUDO_DEBUG_INFO,
156
"will restore signal %d on exec", SIGPIPE);
157
saved_signals[SAVED_SIGPIPE].restore = true;
158
sa.sa_handler = SIG_IGN;
159
if (sigaction(SIGPIPE, &sa, NULL) != 0)
160
sudo_warn(U_("unable to set handler for signal %d"), SIGPIPE);
161
}
162
163
debug_return;
164
}
165
166
/*
167
* Like sigaction() but sets restore flag in saved_signals[]
168
* if needed.
169
*/
170
int
171
sudo_sigaction(int signo, struct sigaction *sa, struct sigaction *osa)
172
{
173
struct signal_state *ss;
174
int ret;
175
debug_decl(sudo_sigaction, SUDO_DEBUG_MAIN);
176
177
for (ss = saved_signals; ss->signo > 0; ss++) {
178
if (ss->signo == signo) {
179
/* If signal was or now is ignored, restore old handler on exec. */
180
if (ss->sa.sa_handler == SIG_IGN || sa->sa_handler == SIG_IGN) {
181
sudo_debug_printf(SUDO_DEBUG_INFO,
182
"will restore signal %d on exec", signo);
183
ss->restore = true;
184
}
185
break;
186
}
187
}
188
ret = sigaction(signo, sa, osa);
189
190
debug_return_int(ret);
191
}
192
193