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