Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
728df0db | 6 | * @(#)kern_sig.c 7.3 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
961945a8 SL |
8 | |
9 | #include "../machine/reg.h" | |
10 | #include "../machine/pte.h" | |
11 | #include "../machine/psl.h" | |
fb1db32c | 12 | #include "../machine/mtpr.h" |
687880f9 | 13 | |
94368568 JB |
14 | #include "param.h" |
15 | #include "systm.h" | |
16 | #include "dir.h" | |
17 | #include "user.h" | |
18 | #include "inode.h" | |
19 | #include "proc.h" | |
20 | #include "timeb.h" | |
21 | #include "times.h" | |
94368568 JB |
22 | #include "buf.h" |
23 | #include "mount.h" | |
24 | #include "text.h" | |
25 | #include "seg.h" | |
26 | #include "vm.h" | |
27 | #include "acct.h" | |
28 | #include "uio.h" | |
29 | #include "kernel.h" | |
687880f9 | 30 | |
feff6b5a | 31 | #define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)) |
3b2ddb34 MK |
32 | #define stopsigmask (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \ |
33 | sigmask(SIGTTIN)|sigmask(SIGTTOU)) | |
457aa395 | 34 | |
2e143991 KM |
35 | /* |
36 | * Generalized interface signal handler. | |
37 | */ | |
4147b3f6 BJ |
38 | sigvec() |
39 | { | |
457aa395 | 40 | register struct a { |
dd012d1e | 41 | int signo; |
457aa395 SL |
42 | struct sigvec *nsv; |
43 | struct sigvec *osv; | |
dd012d1e | 44 | } *uap = (struct a *)u.u_ap; |
457aa395 SL |
45 | struct sigvec vec; |
46 | register struct sigvec *sv; | |
dd012d1e | 47 | register int sig; |
fe7f81f4 | 48 | int bit; |
dd012d1e SL |
49 | |
50 | sig = uap->signo; | |
457aa395 | 51 | if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { |
dd012d1e SL |
52 | u.u_error = EINVAL; |
53 | return; | |
54 | } | |
457aa395 SL |
55 | sv = &vec; |
56 | if (uap->osv) { | |
57 | sv->sv_handler = u.u_signal[sig]; | |
58 | sv->sv_mask = u.u_sigmask[sig]; | |
fe7f81f4 KM |
59 | bit = sigmask(sig); |
60 | sv->sv_flags = 0; | |
61 | if ((u.u_sigonstack & bit) != 0) | |
62 | sv->sv_flags |= SV_ONSTACK; | |
63 | if ((u.u_sigintr & bit) != 0) | |
64 | sv->sv_flags |= SV_INTERRUPT; | |
457aa395 SL |
65 | u.u_error = |
66 | copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); | |
67 | if (u.u_error) | |
68 | return; | |
69 | } | |
70 | if (uap->nsv) { | |
71 | u.u_error = | |
72 | copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); | |
73 | if (u.u_error) | |
74 | return; | |
75 | if (sig == SIGCONT && sv->sv_handler == SIG_IGN) { | |
76 | u.u_error = EINVAL; | |
77 | return; | |
78 | } | |
79 | setsigvec(sig, sv); | |
80 | } | |
dd012d1e | 81 | } |
4147b3f6 | 82 | |
457aa395 SL |
83 | setsigvec(sig, sv) |
84 | int sig; | |
85 | register struct sigvec *sv; | |
dd012d1e SL |
86 | { |
87 | register struct proc *p; | |
457aa395 | 88 | register int bit; |
dd012d1e | 89 | |
feff6b5a | 90 | bit = sigmask(sig); |
dd012d1e SL |
91 | p = u.u_procp; |
92 | /* | |
93 | * Change setting atomically. | |
94 | */ | |
feff6b5a | 95 | (void) splhigh(); |
457aa395 SL |
96 | u.u_signal[sig] = sv->sv_handler; |
97 | u.u_sigmask[sig] = sv->sv_mask &~ cantmask; | |
fe7f81f4 KM |
98 | if (sv->sv_flags & SV_INTERRUPT) |
99 | u.u_sigintr |= bit; | |
100 | else | |
101 | u.u_sigintr &= ~bit; | |
102 | if (sv->sv_flags & SV_ONSTACK) | |
457aa395 SL |
103 | u.u_sigonstack |= bit; |
104 | else | |
105 | u.u_sigonstack &= ~bit; | |
106 | if (sv->sv_handler == SIG_IGN) { | |
107 | p->p_sig &= ~bit; /* never to be seen again */ | |
108 | p->p_sigignore |= bit; | |
109 | p->p_sigcatch &= ~bit; | |
dd012d1e | 110 | } else { |
457aa395 SL |
111 | p->p_sigignore &= ~bit; |
112 | if (sv->sv_handler == SIG_DFL) | |
113 | p->p_sigcatch &= ~bit; | |
dd012d1e | 114 | else |
457aa395 | 115 | p->p_sigcatch |= bit; |
dd012d1e SL |
116 | } |
117 | (void) spl0(); | |
4147b3f6 BJ |
118 | } |
119 | ||
120 | sigblock() | |
121 | { | |
dd012d1e | 122 | struct a { |
feff6b5a | 123 | int mask; |
dd012d1e | 124 | } *uap = (struct a *)u.u_ap; |
457aa395 | 125 | register struct proc *p = u.u_procp; |
4147b3f6 | 126 | |
feff6b5a | 127 | (void) splhigh(); |
dd012d1e | 128 | u.u_r.r_val1 = p->p_sigmask; |
feff6b5a | 129 | p->p_sigmask |= uap->mask &~ cantmask; |
dd012d1e | 130 | (void) spl0(); |
4147b3f6 BJ |
131 | } |
132 | ||
133 | sigsetmask() | |
687880f9 | 134 | { |
dd012d1e | 135 | struct a { |
feff6b5a | 136 | int mask; |
dd012d1e SL |
137 | } *uap = (struct a *)u.u_ap; |
138 | register struct proc *p = u.u_procp; | |
687880f9 | 139 | |
feff6b5a | 140 | (void) splhigh(); |
dd012d1e | 141 | u.u_r.r_val1 = p->p_sigmask; |
feff6b5a | 142 | p->p_sigmask = uap->mask &~ cantmask; |
dd012d1e | 143 | (void) spl0(); |
687880f9 BJ |
144 | } |
145 | ||
4147b3f6 BJ |
146 | sigpause() |
147 | { | |
dd012d1e | 148 | struct a { |
feff6b5a | 149 | int mask; |
dd012d1e SL |
150 | } *uap = (struct a *)u.u_ap; |
151 | register struct proc *p = u.u_procp; | |
4147b3f6 | 152 | |
dd012d1e SL |
153 | /* |
154 | * When returning from sigpause, we want | |
155 | * the old mask to be restored after the | |
156 | * signal handler has finished. Thus, we | |
157 | * save it here and mark the proc structure | |
158 | * to indicate this (should be in u.). | |
159 | */ | |
160 | u.u_oldmask = p->p_sigmask; | |
161 | p->p_flag |= SOMASK; | |
feff6b5a | 162 | p->p_sigmask = uap->mask &~ cantmask; |
dd012d1e SL |
163 | for (;;) |
164 | sleep((caddr_t)&u, PSLEP); | |
165 | /*NOTREACHED*/ | |
4147b3f6 | 166 | } |
457aa395 | 167 | #undef cantmask |
4147b3f6 BJ |
168 | |
169 | sigstack() | |
170 | { | |
457aa395 | 171 | register struct a { |
457aa395 SL |
172 | struct sigstack *nss; |
173 | struct sigstack *oss; | |
dd012d1e | 174 | } *uap = (struct a *)u.u_ap; |
457aa395 | 175 | struct sigstack ss; |
4147b3f6 | 176 | |
457aa395 SL |
177 | if (uap->oss) { |
178 | u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss, | |
179 | sizeof (struct sigstack)); | |
180 | if (u.u_error) | |
181 | return; | |
182 | } | |
183 | if (uap->nss) { | |
184 | u.u_error = | |
185 | copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)); | |
186 | if (u.u_error == 0) | |
187 | u.u_sigstack = ss; | |
188 | } | |
4147b3f6 BJ |
189 | } |
190 | ||
1e3738da BJ |
191 | kill() |
192 | { | |
dd012d1e SL |
193 | register struct a { |
194 | int pid; | |
195 | int signo; | |
196 | } *uap = (struct a *)u.u_ap; | |
7713be67 | 197 | register struct proc *p; |
1e3738da | 198 | |
7713be67 KM |
199 | if (uap->signo < 0 || uap->signo > NSIG) { |
200 | u.u_error = EINVAL; | |
201 | return; | |
202 | } | |
203 | if (uap->pid > 0) { | |
204 | /* kill single process */ | |
205 | p = pfind(uap->pid); | |
206 | if (p == 0) { | |
207 | u.u_error = ESRCH; | |
208 | return; | |
209 | } | |
210 | if (u.u_uid && u.u_uid != p->p_uid) | |
211 | u.u_error = EPERM; | |
212 | else if (uap->signo) | |
213 | psignal(p, uap->signo); | |
214 | return; | |
215 | } | |
216 | switch (uap->pid) { | |
217 | case -1: /* broadcast signal */ | |
c52373fd | 218 | u.u_error = killpg1(uap->signo, 0, 1); |
7713be67 KM |
219 | break; |
220 | case 0: /* signal own process group */ | |
221 | u.u_error = killpg1(uap->signo, 0, 0); | |
222 | break; | |
223 | default: /* negative explicit process group */ | |
224 | u.u_error = killpg1(uap->signo, -uap->pid, 0); | |
225 | break; | |
226 | } | |
227 | return; | |
1e3738da BJ |
228 | } |
229 | ||
230 | killpg() | |
231 | { | |
3b4f6e10 SL |
232 | register struct a { |
233 | int pgrp; | |
234 | int signo; | |
235 | } *uap = (struct a *)u.u_ap; | |
1e3738da | 236 | |
7713be67 KM |
237 | if (uap->signo < 0 || uap->signo > NSIG) { |
238 | u.u_error = EINVAL; | |
239 | return; | |
240 | } | |
241 | u.u_error = killpg1(uap->signo, uap->pgrp, 0); | |
1e3738da BJ |
242 | } |
243 | ||
dd012d1e SL |
244 | /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ |
245 | ||
7713be67 KM |
246 | killpg1(signo, pgrp, all) |
247 | int signo, pgrp, all; | |
3b4f6e10 SL |
248 | { |
249 | register struct proc *p; | |
7713be67 | 250 | int f, error = 0; |
3b4f6e10 | 251 | |
7713be67 | 252 | if (!all && pgrp == 0) { |
687880f9 BJ |
253 | /* |
254 | * Zero process id means send to my process group. | |
255 | */ | |
7713be67 KM |
256 | pgrp = u.u_procp->p_pgrp; |
257 | if (pgrp == 0) | |
c52373fd | 258 | return (ESRCH); |
687880f9 | 259 | } |
1d348849 | 260 | for (f = 0, p = allproc; p != NULL; p = p->p_nxt) { |
7713be67 KM |
261 | if ((p->p_pgrp != pgrp && !all) || p->p_ppid == 0 || |
262 | (p->p_flag&SSYS) || (all && p == u.u_procp)) | |
687880f9 BJ |
263 | continue; |
264 | if (u.u_uid != 0 && u.u_uid != p->p_uid && | |
7713be67 | 265 | (signo != SIGCONT || !inferior(p))) { |
c52373fd KM |
266 | if (!all) |
267 | error = EPERM; | |
687880f9 | 268 | continue; |
7713be67 | 269 | } |
c52373fd | 270 | f++; |
dc7d58ca SL |
271 | if (signo) |
272 | psignal(p, signo); | |
687880f9 | 273 | } |
8db20a41 | 274 | return (error ? error : (f == 0 ? ESRCH : 0)); |
4147b3f6 | 275 | } |
687880f9 BJ |
276 | |
277 | /* | |
278 | * Send the specified signal to | |
279 | * all processes with 'pgrp' as | |
280 | * process group. | |
687880f9 BJ |
281 | */ |
282 | gsignal(pgrp, sig) | |
283 | register int pgrp; | |
284 | { | |
285 | register struct proc *p; | |
286 | ||
287 | if (pgrp == 0) | |
288 | return; | |
1d348849 | 289 | for (p = allproc; p != NULL; p = p->p_nxt) |
687880f9 BJ |
290 | if (p->p_pgrp == pgrp) |
291 | psignal(p, sig); | |
292 | } | |
293 | ||
294 | /* | |
295 | * Send the specified signal to | |
296 | * the specified process. | |
297 | */ | |
298 | psignal(p, sig) | |
299 | register struct proc *p; | |
300 | register int sig; | |
301 | { | |
302 | register int s; | |
303 | register int (*action)(); | |
feff6b5a | 304 | int mask; |
687880f9 BJ |
305 | |
306 | if ((unsigned)sig >= NSIG) | |
307 | return; | |
feff6b5a | 308 | mask = sigmask(sig); |
687880f9 BJ |
309 | |
310 | /* | |
311 | * If proc is traced, always give parent a chance. | |
687880f9 BJ |
312 | */ |
313 | if (p->p_flag & STRC) | |
314 | action = SIG_DFL; | |
315 | else { | |
687880f9 | 316 | /* |
dd012d1e SL |
317 | * If the signal is being ignored, |
318 | * then we forget about it immediately. | |
687880f9 | 319 | */ |
feff6b5a | 320 | if (p->p_sigignore & mask) |
687880f9 | 321 | return; |
feff6b5a | 322 | if (p->p_sigmask & mask) |
dd012d1e | 323 | action = SIG_HOLD; |
feff6b5a | 324 | else if (p->p_sigcatch & mask) |
dd012d1e SL |
325 | action = SIG_CATCH; |
326 | else | |
327 | action = SIG_DFL; | |
687880f9 | 328 | } |
687880f9 | 329 | if (sig) { |
feff6b5a | 330 | p->p_sig |= mask; |
687880f9 BJ |
331 | switch (sig) { |
332 | ||
333 | case SIGTERM: | |
dd012d1e | 334 | if ((p->p_flag&STRC) || action != SIG_DFL) |
687880f9 BJ |
335 | break; |
336 | /* fall into ... */ | |
337 | ||
338 | case SIGKILL: | |
339 | if (p->p_nice > NZERO) | |
340 | p->p_nice = NZERO; | |
341 | break; | |
342 | ||
343 | case SIGCONT: | |
3b2ddb34 | 344 | p->p_sig &= ~stopsigmask; |
687880f9 BJ |
345 | break; |
346 | ||
347 | case SIGSTOP: | |
348 | case SIGTSTP: | |
349 | case SIGTTIN: | |
350 | case SIGTTOU: | |
feff6b5a | 351 | p->p_sig &= ~sigmask(SIGCONT); |
687880f9 BJ |
352 | break; |
353 | } | |
354 | } | |
687880f9 BJ |
355 | /* |
356 | * Defer further processing for signals which are held. | |
357 | */ | |
358 | if (action == SIG_HOLD) | |
359 | return; | |
feff6b5a | 360 | s = splhigh(); |
687880f9 BJ |
361 | switch (p->p_stat) { |
362 | ||
363 | case SSLEEP: | |
364 | /* | |
365 | * If process is sleeping at negative priority | |
366 | * we can't interrupt the sleep... the signal will | |
367 | * be noticed when the process returns through | |
368 | * trap() or syscall(). | |
369 | */ | |
370 | if (p->p_pri <= PZERO) | |
371 | goto out; | |
372 | /* | |
373 | * Process is sleeping and traced... make it runnable | |
374 | * so it can discover the signal in issig() and stop | |
375 | * for the parent. | |
376 | */ | |
377 | if (p->p_flag&STRC) | |
378 | goto run; | |
379 | switch (sig) { | |
380 | ||
381 | case SIGSTOP: | |
382 | case SIGTSTP: | |
383 | case SIGTTIN: | |
384 | case SIGTTOU: | |
385 | /* | |
386 | * These are the signals which by default | |
387 | * stop a process. | |
388 | */ | |
389 | if (action != SIG_DFL) | |
390 | goto run; | |
391 | /* | |
392 | * Don't clog system with children of init | |
393 | * stopped from the keyboard. | |
394 | */ | |
395 | if (sig != SIGSTOP && p->p_pptr == &proc[1]) { | |
396 | psignal(p, SIGKILL); | |
feff6b5a | 397 | p->p_sig &= ~mask; |
687880f9 BJ |
398 | splx(s); |
399 | return; | |
400 | } | |
401 | /* | |
402 | * If a child in vfork(), stopping could | |
403 | * cause deadlock. | |
404 | */ | |
405 | if (p->p_flag&SVFORK) | |
406 | goto out; | |
feff6b5a | 407 | p->p_sig &= ~mask; |
687880f9 | 408 | p->p_cursig = sig; |
ad6c75cb | 409 | psignal(p->p_pptr, SIGCHLD); |
687880f9 BJ |
410 | stop(p); |
411 | goto out; | |
412 | ||
413 | case SIGIO: | |
414 | case SIGURG: | |
415 | case SIGCHLD: | |
434b302a | 416 | case SIGWINCH: |
687880f9 BJ |
417 | /* |
418 | * These signals are special in that they | |
419 | * don't get propogated... if the process | |
420 | * isn't interested, forget it. | |
421 | */ | |
422 | if (action != SIG_DFL) | |
423 | goto run; | |
feff6b5a | 424 | p->p_sig &= ~mask; /* take it away */ |
687880f9 BJ |
425 | goto out; |
426 | ||
427 | default: | |
428 | /* | |
429 | * All other signals cause the process to run | |
430 | */ | |
431 | goto run; | |
432 | } | |
433 | /*NOTREACHED*/ | |
434 | ||
435 | case SSTOP: | |
436 | /* | |
437 | * If traced process is already stopped, | |
438 | * then no further action is necessary. | |
439 | */ | |
440 | if (p->p_flag&STRC) | |
441 | goto out; | |
442 | switch (sig) { | |
443 | ||
444 | case SIGKILL: | |
445 | /* | |
446 | * Kill signal always sets processes running. | |
447 | */ | |
448 | goto run; | |
449 | ||
450 | case SIGCONT: | |
451 | /* | |
452 | * If the process catches SIGCONT, let it handle | |
453 | * the signal itself. If it isn't waiting on | |
454 | * an event, then it goes back to run state. | |
455 | * Otherwise, process goes back to sleep state. | |
456 | */ | |
457 | if (action != SIG_DFL || p->p_wchan == 0) | |
458 | goto run; | |
459 | p->p_stat = SSLEEP; | |
460 | goto out; | |
461 | ||
462 | case SIGSTOP: | |
463 | case SIGTSTP: | |
464 | case SIGTTIN: | |
465 | case SIGTTOU: | |
466 | /* | |
467 | * Already stopped, don't need to stop again. | |
468 | * (If we did the shell could get confused.) | |
469 | */ | |
feff6b5a | 470 | p->p_sig &= ~mask; /* take it away */ |
687880f9 BJ |
471 | goto out; |
472 | ||
473 | default: | |
474 | /* | |
475 | * If process is sleeping interruptibly, then | |
476 | * unstick it so that when it is continued | |
477 | * it can look at the signal. | |
478 | * But don't setrun the process as its not to | |
479 | * be unstopped by the signal alone. | |
480 | */ | |
481 | if (p->p_wchan && p->p_pri > PZERO) | |
482 | unsleep(p); | |
483 | goto out; | |
484 | } | |
485 | /*NOTREACHED*/ | |
486 | ||
487 | default: | |
488 | /* | |
489 | * SRUN, SIDL, SZOMB do nothing with the signal, | |
490 | * other than kicking ourselves if we are running. | |
491 | * It will either never be noticed, or noticed very soon. | |
492 | */ | |
493 | if (p == u.u_procp && !noproc) | |
494 | aston(); | |
495 | goto out; | |
496 | } | |
497 | /*NOTREACHED*/ | |
498 | run: | |
499 | /* | |
500 | * Raise priority to at least PUSER. | |
501 | */ | |
502 | if (p->p_pri > PUSER) | |
e4f89871 | 503 | p->p_pri = PUSER; |
687880f9 BJ |
504 | setrun(p); |
505 | out: | |
506 | splx(s); | |
507 | } | |
508 | ||
509 | /* | |
510 | * Returns true if the current | |
511 | * process has a signal to process. | |
512 | * The signal to process is put in p_cursig. | |
513 | * This is asked at least once each time a process enters the | |
514 | * system (though this can usually be done without actually | |
515 | * calling issig by checking the pending signal masks.) | |
516 | * A signal does not do anything | |
517 | * directly to a process; it sets | |
518 | * a flag that asks the process to | |
519 | * do something to itself. | |
520 | */ | |
521 | issig() | |
522 | { | |
523 | register struct proc *p; | |
524 | register int sig; | |
feff6b5a | 525 | int sigbits, mask; |
687880f9 BJ |
526 | |
527 | p = u.u_procp; | |
528 | for (;;) { | |
f99e4a3a | 529 | sigbits = p->p_sig &~ p->p_sigmask; |
687880f9 | 530 | if ((p->p_flag&STRC) == 0) |
f99e4a3a | 531 | sigbits &= ~p->p_sigignore; |
687880f9 | 532 | if (p->p_flag&SVFORK) |
3b2ddb34 | 533 | sigbits &= ~stopsigmask; |
687880f9 BJ |
534 | if (sigbits == 0) |
535 | break; | |
8011f5df | 536 | sig = ffs((long)sigbits); |
feff6b5a JB |
537 | mask = sigmask(sig); |
538 | p->p_sig &= ~mask; /* take the signal! */ | |
687880f9 | 539 | p->p_cursig = sig; |
dd012d1e | 540 | if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { |
687880f9 BJ |
541 | /* |
542 | * If traced, always stop, and stay | |
543 | * stopped until released by the parent. | |
544 | */ | |
ad6c75cb | 545 | psignal(p->p_pptr, SIGCHLD); |
687880f9 BJ |
546 | do { |
547 | stop(p); | |
548 | swtch(); | |
549 | } while (!procxmt() && p->p_flag&STRC); | |
550 | ||
551 | /* | |
f99e4a3a SL |
552 | * If the traced bit got turned off, |
553 | * then put the signal taken above back into p_sig | |
554 | * and go back up to the top to rescan signals. | |
555 | * This ensures that p_sig* and u_signal are consistent. | |
687880f9 | 556 | */ |
f99e4a3a | 557 | if ((p->p_flag&STRC) == 0) { |
feff6b5a | 558 | p->p_sig |= mask; |
687880f9 BJ |
559 | continue; |
560 | } | |
561 | ||
562 | /* | |
563 | * If parent wants us to take the signal, | |
564 | * then it will leave it in p->p_cursig; | |
565 | * otherwise we just look for signals again. | |
566 | */ | |
567 | sig = p->p_cursig; | |
568 | if (sig == 0) | |
569 | continue; | |
f99e4a3a SL |
570 | |
571 | /* | |
572 | * If signal is being masked put it back | |
573 | * into p_sig and look for other signals. | |
574 | */ | |
feff6b5a JB |
575 | mask = sigmask(sig); |
576 | if (p->p_sigmask & mask) { | |
577 | p->p_sig |= mask; | |
f99e4a3a SL |
578 | continue; |
579 | } | |
687880f9 | 580 | } |
a488db1a | 581 | switch ((int)u.u_signal[sig]) { |
687880f9 BJ |
582 | |
583 | case SIG_DFL: | |
584 | /* | |
585 | * Don't take default actions on system processes. | |
586 | */ | |
587 | if (p->p_ppid == 0) | |
588 | break; | |
589 | switch (sig) { | |
590 | ||
591 | case SIGTSTP: | |
592 | case SIGTTIN: | |
593 | case SIGTTOU: | |
594 | /* | |
595 | * Children of init aren't allowed to stop | |
596 | * on signals from the keyboard. | |
597 | */ | |
598 | if (p->p_pptr == &proc[1]) { | |
599 | psignal(p, SIGKILL); | |
600 | continue; | |
601 | } | |
602 | /* fall into ... */ | |
603 | ||
604 | case SIGSTOP: | |
605 | if (p->p_flag&STRC) | |
606 | continue; | |
ad6c75cb | 607 | psignal(p->p_pptr, SIGCHLD); |
687880f9 BJ |
608 | stop(p); |
609 | swtch(); | |
610 | continue; | |
611 | ||
612 | case SIGCONT: | |
613 | case SIGCHLD: | |
dd012d1e | 614 | case SIGURG: |
457aa395 | 615 | case SIGIO: |
434b302a | 616 | case SIGWINCH: |
687880f9 BJ |
617 | /* |
618 | * These signals are normally not | |
619 | * sent if the action is the default. | |
620 | */ | |
621 | continue; /* == ignore */ | |
622 | ||
623 | default: | |
624 | goto send; | |
625 | } | |
626 | /*NOTREACHED*/ | |
627 | ||
628 | case SIG_HOLD: | |
629 | case SIG_IGN: | |
630 | /* | |
631 | * Masking above should prevent us | |
632 | * ever trying to take action on a held | |
633 | * or ignored signal, unless process is traced. | |
634 | */ | |
635 | if ((p->p_flag&STRC) == 0) | |
636 | printf("issig\n"); | |
637 | continue; | |
638 | ||
639 | default: | |
640 | /* | |
641 | * This signal has an action, let | |
642 | * psig process it. | |
643 | */ | |
644 | goto send; | |
645 | } | |
646 | /*NOTREACHED*/ | |
647 | } | |
648 | /* | |
649 | * Didn't find a signal to send. | |
650 | */ | |
651 | p->p_cursig = 0; | |
652 | return (0); | |
653 | ||
654 | send: | |
655 | /* | |
656 | * Let psig process the signal. | |
657 | */ | |
658 | return (sig); | |
659 | } | |
660 | ||
687880f9 BJ |
661 | /* |
662 | * Put the argument process into the stopped | |
ad6c75cb MK |
663 | * state and notify the parent via wakeup. |
664 | * Signals are handled elsewhere. | |
687880f9 BJ |
665 | */ |
666 | stop(p) | |
667 | register struct proc *p; | |
668 | { | |
669 | ||
670 | p->p_stat = SSTOP; | |
671 | p->p_flag &= ~SWTED; | |
672 | wakeup((caddr_t)p->p_pptr); | |
687880f9 BJ |
673 | } |
674 | ||
675 | /* | |
676 | * Perform the action specified by | |
677 | * the current signal. | |
678 | * The usual sequence is: | |
679 | * if (issig()) | |
680 | * psig(); | |
681 | * The signal bit has already been cleared by issig, | |
682 | * and the current signal number stored in p->p_cursig. | |
683 | */ | |
684 | psig() | |
685 | { | |
dd012d1e SL |
686 | register struct proc *p = u.u_procp; |
687 | register int sig = p->p_cursig; | |
feff6b5a | 688 | int mask = sigmask(sig), returnmask; |
687880f9 BJ |
689 | register int (*action)(); |
690 | ||
dd012d1e | 691 | if (sig == 0) |
687880f9 | 692 | panic("psig"); |
dd012d1e | 693 | action = u.u_signal[sig]; |
687880f9 | 694 | if (action != SIG_DFL) { |
feff6b5a | 695 | if (action == SIG_IGN || (p->p_sigmask & mask)) |
687880f9 BJ |
696 | panic("psig action"); |
697 | u.u_error = 0; | |
687880f9 | 698 | /* |
dd012d1e SL |
699 | * Set the new mask value and also defer further |
700 | * occurences of this signal (unless we're simulating | |
701 | * the old signal facilities). | |
702 | * | |
703 | * Special case: user has done a sigpause. Here the | |
704 | * current mask is not of interest, but rather the | |
705 | * mask from before the sigpause is what we want restored | |
706 | * after the signal processing is completed. | |
687880f9 | 707 | */ |
feff6b5a | 708 | (void) splhigh(); |
dd012d1e SL |
709 | if (p->p_flag & SOUSIG) { |
710 | if (sig != SIGILL && sig != SIGTRAP) { | |
711 | u.u_signal[sig] = SIG_DFL; | |
feff6b5a | 712 | p->p_sigcatch &= ~mask; |
dd012d1e | 713 | } |
feff6b5a | 714 | mask = 0; |
687880f9 | 715 | } |
dd012d1e SL |
716 | if (p->p_flag & SOMASK) { |
717 | returnmask = u.u_oldmask; | |
718 | p->p_flag &= ~SOMASK; | |
719 | } else | |
720 | returnmask = p->p_sigmask; | |
feff6b5a | 721 | p->p_sigmask |= u.u_sigmask[sig] | mask; |
dd012d1e | 722 | (void) spl0(); |
1e3738da | 723 | u.u_ru.ru_nsignals++; |
dd012d1e SL |
724 | sendsig(action, sig, returnmask); |
725 | p->p_cursig = 0; | |
687880f9 BJ |
726 | return; |
727 | } | |
728 | u.u_acflag |= AXSIG; | |
dd012d1e | 729 | switch (sig) { |
687880f9 BJ |
730 | |
731 | case SIGILL: | |
732 | case SIGIOT: | |
733 | case SIGBUS: | |
734 | case SIGQUIT: | |
735 | case SIGTRAP: | |
736 | case SIGEMT: | |
737 | case SIGFPE: | |
738 | case SIGSEGV: | |
739 | case SIGSYS: | |
dd012d1e | 740 | u.u_arg[0] = sig; |
687880f9 | 741 | if (core()) |
dd012d1e | 742 | sig += 0200; |
687880f9 | 743 | } |
dd012d1e | 744 | exit(sig); |
687880f9 BJ |
745 | } |
746 | ||
687880f9 BJ |
747 | /* |
748 | * Create a core image on the file "core" | |
749 | * If you are looking for protection glitches, | |
750 | * there are probably a wealth of them here | |
751 | * when this occurs to a suid command. | |
752 | * | |
753 | * It writes UPAGES block of the | |
754 | * user.h area followed by the entire | |
755 | * data+stack segments. | |
756 | */ | |
757 | core() | |
758 | { | |
759 | register struct inode *ip; | |
715baff1 | 760 | register struct nameidata *ndp = &u.u_nd; |
687880f9 | 761 | |
be6bd5b8 | 762 | if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) |
7b0cb7cb | 763 | return (0); |
1e3738da BJ |
764 | if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= |
765 | u.u_rlimit[RLIMIT_CORE].rlim_cur) | |
687880f9 | 766 | return (0); |
362072cf KM |
767 | if (u.u_procp->p_textp && access(u.u_procp->p_textp->x_iptr, IREAD)) |
768 | return (0); | |
687880f9 | 769 | u.u_error = 0; |
715baff1 KM |
770 | ndp->ni_nameiop = CREATE | FOLLOW; |
771 | ndp->ni_segflg = UIO_SYSSPACE; | |
772 | ndp->ni_dirp = "core"; | |
773 | ip = namei(ndp); | |
687880f9 BJ |
774 | if (ip == NULL) { |
775 | if (u.u_error) | |
776 | return (0); | |
715baff1 | 777 | ip = maknode(0644, ndp); |
687880f9 BJ |
778 | if (ip==NULL) |
779 | return (0); | |
780 | } | |
7b0cb7cb BJ |
781 | if (access(ip, IWRITE) || |
782 | (ip->i_mode&IFMT) != IFREG || | |
783 | ip->i_nlink != 1) { | |
687880f9 | 784 | u.u_error = EFAULT; |
7b0cb7cb BJ |
785 | goto out; |
786 | } | |
728df0db SL |
787 | #ifdef MMAP |
788 | { register int fd; | |
789 | /* unmasp funky devices in the user's address space */ | |
790 | for (fd = 0; fd < u.u_lastfile; fd++) | |
791 | if (u.u_ofile[fd] && (u.u_pofile[fd] & UF_MAPPED)) | |
792 | munmapfd(fd); | |
793 | } | |
794 | #endif | |
4f083fd7 | 795 | itrunc(ip, (u_long)0); |
7b0cb7cb | 796 | u.u_acflag |= ACORE; |
dd012d1e SL |
797 | u.u_error = rdwri(UIO_WRITE, ip, |
798 | (caddr_t)&u, | |
799 | ctob(UPAGES), | |
8011f5df | 800 | (off_t)0, 1, (int *)0); |
1edb1cf8 | 801 | if (u.u_error == 0) |
a1edc12b | 802 | u.u_error = rdwri(UIO_WRITE, ip, |
e0fc9a90 | 803 | (caddr_t)ctob(dptov(u.u_procp, 0)), |
8011f5df MK |
804 | (int)ctob(u.u_dsize), |
805 | (off_t)ctob(UPAGES), 0, (int *)0); | |
1edb1cf8 | 806 | if (u.u_error == 0) |
a1edc12b | 807 | u.u_error = rdwri(UIO_WRITE, ip, |
e0fc9a90 | 808 | (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), |
8011f5df MK |
809 | (int)ctob(u.u_ssize), |
810 | (off_t)ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); | |
7b0cb7cb | 811 | out: |
687880f9 | 812 | iput(ip); |
7b0cb7cb | 813 | return (u.u_error == 0); |
687880f9 | 814 | } |