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