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