1
2
3
4
5
6
7
8
9#include <stdlib.h>
10#include <stdarg.h>
11#include <errno.h>
12#include <signal.h>
13#include <strings.h>
14#include <as-layout.h>
15#include <kern_util.h>
16#include <os.h>
17#include <sysdep/mcontext.h>
18
19void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
20 [SIGTRAP] = relay_signal,
21 [SIGFPE] = relay_signal,
22 [SIGILL] = relay_signal,
23 [SIGWINCH] = winch,
24 [SIGBUS] = bus_handler,
25 [SIGSEGV] = segv_handler,
26 [SIGIO] = sigio_handler,
27 [SIGALRM] = timer_handler
28};
29
30static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
31{
32 struct uml_pt_regs r;
33 int save_errno = errno;
34
35 r.is_user = 0;
36 if (sig == SIGSEGV) {
37
38 get_regs_from_mc(&r, mc);
39 GET_FAULTINFO_FROM_MC(r.faultinfo, mc);
40 }
41
42
43 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGALRM))
44 unblock_signals();
45
46 (*sig_info[sig])(sig, si, &r);
47
48 errno = save_errno;
49}
50
51
52
53
54
55
56
57#define SIGIO_BIT 0
58#define SIGIO_MASK (1 << SIGIO_BIT)
59
60#define SIGALRM_BIT 1
61#define SIGALRM_MASK (1 << SIGALRM_BIT)
62
63static int signals_enabled;
64static unsigned int signals_pending;
65static unsigned int signals_active = 0;
66
67void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
68{
69 int enabled;
70
71 enabled = signals_enabled;
72 if (!enabled && (sig == SIGIO)) {
73 signals_pending |= SIGIO_MASK;
74 return;
75 }
76
77 block_signals();
78
79 sig_handler_common(sig, si, mc);
80
81 set_signals(enabled);
82}
83
84static void timer_real_alarm_handler(mcontext_t *mc)
85{
86 struct uml_pt_regs regs;
87
88 if (mc != NULL)
89 get_regs_from_mc(®s, mc);
90 timer_handler(SIGALRM, NULL, ®s);
91}
92
93void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
94{
95 int enabled;
96
97 enabled = signals_enabled;
98 if (!signals_enabled) {
99 signals_pending |= SIGALRM_MASK;
100 return;
101 }
102
103 block_signals();
104
105 signals_active |= SIGALRM_MASK;
106
107 timer_real_alarm_handler(mc);
108
109 signals_active &= ~SIGALRM_MASK;
110
111 set_signals(enabled);
112}
113
114void deliver_alarm(void) {
115 timer_alarm_handler(SIGALRM, NULL, NULL);
116}
117
118void timer_set_signal_handler(void)
119{
120 set_handler(SIGALRM);
121}
122
123void set_sigstack(void *sig_stack, int size)
124{
125 stack_t stack = {
126 .ss_flags = 0,
127 .ss_sp = sig_stack,
128 .ss_size = size - sizeof(void *)
129 };
130
131 if (sigaltstack(&stack, NULL) != 0)
132 panic("enabling signal stack failed, errno = %d\n", errno);
133}
134
135static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
136 [SIGSEGV] = sig_handler,
137 [SIGBUS] = sig_handler,
138 [SIGILL] = sig_handler,
139 [SIGFPE] = sig_handler,
140 [SIGTRAP] = sig_handler,
141
142 [SIGIO] = sig_handler,
143 [SIGWINCH] = sig_handler,
144 [SIGALRM] = timer_alarm_handler
145};
146
147static void hard_handler(int sig, siginfo_t *si, void *p)
148{
149 struct ucontext *uc = p;
150 mcontext_t *mc = &uc->uc_mcontext;
151 unsigned long pending = 1UL << sig;
152
153 do {
154 int nested, bail;
155
156
157
158
159
160
161
162
163
164
165
166 bail = to_irq_stack(&pending);
167 if (bail)
168 return;
169
170 nested = pending & 1;
171 pending &= ~1;
172
173 while ((sig = ffs(pending)) != 0){
174 sig--;
175 pending &= ~(1 << sig);
176 (*handlers[sig])(sig, (struct siginfo *)si, mc);
177 }
178
179
180
181
182
183
184
185 if (!nested)
186 pending = from_irq_stack(nested);
187 } while (pending);
188}
189
190void set_handler(int sig)
191{
192 struct sigaction action;
193 int flags = SA_SIGINFO | SA_ONSTACK;
194 sigset_t sig_mask;
195
196 action.sa_sigaction = hard_handler;
197
198
199 sigemptyset(&action.sa_mask);
200 sigaddset(&action.sa_mask, SIGIO);
201 sigaddset(&action.sa_mask, SIGWINCH);
202 sigaddset(&action.sa_mask, SIGALRM);
203
204 if (sig == SIGSEGV)
205 flags |= SA_NODEFER;
206
207 if (sigismember(&action.sa_mask, sig))
208 flags |= SA_RESTART;
209
210 action.sa_flags = flags;
211 action.sa_restorer = NULL;
212 if (sigaction(sig, &action, NULL) < 0)
213 panic("sigaction failed - errno = %d\n", errno);
214
215 sigemptyset(&sig_mask);
216 sigaddset(&sig_mask, sig);
217 if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
218 panic("sigprocmask failed - errno = %d\n", errno);
219}
220
221int change_sig(int signal, int on)
222{
223 sigset_t sigset;
224
225 sigemptyset(&sigset);
226 sigaddset(&sigset, signal);
227 if (sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, NULL) < 0)
228 return -errno;
229
230 return 0;
231}
232
233void block_signals(void)
234{
235 signals_enabled = 0;
236
237
238
239
240
241
242 barrier();
243}
244
245void unblock_signals(void)
246{
247 int save_pending;
248
249 if (signals_enabled == 1)
250 return;
251
252
253
254
255
256
257 while (1) {
258
259
260
261
262 signals_enabled = 1;
263
264
265
266
267
268 barrier();
269
270 save_pending = signals_pending;
271 if (save_pending == 0)
272 return;
273
274 signals_pending = 0;
275
276
277
278
279
280
281
282 signals_enabled = 0;
283
284
285
286
287
288
289
290
291
292 if (save_pending & SIGIO_MASK)
293 sig_handler_common(SIGIO, NULL, NULL);
294
295
296
297 if ((save_pending & SIGALRM_MASK) && (!(signals_active & SIGALRM_MASK)))
298 timer_real_alarm_handler(NULL);
299
300
301
302 if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
303 return;
304
305 }
306}
307
308int get_signals(void)
309{
310 return signals_enabled;
311}
312
313int set_signals(int enable)
314{
315 int ret;
316 if (signals_enabled == enable)
317 return enable;
318
319 ret = signals_enabled;
320 if (enable)
321 unblock_signals();
322 else block_signals();
323
324 return ret;
325}
326
327int os_is_signal_stack(void)
328{
329 stack_t ss;
330 sigaltstack(NULL, &ss);
331
332 return ss.ss_flags & SS_ONSTACK;
333}
334