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