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 | * | |
8fe87cbb | 6 | * @(#)kern_sig.c 7.4 (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 | 232 | register struct a { |
8fe87cbb | 233 | int pgid; |
3b4f6e10 SL |
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 | } | |
8fe87cbb | 241 | u.u_error = killpg1(uap->signo, uap->pgid, 0); |
1e3738da BJ |
242 | } |
243 | ||
dd012d1e SL |
244 | /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ |
245 | ||
8fe87cbb MT |
246 | killpg1(signo, pgid, all) |
247 | int signo, pgid, all; | |
3b4f6e10 SL |
248 | { |
249 | register struct proc *p; | |
8fe87cbb MT |
250 | struct pgrp *pgrp; |
251 | int f = 0, error = 0; | |
3b4f6e10 | 252 | |
8fe87cbb MT |
253 | |
254 | if (all) | |
255 | /* | |
256 | * broadcast | |
687880f9 | 257 | */ |
8fe87cbb MT |
258 | for (p = allproc; p != NULL; p = p->p_nxt) { |
259 | if (p->p_ppid == 0 || p->p_flag&SSYS || | |
260 | p == u.u_procp || | |
261 | (u.u_uid && u.u_uid != p->p_uid && | |
262 | !(signo == SIGCONT && inferior(p)))) | |
263 | continue; | |
264 | f++; | |
265 | if (signo) | |
266 | psignal(p, signo); | |
267 | } | |
268 | else { | |
269 | if (pgid == 0) | |
270 | /* | |
271 | * zero pgid means send to my process group. | |
272 | */ | |
273 | pgrp = u.u_procp->p_pgrp; | |
274 | else { | |
275 | pgrp = pgfind(pgid); | |
276 | if (pgrp == NULL) | |
277 | return(ESRCH); | |
278 | } | |
279 | if (!(pgrp->pg_jobc) && | |
280 | (signo==SIGTTIN || signo==SIGTTOU || signo==SIGTSTP)) | |
281 | return(EPERM); | |
282 | for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) { | |
283 | if (p->p_ppid == 0 || p->p_flag&SSYS) | |
284 | continue; | |
285 | if (u.u_uid && u.u_uid != p->p_uid && | |
286 | !(signo == SIGCONT && inferior(p))) { | |
c52373fd | 287 | error = EPERM; |
8fe87cbb MT |
288 | continue; |
289 | } | |
290 | f++; | |
291 | if (signo) | |
292 | psignal(p, signo); | |
7713be67 | 293 | } |
687880f9 | 294 | } |
8db20a41 | 295 | return (error ? error : (f == 0 ? ESRCH : 0)); |
4147b3f6 | 296 | } |
687880f9 BJ |
297 | |
298 | /* | |
299 | * Send the specified signal to | |
8fe87cbb | 300 | * all processes with 'pgid' as |
687880f9 | 301 | * process group. |
687880f9 | 302 | */ |
8fe87cbb MT |
303 | gsignal(pgid, sig) |
304 | { | |
305 | register struct pgrp *pgrp; | |
306 | register struct proc *p; | |
307 | ||
308 | if (!pgid) | |
309 | return; | |
310 | if ((pgrp = pgfind(pgid)) == NULL) | |
311 | return; | |
312 | pgsignal(pgrp, sig); | |
313 | } | |
314 | ||
315 | pgsignal(pgrp, sig) | |
316 | register struct pgrp *pgrp; | |
687880f9 BJ |
317 | { |
318 | register struct proc *p; | |
319 | ||
8fe87cbb MT |
320 | if (!(pgrp->pg_jobc) && |
321 | (sig==SIGTTIN || sig==SIGTTOU || sig==SIGTSTP)) | |
687880f9 | 322 | return; |
8fe87cbb MT |
323 | for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) |
324 | psignal(p, sig); | |
687880f9 BJ |
325 | } |
326 | ||
327 | /* | |
328 | * Send the specified signal to | |
329 | * the specified process. | |
330 | */ | |
331 | psignal(p, sig) | |
332 | register struct proc *p; | |
333 | register int sig; | |
334 | { | |
335 | register int s; | |
336 | register int (*action)(); | |
feff6b5a | 337 | int mask; |
687880f9 BJ |
338 | |
339 | if ((unsigned)sig >= NSIG) | |
340 | return; | |
feff6b5a | 341 | mask = sigmask(sig); |
687880f9 BJ |
342 | |
343 | /* | |
344 | * If proc is traced, always give parent a chance. | |
687880f9 BJ |
345 | */ |
346 | if (p->p_flag & STRC) | |
347 | action = SIG_DFL; | |
348 | else { | |
687880f9 | 349 | /* |
dd012d1e SL |
350 | * If the signal is being ignored, |
351 | * then we forget about it immediately. | |
687880f9 | 352 | */ |
feff6b5a | 353 | if (p->p_sigignore & mask) |
687880f9 | 354 | return; |
feff6b5a | 355 | if (p->p_sigmask & mask) |
dd012d1e | 356 | action = SIG_HOLD; |
feff6b5a | 357 | else if (p->p_sigcatch & mask) |
dd012d1e SL |
358 | action = SIG_CATCH; |
359 | else | |
360 | action = SIG_DFL; | |
687880f9 | 361 | } |
687880f9 | 362 | if (sig) { |
687880f9 BJ |
363 | switch (sig) { |
364 | ||
365 | case SIGTERM: | |
dd012d1e | 366 | if ((p->p_flag&STRC) || action != SIG_DFL) |
687880f9 BJ |
367 | break; |
368 | /* fall into ... */ | |
369 | ||
370 | case SIGKILL: | |
371 | if (p->p_nice > NZERO) | |
372 | p->p_nice = NZERO; | |
373 | break; | |
374 | ||
375 | case SIGCONT: | |
3b2ddb34 | 376 | p->p_sig &= ~stopsigmask; |
687880f9 BJ |
377 | break; |
378 | ||
687880f9 BJ |
379 | case SIGTSTP: |
380 | case SIGTTIN: | |
381 | case SIGTTOU: | |
8fe87cbb MT |
382 | /*FALLTHROUGH*/ |
383 | case SIGSTOP: | |
feff6b5a | 384 | p->p_sig &= ~sigmask(SIGCONT); |
687880f9 BJ |
385 | break; |
386 | } | |
8fe87cbb | 387 | p->p_sig |= mask; |
687880f9 | 388 | } |
687880f9 BJ |
389 | /* |
390 | * Defer further processing for signals which are held. | |
391 | */ | |
392 | if (action == SIG_HOLD) | |
393 | return; | |
feff6b5a | 394 | s = splhigh(); |
687880f9 BJ |
395 | switch (p->p_stat) { |
396 | ||
397 | case SSLEEP: | |
398 | /* | |
399 | * If process is sleeping at negative priority | |
400 | * we can't interrupt the sleep... the signal will | |
401 | * be noticed when the process returns through | |
402 | * trap() or syscall(). | |
403 | */ | |
404 | if (p->p_pri <= PZERO) | |
405 | goto out; | |
406 | /* | |
407 | * Process is sleeping and traced... make it runnable | |
408 | * so it can discover the signal in issig() and stop | |
409 | * for the parent. | |
410 | */ | |
411 | if (p->p_flag&STRC) | |
412 | goto run; | |
413 | switch (sig) { | |
414 | ||
415 | case SIGSTOP: | |
416 | case SIGTSTP: | |
417 | case SIGTTIN: | |
418 | case SIGTTOU: | |
419 | /* | |
420 | * These are the signals which by default | |
421 | * stop a process. | |
422 | */ | |
423 | if (action != SIG_DFL) | |
424 | goto run; | |
687880f9 BJ |
425 | /* |
426 | * If a child in vfork(), stopping could | |
427 | * cause deadlock. | |
428 | */ | |
429 | if (p->p_flag&SVFORK) | |
430 | goto out; | |
feff6b5a | 431 | p->p_sig &= ~mask; |
687880f9 | 432 | p->p_cursig = sig; |
ad6c75cb | 433 | psignal(p->p_pptr, SIGCHLD); |
687880f9 BJ |
434 | stop(p); |
435 | goto out; | |
436 | ||
437 | case SIGIO: | |
438 | case SIGURG: | |
439 | case SIGCHLD: | |
434b302a | 440 | case SIGWINCH: |
687880f9 BJ |
441 | /* |
442 | * These signals are special in that they | |
443 | * don't get propogated... if the process | |
444 | * isn't interested, forget it. | |
445 | */ | |
446 | if (action != SIG_DFL) | |
447 | goto run; | |
feff6b5a | 448 | p->p_sig &= ~mask; /* take it away */ |
687880f9 BJ |
449 | goto out; |
450 | ||
451 | default: | |
452 | /* | |
453 | * All other signals cause the process to run | |
454 | */ | |
455 | goto run; | |
456 | } | |
457 | /*NOTREACHED*/ | |
458 | ||
459 | case SSTOP: | |
460 | /* | |
461 | * If traced process is already stopped, | |
462 | * then no further action is necessary. | |
463 | */ | |
464 | if (p->p_flag&STRC) | |
465 | goto out; | |
466 | switch (sig) { | |
467 | ||
468 | case SIGKILL: | |
469 | /* | |
470 | * Kill signal always sets processes running. | |
471 | */ | |
472 | goto run; | |
473 | ||
474 | case SIGCONT: | |
475 | /* | |
476 | * If the process catches SIGCONT, let it handle | |
477 | * the signal itself. If it isn't waiting on | |
478 | * an event, then it goes back to run state. | |
479 | * Otherwise, process goes back to sleep state. | |
480 | */ | |
481 | if (action != SIG_DFL || p->p_wchan == 0) | |
482 | goto run; | |
483 | p->p_stat = SSLEEP; | |
484 | goto out; | |
485 | ||
486 | case SIGSTOP: | |
487 | case SIGTSTP: | |
488 | case SIGTTIN: | |
489 | case SIGTTOU: | |
490 | /* | |
491 | * Already stopped, don't need to stop again. | |
492 | * (If we did the shell could get confused.) | |
493 | */ | |
feff6b5a | 494 | p->p_sig &= ~mask; /* take it away */ |
687880f9 BJ |
495 | goto out; |
496 | ||
497 | default: | |
498 | /* | |
499 | * If process is sleeping interruptibly, then | |
500 | * unstick it so that when it is continued | |
501 | * it can look at the signal. | |
502 | * But don't setrun the process as its not to | |
503 | * be unstopped by the signal alone. | |
504 | */ | |
505 | if (p->p_wchan && p->p_pri > PZERO) | |
506 | unsleep(p); | |
507 | goto out; | |
508 | } | |
509 | /*NOTREACHED*/ | |
510 | ||
511 | default: | |
512 | /* | |
513 | * SRUN, SIDL, SZOMB do nothing with the signal, | |
514 | * other than kicking ourselves if we are running. | |
515 | * It will either never be noticed, or noticed very soon. | |
516 | */ | |
517 | if (p == u.u_procp && !noproc) | |
518 | aston(); | |
519 | goto out; | |
520 | } | |
521 | /*NOTREACHED*/ | |
522 | run: | |
523 | /* | |
524 | * Raise priority to at least PUSER. | |
525 | */ | |
526 | if (p->p_pri > PUSER) | |
e4f89871 | 527 | p->p_pri = PUSER; |
687880f9 BJ |
528 | setrun(p); |
529 | out: | |
530 | splx(s); | |
531 | } | |
532 | ||
533 | /* | |
534 | * Returns true if the current | |
535 | * process has a signal to process. | |
536 | * The signal to process is put in p_cursig. | |
537 | * This is asked at least once each time a process enters the | |
538 | * system (though this can usually be done without actually | |
539 | * calling issig by checking the pending signal masks.) | |
540 | * A signal does not do anything | |
541 | * directly to a process; it sets | |
542 | * a flag that asks the process to | |
543 | * do something to itself. | |
544 | */ | |
545 | issig() | |
546 | { | |
547 | register struct proc *p; | |
548 | register int sig; | |
feff6b5a | 549 | int sigbits, mask; |
687880f9 BJ |
550 | |
551 | p = u.u_procp; | |
552 | for (;;) { | |
f99e4a3a | 553 | sigbits = p->p_sig &~ p->p_sigmask; |
687880f9 | 554 | if ((p->p_flag&STRC) == 0) |
f99e4a3a | 555 | sigbits &= ~p->p_sigignore; |
687880f9 | 556 | if (p->p_flag&SVFORK) |
3b2ddb34 | 557 | sigbits &= ~stopsigmask; |
687880f9 BJ |
558 | if (sigbits == 0) |
559 | break; | |
8011f5df | 560 | sig = ffs((long)sigbits); |
feff6b5a JB |
561 | mask = sigmask(sig); |
562 | p->p_sig &= ~mask; /* take the signal! */ | |
687880f9 | 563 | p->p_cursig = sig; |
dd012d1e | 564 | if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { |
687880f9 BJ |
565 | /* |
566 | * If traced, always stop, and stay | |
567 | * stopped until released by the parent. | |
568 | */ | |
ad6c75cb | 569 | psignal(p->p_pptr, SIGCHLD); |
687880f9 BJ |
570 | do { |
571 | stop(p); | |
572 | swtch(); | |
573 | } while (!procxmt() && p->p_flag&STRC); | |
574 | ||
575 | /* | |
f99e4a3a SL |
576 | * If the traced bit got turned off, |
577 | * then put the signal taken above back into p_sig | |
578 | * and go back up to the top to rescan signals. | |
579 | * This ensures that p_sig* and u_signal are consistent. | |
687880f9 | 580 | */ |
f99e4a3a | 581 | if ((p->p_flag&STRC) == 0) { |
feff6b5a | 582 | p->p_sig |= mask; |
687880f9 BJ |
583 | continue; |
584 | } | |
585 | ||
586 | /* | |
587 | * If parent wants us to take the signal, | |
588 | * then it will leave it in p->p_cursig; | |
589 | * otherwise we just look for signals again. | |
590 | */ | |
591 | sig = p->p_cursig; | |
592 | if (sig == 0) | |
593 | continue; | |
f99e4a3a SL |
594 | |
595 | /* | |
596 | * If signal is being masked put it back | |
597 | * into p_sig and look for other signals. | |
598 | */ | |
feff6b5a JB |
599 | mask = sigmask(sig); |
600 | if (p->p_sigmask & mask) { | |
601 | p->p_sig |= mask; | |
f99e4a3a SL |
602 | continue; |
603 | } | |
687880f9 | 604 | } |
a488db1a | 605 | switch ((int)u.u_signal[sig]) { |
687880f9 BJ |
606 | |
607 | case SIG_DFL: | |
608 | /* | |
609 | * Don't take default actions on system processes. | |
610 | */ | |
611 | if (p->p_ppid == 0) | |
612 | break; | |
613 | switch (sig) { | |
614 | ||
615 | case SIGTSTP: | |
616 | case SIGTTIN: | |
617 | case SIGTTOU: | |
687880f9 BJ |
618 | case SIGSTOP: |
619 | if (p->p_flag&STRC) | |
620 | continue; | |
ad6c75cb | 621 | psignal(p->p_pptr, SIGCHLD); |
687880f9 BJ |
622 | stop(p); |
623 | swtch(); | |
624 | continue; | |
625 | ||
626 | case SIGCONT: | |
627 | case SIGCHLD: | |
dd012d1e | 628 | case SIGURG: |
457aa395 | 629 | case SIGIO: |
434b302a | 630 | case SIGWINCH: |
687880f9 BJ |
631 | /* |
632 | * These signals are normally not | |
633 | * sent if the action is the default. | |
634 | */ | |
635 | continue; /* == ignore */ | |
636 | ||
637 | default: | |
638 | goto send; | |
639 | } | |
640 | /*NOTREACHED*/ | |
641 | ||
642 | case SIG_HOLD: | |
643 | case SIG_IGN: | |
644 | /* | |
645 | * Masking above should prevent us | |
646 | * ever trying to take action on a held | |
647 | * or ignored signal, unless process is traced. | |
648 | */ | |
649 | if ((p->p_flag&STRC) == 0) | |
650 | printf("issig\n"); | |
651 | continue; | |
652 | ||
653 | default: | |
654 | /* | |
655 | * This signal has an action, let | |
656 | * psig process it. | |
657 | */ | |
658 | goto send; | |
659 | } | |
660 | /*NOTREACHED*/ | |
661 | } | |
662 | /* | |
663 | * Didn't find a signal to send. | |
664 | */ | |
665 | p->p_cursig = 0; | |
666 | return (0); | |
667 | ||
668 | send: | |
669 | /* | |
670 | * Let psig process the signal. | |
671 | */ | |
672 | return (sig); | |
673 | } | |
674 | ||
687880f9 BJ |
675 | /* |
676 | * Put the argument process into the stopped | |
ad6c75cb MK |
677 | * state and notify the parent via wakeup. |
678 | * Signals are handled elsewhere. | |
687880f9 BJ |
679 | */ |
680 | stop(p) | |
681 | register struct proc *p; | |
682 | { | |
683 | ||
684 | p->p_stat = SSTOP; | |
685 | p->p_flag &= ~SWTED; | |
686 | wakeup((caddr_t)p->p_pptr); | |
687880f9 BJ |
687 | } |
688 | ||
689 | /* | |
690 | * Perform the action specified by | |
691 | * the current signal. | |
692 | * The usual sequence is: | |
693 | * if (issig()) | |
694 | * psig(); | |
695 | * The signal bit has already been cleared by issig, | |
696 | * and the current signal number stored in p->p_cursig. | |
697 | */ | |
698 | psig() | |
699 | { | |
dd012d1e SL |
700 | register struct proc *p = u.u_procp; |
701 | register int sig = p->p_cursig; | |
feff6b5a | 702 | int mask = sigmask(sig), returnmask; |
687880f9 BJ |
703 | register int (*action)(); |
704 | ||
dd012d1e | 705 | if (sig == 0) |
687880f9 | 706 | panic("psig"); |
dd012d1e | 707 | action = u.u_signal[sig]; |
687880f9 | 708 | if (action != SIG_DFL) { |
feff6b5a | 709 | if (action == SIG_IGN || (p->p_sigmask & mask)) |
687880f9 BJ |
710 | panic("psig action"); |
711 | u.u_error = 0; | |
687880f9 | 712 | /* |
dd012d1e SL |
713 | * Set the new mask value and also defer further |
714 | * occurences of this signal (unless we're simulating | |
715 | * the old signal facilities). | |
716 | * | |
717 | * Special case: user has done a sigpause. Here the | |
718 | * current mask is not of interest, but rather the | |
719 | * mask from before the sigpause is what we want restored | |
720 | * after the signal processing is completed. | |
687880f9 | 721 | */ |
feff6b5a | 722 | (void) splhigh(); |
dd012d1e SL |
723 | if (p->p_flag & SOUSIG) { |
724 | if (sig != SIGILL && sig != SIGTRAP) { | |
725 | u.u_signal[sig] = SIG_DFL; | |
feff6b5a | 726 | p->p_sigcatch &= ~mask; |
dd012d1e | 727 | } |
feff6b5a | 728 | mask = 0; |
687880f9 | 729 | } |
dd012d1e SL |
730 | if (p->p_flag & SOMASK) { |
731 | returnmask = u.u_oldmask; | |
732 | p->p_flag &= ~SOMASK; | |
733 | } else | |
734 | returnmask = p->p_sigmask; | |
feff6b5a | 735 | p->p_sigmask |= u.u_sigmask[sig] | mask; |
dd012d1e | 736 | (void) spl0(); |
1e3738da | 737 | u.u_ru.ru_nsignals++; |
dd012d1e SL |
738 | sendsig(action, sig, returnmask); |
739 | p->p_cursig = 0; | |
687880f9 BJ |
740 | return; |
741 | } | |
742 | u.u_acflag |= AXSIG; | |
dd012d1e | 743 | switch (sig) { |
687880f9 BJ |
744 | |
745 | case SIGILL: | |
746 | case SIGIOT: | |
747 | case SIGBUS: | |
748 | case SIGQUIT: | |
749 | case SIGTRAP: | |
750 | case SIGEMT: | |
751 | case SIGFPE: | |
752 | case SIGSEGV: | |
753 | case SIGSYS: | |
dd012d1e | 754 | u.u_arg[0] = sig; |
687880f9 | 755 | if (core()) |
dd012d1e | 756 | sig += 0200; |
687880f9 | 757 | } |
dd012d1e | 758 | exit(sig); |
687880f9 BJ |
759 | } |
760 | ||
687880f9 BJ |
761 | /* |
762 | * Create a core image on the file "core" | |
763 | * If you are looking for protection glitches, | |
764 | * there are probably a wealth of them here | |
765 | * when this occurs to a suid command. | |
766 | * | |
767 | * It writes UPAGES block of the | |
768 | * user.h area followed by the entire | |
769 | * data+stack segments. | |
770 | */ | |
771 | core() | |
772 | { | |
773 | register struct inode *ip; | |
715baff1 | 774 | register struct nameidata *ndp = &u.u_nd; |
687880f9 | 775 | |
be6bd5b8 | 776 | if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) |
7b0cb7cb | 777 | return (0); |
1e3738da BJ |
778 | if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= |
779 | u.u_rlimit[RLIMIT_CORE].rlim_cur) | |
687880f9 | 780 | return (0); |
362072cf KM |
781 | if (u.u_procp->p_textp && access(u.u_procp->p_textp->x_iptr, IREAD)) |
782 | return (0); | |
687880f9 | 783 | u.u_error = 0; |
715baff1 KM |
784 | ndp->ni_nameiop = CREATE | FOLLOW; |
785 | ndp->ni_segflg = UIO_SYSSPACE; | |
786 | ndp->ni_dirp = "core"; | |
787 | ip = namei(ndp); | |
687880f9 BJ |
788 | if (ip == NULL) { |
789 | if (u.u_error) | |
790 | return (0); | |
715baff1 | 791 | ip = maknode(0644, ndp); |
687880f9 BJ |
792 | if (ip==NULL) |
793 | return (0); | |
794 | } | |
7b0cb7cb BJ |
795 | if (access(ip, IWRITE) || |
796 | (ip->i_mode&IFMT) != IFREG || | |
797 | ip->i_nlink != 1) { | |
687880f9 | 798 | u.u_error = EFAULT; |
7b0cb7cb BJ |
799 | goto out; |
800 | } | |
728df0db SL |
801 | #ifdef MMAP |
802 | { register int fd; | |
803 | /* unmasp funky devices in the user's address space */ | |
804 | for (fd = 0; fd < u.u_lastfile; fd++) | |
805 | if (u.u_ofile[fd] && (u.u_pofile[fd] & UF_MAPPED)) | |
806 | munmapfd(fd); | |
807 | } | |
808 | #endif | |
4f083fd7 | 809 | itrunc(ip, (u_long)0); |
7b0cb7cb | 810 | u.u_acflag |= ACORE; |
dd012d1e SL |
811 | u.u_error = rdwri(UIO_WRITE, ip, |
812 | (caddr_t)&u, | |
813 | ctob(UPAGES), | |
8011f5df | 814 | (off_t)0, 1, (int *)0); |
1edb1cf8 | 815 | if (u.u_error == 0) |
a1edc12b | 816 | u.u_error = rdwri(UIO_WRITE, ip, |
e0fc9a90 | 817 | (caddr_t)ctob(dptov(u.u_procp, 0)), |
8011f5df MK |
818 | (int)ctob(u.u_dsize), |
819 | (off_t)ctob(UPAGES), 0, (int *)0); | |
1edb1cf8 | 820 | if (u.u_error == 0) |
a1edc12b | 821 | u.u_error = rdwri(UIO_WRITE, ip, |
e0fc9a90 | 822 | (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), |
8011f5df MK |
823 | (int)ctob(u.u_ssize), |
824 | (off_t)ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); | |
7b0cb7cb | 825 | out: |
687880f9 | 826 | iput(ip); |
7b0cb7cb | 827 | return (u.u_error == 0); |
687880f9 | 828 | } |