Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
8429d022 | 2 | * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. |
d86a61ec | 3 | * All rights reserved. |
da7c5cc6 | 4 | * |
dbf0c423 | 5 | * %sccs.include.redist.c% |
d86a61ec | 6 | * |
ea67b335 | 7 | * @(#)kern_sig.c 7.45 (Berkeley) %G% |
da7c5cc6 | 8 | */ |
961945a8 | 9 | |
8429d022 | 10 | #define SIGPROP /* include signal properties table */ |
94368568 | 11 | #include "param.h" |
35493b0f MK |
12 | #include "signalvar.h" |
13 | #include "resourcevar.h" | |
6bcdc4f3 | 14 | #include "namei.h" |
d86a61ec | 15 | #include "vnode.h" |
94368568 | 16 | #include "proc.h" |
8429d022 | 17 | #include "systm.h" |
94368568 JB |
18 | #include "timeb.h" |
19 | #include "times.h" | |
94368568 | 20 | #include "buf.h" |
94368568 | 21 | #include "acct.h" |
d86a61ec | 22 | #include "file.h" |
94368568 | 23 | #include "kernel.h" |
f4af9a5b | 24 | #include "wait.h" |
22585170 | 25 | #include "ktrace.h" |
687880f9 | 26 | |
8e6cd807 MK |
27 | #include "machine/cpu.h" |
28 | ||
35493b0f MK |
29 | #include "vm/vm.h" |
30 | #include "kinfo_proc.h" | |
31 | #include "user.h" /* for coredump */ | |
d301d150 | 32 | |
2e143991 | 33 | /* |
8429d022 | 34 | * Can process p, with pcred pc, send the signal signo to process q? |
2e143991 | 35 | */ |
8429d022 MK |
36 | #define CANSIGNAL(p, pc, q, signo) \ |
37 | ((pc)->pc_ucred->cr_uid == 0 || \ | |
38 | (pc)->p_ruid == (q)->p_cred->p_ruid || \ | |
39 | (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \ | |
40 | (pc)->p_ruid == (q)->p_ucred->cr_uid || \ | |
41 | (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \ | |
e635a749 MK |
42 | ((signo) == SIGCONT && (q)->p_session == (p)->p_session)) |
43 | ||
44 | /* ARGSUSED */ | |
45 | sigaction(p, uap, retval) | |
46 | struct proc *p; | |
47 | register struct args { | |
dd012d1e | 48 | int signo; |
f4af9a5b MK |
49 | struct sigaction *nsa; |
50 | struct sigaction *osa; | |
e635a749 MK |
51 | } *uap; |
52 | int *retval; | |
53 | { | |
f4af9a5b MK |
54 | struct sigaction vec; |
55 | register struct sigaction *sa; | |
8429d022 | 56 | register struct sigacts *ps = p->p_sigacts; |
dd012d1e | 57 | register int sig; |
f4af9a5b | 58 | int bit, error; |
dd012d1e SL |
59 | |
60 | sig = uap->signo; | |
f4af9a5b | 61 | if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) |
d9c2f47f | 62 | return (EINVAL); |
f4af9a5b MK |
63 | sa = &vec; |
64 | if (uap->osa) { | |
8429d022 MK |
65 | sa->sa_handler = ps->ps_sigact[sig]; |
66 | sa->sa_mask = ps->ps_catchmask[sig]; | |
fe7f81f4 | 67 | bit = sigmask(sig); |
f4af9a5b | 68 | sa->sa_flags = 0; |
8429d022 | 69 | if ((ps->ps_sigonstack & bit) != 0) |
f4af9a5b | 70 | sa->sa_flags |= SA_ONSTACK; |
8429d022 | 71 | if ((ps->ps_sigintr & bit) == 0) |
f4af9a5b | 72 | sa->sa_flags |= SA_RESTART; |
e635a749 | 73 | if (p->p_flag & SNOCLDSTOP) |
f4af9a5b MK |
74 | sa->sa_flags |= SA_NOCLDSTOP; |
75 | if (error = copyout((caddr_t)sa, (caddr_t)uap->osa, | |
76 | sizeof (vec))) | |
d9c2f47f | 77 | return (error); |
457aa395 | 78 | } |
f4af9a5b MK |
79 | if (uap->nsa) { |
80 | if (error = copyin((caddr_t)uap->nsa, (caddr_t)sa, | |
81 | sizeof (vec))) | |
d9c2f47f | 82 | return (error); |
e635a749 | 83 | setsigvec(p, sig, sa); |
457aa395 | 84 | } |
d9c2f47f | 85 | return (0); |
dd012d1e | 86 | } |
4147b3f6 | 87 | |
e635a749 MK |
88 | setsigvec(p, sig, sa) |
89 | register struct proc *p; | |
457aa395 | 90 | int sig; |
f4af9a5b | 91 | register struct sigaction *sa; |
dd012d1e | 92 | { |
8429d022 | 93 | register struct sigacts *ps = p->p_sigacts; |
457aa395 | 94 | register int bit; |
dd012d1e | 95 | |
feff6b5a | 96 | bit = sigmask(sig); |
dd012d1e SL |
97 | /* |
98 | * Change setting atomically. | |
99 | */ | |
feff6b5a | 100 | (void) splhigh(); |
8429d022 MK |
101 | ps->ps_sigact[sig] = sa->sa_handler; |
102 | ps->ps_catchmask[sig] = sa->sa_mask &~ sigcantmask; | |
f4af9a5b | 103 | if ((sa->sa_flags & SA_RESTART) == 0) |
8429d022 | 104 | ps->ps_sigintr |= bit; |
fe7f81f4 | 105 | else |
8429d022 | 106 | ps->ps_sigintr &= ~bit; |
f4af9a5b | 107 | if (sa->sa_flags & SA_ONSTACK) |
8429d022 | 108 | ps->ps_sigonstack |= bit; |
457aa395 | 109 | else |
8429d022 | 110 | ps->ps_sigonstack &= ~bit; |
0cbc4437 CT |
111 | #ifdef COMPAT_SUNOS |
112 | if (sa->sa_flags & SA_USERTRAMP) | |
113 | ps->ps_usertramp |= bit; | |
114 | else | |
115 | ps->ps_usertramp &= ~bit; | |
116 | #endif | |
f4af9a5b MK |
117 | if (sig == SIGCHLD) { |
118 | if (sa->sa_flags & SA_NOCLDSTOP) | |
119 | p->p_flag |= SNOCLDSTOP; | |
120 | else | |
121 | p->p_flag &= ~SNOCLDSTOP; | |
122 | } | |
123 | /* | |
124 | * Set bit in p_sigignore for signals that are set to SIG_IGN, | |
125 | * and for signals set to SIG_DFL where the default is to ignore. | |
126 | * However, don't put SIGCONT in p_sigignore, | |
127 | * as we have to restart the process. | |
128 | */ | |
129 | if (sa->sa_handler == SIG_IGN || | |
8429d022 | 130 | (sigprop[sig] & SA_IGNORE && sa->sa_handler == SIG_DFL)) { |
457aa395 | 131 | p->p_sig &= ~bit; /* never to be seen again */ |
f4af9a5b MK |
132 | if (sig != SIGCONT) |
133 | p->p_sigignore |= bit; /* easier in psignal */ | |
457aa395 | 134 | p->p_sigcatch &= ~bit; |
dd012d1e | 135 | } else { |
457aa395 | 136 | p->p_sigignore &= ~bit; |
f4af9a5b | 137 | if (sa->sa_handler == SIG_DFL) |
457aa395 | 138 | p->p_sigcatch &= ~bit; |
dd012d1e | 139 | else |
457aa395 | 140 | p->p_sigcatch |= bit; |
dd012d1e SL |
141 | } |
142 | (void) spl0(); | |
4147b3f6 BJ |
143 | } |
144 | ||
f4af9a5b MK |
145 | /* |
146 | * Initialize signal state for process 0; | |
147 | * set to ignore signals that are ignored by default. | |
148 | */ | |
8429d022 | 149 | void |
f4af9a5b MK |
150 | siginit(p) |
151 | struct proc *p; | |
152 | { | |
8429d022 | 153 | register int i; |
f4af9a5b | 154 | |
8429d022 MK |
155 | for (i = 0; i < NSIG; i++) |
156 | if (sigprop[i] & SA_IGNORE && i != SIGCONT) | |
157 | p->p_sigignore |= sigmask(i); | |
f4af9a5b MK |
158 | } |
159 | ||
160 | /* | |
161 | * Reset signals for an exec of the specified process. | |
162 | */ | |
8429d022 | 163 | void |
f4af9a5b MK |
164 | execsigs(p) |
165 | register struct proc *p; | |
166 | { | |
8429d022 | 167 | register struct sigacts *ps = p->p_sigacts; |
f4af9a5b MK |
168 | register int nc, mask; |
169 | ||
170 | /* | |
171 | * Reset caught signals. Held signals remain held | |
172 | * through p_sigmask (unless they were caught, | |
173 | * and are now ignored by default). | |
174 | */ | |
175 | while (p->p_sigcatch) { | |
176 | nc = ffs((long)p->p_sigcatch); | |
177 | mask = sigmask(nc); | |
178 | p->p_sigcatch &= ~mask; | |
8429d022 | 179 | if (sigprop[nc] & SA_IGNORE) { |
f4af9a5b MK |
180 | if (nc != SIGCONT) |
181 | p->p_sigignore |= mask; | |
182 | p->p_sig &= ~mask; | |
183 | } | |
8429d022 | 184 | ps->ps_sigact[nc] = SIG_DFL; |
f4af9a5b MK |
185 | } |
186 | /* | |
187 | * Reset stack state to the user stack. | |
188 | * Clear set of signals caught on the signal stack. | |
189 | */ | |
ebf08548 KM |
190 | ps->ps_sigstk.ss_flags = SA_DISABLE; |
191 | ps->ps_sigstk.ss_size = 0; | |
192 | ps->ps_sigstk.ss_base = 0; | |
193 | ps->ps_flags = 0; | |
f4af9a5b MK |
194 | } |
195 | ||
196 | /* | |
197 | * Manipulate signal mask. | |
198 | * Note that we receive new mask, not pointer, | |
199 | * and return old mask as return value; | |
200 | * the library stub does the rest. | |
201 | */ | |
e635a749 MK |
202 | sigprocmask(p, uap, retval) |
203 | register struct proc *p; | |
204 | struct args { | |
f4af9a5b MK |
205 | int how; |
206 | sigset_t mask; | |
e635a749 MK |
207 | } *uap; |
208 | int *retval; | |
209 | { | |
f4af9a5b MK |
210 | int error = 0; |
211 | ||
e635a749 | 212 | *retval = p->p_sigmask; |
f4af9a5b MK |
213 | (void) splhigh(); |
214 | ||
215 | switch (uap->how) { | |
216 | case SIG_BLOCK: | |
217 | p->p_sigmask |= uap->mask &~ sigcantmask; | |
218 | break; | |
219 | ||
220 | case SIG_UNBLOCK: | |
221 | p->p_sigmask &= ~uap->mask; | |
222 | break; | |
223 | ||
224 | case SIG_SETMASK: | |
225 | p->p_sigmask = uap->mask &~ sigcantmask; | |
226 | break; | |
227 | ||
228 | default: | |
229 | error = EINVAL; | |
230 | break; | |
231 | } | |
232 | (void) spl0(); | |
d9c2f47f | 233 | return (error); |
f4af9a5b MK |
234 | } |
235 | ||
e635a749 MK |
236 | /* ARGSUSED */ |
237 | sigpending(p, uap, retval) | |
238 | struct proc *p; | |
239 | void *uap; | |
240 | int *retval; | |
f4af9a5b MK |
241 | { |
242 | ||
e635a749 | 243 | *retval = p->p_sig; |
d9c2f47f | 244 | return (0); |
f4af9a5b MK |
245 | } |
246 | ||
0cbc4437 | 247 | #if defined(COMPAT_43) || defined(COMPAT_SUNOS) |
f4af9a5b MK |
248 | /* |
249 | * Generalized interface signal handler, 4.3-compatible. | |
250 | */ | |
e635a749 MK |
251 | /* ARGSUSED */ |
252 | osigvec(p, uap, retval) | |
253 | struct proc *p; | |
254 | register struct args { | |
f4af9a5b MK |
255 | int signo; |
256 | struct sigvec *nsv; | |
257 | struct sigvec *osv; | |
e635a749 MK |
258 | } *uap; |
259 | int *retval; | |
260 | { | |
f4af9a5b | 261 | struct sigvec vec; |
8429d022 | 262 | register struct sigacts *ps = p->p_sigacts; |
f4af9a5b MK |
263 | register struct sigvec *sv; |
264 | register int sig; | |
265 | int bit, error; | |
266 | ||
267 | sig = uap->signo; | |
268 | if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) | |
d9c2f47f | 269 | return (EINVAL); |
f4af9a5b MK |
270 | sv = &vec; |
271 | if (uap->osv) { | |
8429d022 MK |
272 | *(sig_t *)&sv->sv_handler = ps->ps_sigact[sig]; |
273 | sv->sv_mask = ps->ps_catchmask[sig]; | |
f4af9a5b MK |
274 | bit = sigmask(sig); |
275 | sv->sv_flags = 0; | |
8429d022 | 276 | if ((ps->ps_sigonstack & bit) != 0) |
f4af9a5b | 277 | sv->sv_flags |= SV_ONSTACK; |
8429d022 | 278 | if ((ps->ps_sigintr & bit) != 0) |
f4af9a5b | 279 | sv->sv_flags |= SV_INTERRUPT; |
0cbc4437 | 280 | #ifndef COMPAT_SUNOS |
e635a749 | 281 | if (p->p_flag & SNOCLDSTOP) |
f4af9a5b | 282 | sv->sv_flags |= SA_NOCLDSTOP; |
0cbc4437 | 283 | #endif |
f4af9a5b MK |
284 | if (error = copyout((caddr_t)sv, (caddr_t)uap->osv, |
285 | sizeof (vec))) | |
d9c2f47f | 286 | return (error); |
f4af9a5b MK |
287 | } |
288 | if (uap->nsv) { | |
289 | if (error = copyin((caddr_t)uap->nsv, (caddr_t)sv, | |
290 | sizeof (vec))) | |
d9c2f47f | 291 | return (error); |
0cbc4437 CT |
292 | #ifdef COMPAT_SUNOS |
293 | /* | |
294 | * SunOS uses this bit (SA_NOCLDSTOP) as SV_RESETHAND, | |
295 | * `reset to SIG_DFL on delivery'. We have no such | |
296 | * option now or ever! | |
297 | */ | |
298 | if (sv->sv_flags & SA_NOCLDSTOP) | |
299 | return (EINVAL); | |
300 | sv->sv_flags |= SA_USERTRAMP; | |
301 | #endif | |
f4af9a5b | 302 | sv->sv_flags ^= SA_RESTART; /* opposite of SV_INTERRUPT */ |
e635a749 | 303 | setsigvec(p, sig, (struct sigaction *)sv); |
f4af9a5b | 304 | } |
d9c2f47f | 305 | return (0); |
f4af9a5b MK |
306 | } |
307 | ||
e635a749 MK |
308 | osigblock(p, uap, retval) |
309 | register struct proc *p; | |
310 | struct args { | |
feff6b5a | 311 | int mask; |
e635a749 MK |
312 | } *uap; |
313 | int *retval; | |
314 | { | |
4147b3f6 | 315 | |
feff6b5a | 316 | (void) splhigh(); |
e635a749 | 317 | *retval = p->p_sigmask; |
f4af9a5b | 318 | p->p_sigmask |= uap->mask &~ sigcantmask; |
dd012d1e | 319 | (void) spl0(); |
d9c2f47f | 320 | return (0); |
4147b3f6 BJ |
321 | } |
322 | ||
e635a749 MK |
323 | osigsetmask(p, uap, retval) |
324 | struct proc *p; | |
325 | struct args { | |
feff6b5a | 326 | int mask; |
e635a749 MK |
327 | } *uap; |
328 | int *retval; | |
329 | { | |
687880f9 | 330 | |
feff6b5a | 331 | (void) splhigh(); |
e635a749 | 332 | *retval = p->p_sigmask; |
f4af9a5b | 333 | p->p_sigmask = uap->mask &~ sigcantmask; |
dd012d1e | 334 | (void) spl0(); |
d9c2f47f | 335 | return (0); |
687880f9 | 336 | } |
f4af9a5b | 337 | #endif |
687880f9 | 338 | |
f4af9a5b MK |
339 | /* |
340 | * Suspend process until signal, providing mask to be set | |
341 | * in the meantime. Note nonstandard calling convention: | |
342 | * libc stub passes mask, not pointer, to save a copyin. | |
343 | */ | |
e635a749 MK |
344 | /* ARGSUSED */ |
345 | sigsuspend(p, uap, retval) | |
346 | register struct proc *p; | |
347 | struct args { | |
f4af9a5b | 348 | sigset_t mask; |
e635a749 MK |
349 | } *uap; |
350 | int *retval; | |
351 | { | |
8429d022 | 352 | register struct sigacts *ps = p->p_sigacts; |
4147b3f6 | 353 | |
dd012d1e SL |
354 | /* |
355 | * When returning from sigpause, we want | |
356 | * the old mask to be restored after the | |
357 | * signal handler has finished. Thus, we | |
5077c7b9 MK |
358 | * save it here and mark the sigacts structure |
359 | * to indicate this. | |
dd012d1e | 360 | */ |
8429d022 | 361 | ps->ps_oldmask = p->p_sigmask; |
ebf08548 | 362 | ps->ps_flags |= SAS_OLDMASK; |
f4af9a5b | 363 | p->p_sigmask = uap->mask &~ sigcantmask; |
8429d022 | 364 | (void) tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0); |
22585170 | 365 | /* always return EINTR rather than ERESTART... */ |
d9c2f47f | 366 | return (EINTR); |
4147b3f6 BJ |
367 | } |
368 | ||
ebf08548 | 369 | #ifdef COMPAT_43 |
e635a749 | 370 | /* ARGSUSED */ |
ebf08548 | 371 | osigstack(p, uap, retval) |
e635a749 MK |
372 | struct proc *p; |
373 | register struct args { | |
457aa395 SL |
374 | struct sigstack *nss; |
375 | struct sigstack *oss; | |
e635a749 MK |
376 | } *uap; |
377 | int *retval; | |
378 | { | |
457aa395 | 379 | struct sigstack ss; |
ebf08548 | 380 | struct sigacts *psp; |
f4af9a5b MK |
381 | int error = 0; |
382 | ||
ebf08548 KM |
383 | psp = p->p_sigacts; |
384 | ss.ss_sp = psp->ps_sigstk.ss_base; | |
385 | ss.ss_onstack = psp->ps_sigstk.ss_flags & SA_ONSTACK; | |
386 | if (uap->oss && (error = copyout((caddr_t)&ss, (caddr_t)uap->oss, | |
387 | sizeof (struct sigstack)))) | |
d9c2f47f | 388 | return (error); |
f4af9a5b | 389 | if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, |
ebf08548 KM |
390 | sizeof (ss))) == 0) { |
391 | psp->ps_sigstk.ss_base = ss.ss_sp; | |
392 | psp->ps_sigstk.ss_size = 0; | |
393 | psp->ps_sigstk.ss_flags |= ss.ss_onstack & SA_ONSTACK; | |
394 | psp->ps_flags |= SAS_ALTSTACK; | |
395 | } | |
d9c2f47f | 396 | return (error); |
4147b3f6 | 397 | } |
ebf08548 KM |
398 | #endif /* COMPAT_43 */ |
399 | ||
400 | /* ARGSUSED */ | |
401 | sigaltstack(p, uap, retval) | |
402 | struct proc *p; | |
403 | register struct args { | |
404 | struct sigaltstack *nss; | |
405 | struct sigaltstack *oss; | |
406 | } *uap; | |
407 | int *retval; | |
408 | { | |
409 | struct sigacts *psp; | |
410 | struct sigaltstack ss; | |
411 | int error; | |
412 | ||
413 | psp = p->p_sigacts; | |
414 | if ((psp->ps_flags & SAS_ALTSTACK) == 0) | |
415 | psp->ps_sigstk.ss_flags |= SA_DISABLE; | |
416 | if (uap->oss && (error = copyout((caddr_t)&psp->ps_sigstk, | |
417 | (caddr_t)uap->oss, sizeof (struct sigaltstack)))) | |
418 | return (error); | |
419 | if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, | |
420 | sizeof (ss)))) | |
421 | return (error); | |
422 | if (ss.ss_flags & SA_DISABLE) { | |
423 | if (psp->ps_sigstk.ss_flags & SA_ONSTACK) | |
424 | return (EINVAL); | |
425 | psp->ps_flags &= ~SAS_ALTSTACK; | |
426 | psp->ps_sigstk.ss_flags = ss.ss_flags; | |
427 | return (0); | |
428 | } | |
429 | if (ss.ss_size < MINSIGSTKSZ) | |
430 | return (ENOMEM); | |
431 | psp->ps_flags |= SAS_ALTSTACK; | |
432 | psp->ps_sigstk= ss; | |
433 | return (0); | |
434 | } | |
4147b3f6 | 435 | |
e635a749 MK |
436 | /* ARGSUSED */ |
437 | kill(cp, uap, retval) | |
438 | register struct proc *cp; | |
439 | register struct args { | |
dd012d1e SL |
440 | int pid; |
441 | int signo; | |
e635a749 MK |
442 | } *uap; |
443 | int *retval; | |
444 | { | |
7713be67 | 445 | register struct proc *p; |
8429d022 | 446 | register struct pcred *pc = cp->p_cred; |
1e3738da | 447 | |
f4af9a5b | 448 | if ((unsigned) uap->signo >= NSIG) |
d9c2f47f | 449 | return (EINVAL); |
7713be67 KM |
450 | if (uap->pid > 0) { |
451 | /* kill single process */ | |
452 | p = pfind(uap->pid); | |
f4af9a5b | 453 | if (p == 0) |
d9c2f47f | 454 | return (ESRCH); |
8429d022 | 455 | if (!CANSIGNAL(cp, pc, p, uap->signo)) |
d9c2f47f | 456 | return (EPERM); |
f4af9a5b | 457 | if (uap->signo) |
7713be67 | 458 | psignal(p, uap->signo); |
d9c2f47f | 459 | return (0); |
7713be67 KM |
460 | } |
461 | switch (uap->pid) { | |
462 | case -1: /* broadcast signal */ | |
d9c2f47f | 463 | return (killpg1(cp, uap->signo, 0, 1)); |
7713be67 | 464 | case 0: /* signal own process group */ |
d9c2f47f | 465 | return (killpg1(cp, uap->signo, 0, 0)); |
7713be67 | 466 | default: /* negative explicit process group */ |
d9c2f47f | 467 | return (killpg1(cp, uap->signo, -uap->pid, 0)); |
7713be67 | 468 | } |
f4af9a5b | 469 | /* NOTREACHED */ |
1e3738da BJ |
470 | } |
471 | ||
0cbc4437 | 472 | #if defined(COMPAT_43) || defined(COMPAT_SUNOS) |
e635a749 MK |
473 | /* ARGSUSED */ |
474 | okillpg(p, uap, retval) | |
475 | struct proc *p; | |
476 | register struct args { | |
8fe87cbb | 477 | int pgid; |
3b4f6e10 | 478 | int signo; |
e635a749 MK |
479 | } *uap; |
480 | int *retval; | |
481 | { | |
1e3738da | 482 | |
f4af9a5b | 483 | if ((unsigned) uap->signo >= NSIG) |
d9c2f47f MK |
484 | return (EINVAL); |
485 | return (killpg1(p, uap->signo, uap->pgid, 0)); | |
1e3738da | 486 | } |
f4af9a5b | 487 | #endif |
dd012d1e | 488 | |
e635a749 MK |
489 | /* |
490 | * Common code for kill process group/broadcast kill. | |
491 | * cp is calling process. | |
492 | */ | |
493 | killpg1(cp, signo, pgid, all) | |
494 | register struct proc *cp; | |
8fe87cbb | 495 | int signo, pgid, all; |
3b4f6e10 SL |
496 | { |
497 | register struct proc *p; | |
8429d022 | 498 | register struct pcred *pc = cp->p_cred; |
8fe87cbb | 499 | struct pgrp *pgrp; |
8429d022 | 500 | int nfound = 0; |
8fe87cbb MT |
501 | |
502 | if (all) | |
503 | /* | |
504 | * broadcast | |
687880f9 | 505 | */ |
8fe87cbb | 506 | for (p = allproc; p != NULL; p = p->p_nxt) { |
8429d022 MK |
507 | if (p->p_pid <= 1 || p->p_flag&SSYS || |
508 | p == cp || !CANSIGNAL(cp, pc, p, signo)) | |
8fe87cbb | 509 | continue; |
8429d022 | 510 | nfound++; |
8fe87cbb MT |
511 | if (signo) |
512 | psignal(p, signo); | |
513 | } | |
514 | else { | |
515 | if (pgid == 0) | |
516 | /* | |
517 | * zero pgid means send to my process group. | |
518 | */ | |
8429d022 | 519 | pgrp = cp->p_pgrp; |
8fe87cbb MT |
520 | else { |
521 | pgrp = pgfind(pgid); | |
522 | if (pgrp == NULL) | |
f4af9a5b | 523 | return (ESRCH); |
8fe87cbb | 524 | } |
8fe87cbb | 525 | for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) { |
8429d022 | 526 | if (p->p_pid <= 1 || p->p_flag&SSYS || |
e3448cc4 | 527 | p->p_stat == SZOMB || !CANSIGNAL(cp, pc, p, signo)) |
8fe87cbb | 528 | continue; |
8429d022 | 529 | nfound++; |
8fe87cbb MT |
530 | if (signo) |
531 | psignal(p, signo); | |
7713be67 | 532 | } |
687880f9 | 533 | } |
8429d022 | 534 | return (nfound ? 0 : ESRCH); |
4147b3f6 | 535 | } |
687880f9 | 536 | |
e635a749 | 537 | /* |
687880f9 | 538 | * Send the specified signal to |
8fe87cbb | 539 | * all processes with 'pgid' as |
687880f9 | 540 | * process group. |
687880f9 | 541 | */ |
8429d022 | 542 | void |
8fe87cbb | 543 | gsignal(pgid, sig) |
8429d022 | 544 | int pgid, sig; |
8fe87cbb | 545 | { |
f4af9a5b | 546 | struct pgrp *pgrp; |
8fe87cbb | 547 | |
f4af9a5b | 548 | if (pgid && (pgrp = pgfind(pgid))) |
c697d0b9 | 549 | pgsignal(pgrp, sig, 0); |
8fe87cbb | 550 | } |
e635a749 | 551 | |
22585170 | 552 | /* |
c697d0b9 MT |
553 | * Send sig to every member of a process group. |
554 | * If checktty is 1, limit to members which have a controlling | |
555 | * terminal. | |
22585170 | 556 | */ |
8429d022 | 557 | void |
c697d0b9 | 558 | pgsignal(pgrp, sig, checkctty) |
f4af9a5b | 559 | struct pgrp *pgrp; |
8429d022 | 560 | int sig, checkctty; |
687880f9 BJ |
561 | { |
562 | register struct proc *p; | |
563 | ||
22585170 MT |
564 | if (pgrp) |
565 | for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) | |
c697d0b9 MT |
566 | if (checkctty == 0 || p->p_flag&SCTTY) |
567 | psignal(p, sig); | |
f4af9a5b MK |
568 | } |
569 | ||
570 | /* | |
571 | * Send a signal caused by a trap to the current process. | |
572 | * If it will be caught immediately, deliver it with correct code. | |
573 | * Otherwise, post it normally. | |
574 | */ | |
8429d022 MK |
575 | void |
576 | trapsignal(p, sig, code) | |
577 | struct proc *p; | |
f4af9a5b MK |
578 | register int sig; |
579 | unsigned code; | |
580 | { | |
8429d022 | 581 | register struct sigacts *ps = p->p_sigacts; |
f4af9a5b MK |
582 | int mask; |
583 | ||
584 | mask = sigmask(sig); | |
585 | if ((p->p_flag & STRC) == 0 && (p->p_sigcatch & mask) != 0 && | |
586 | (p->p_sigmask & mask) == 0) { | |
8429d022 | 587 | p->p_stats->p_ru.ru_nsignals++; |
22585170 MT |
588 | #ifdef KTRACE |
589 | if (KTRPOINT(p, KTR_PSIG)) | |
8429d022 | 590 | ktrpsig(p->p_tracep, sig, ps->ps_sigact[sig], |
22585170 MT |
591 | p->p_sigmask, code); |
592 | #endif | |
8429d022 | 593 | sendsig(ps->ps_sigact[sig], sig, p->p_sigmask, code); |
8429d022 | 594 | p->p_sigmask |= ps->ps_catchmask[sig] | mask; |
f4af9a5b | 595 | } else { |
8429d022 | 596 | ps->ps_code = code; /* XXX for core dump/debugger */ |
8fe87cbb | 597 | psignal(p, sig); |
f4af9a5b | 598 | } |
687880f9 BJ |
599 | } |
600 | ||
601 | /* | |
22585170 | 602 | * Send the specified signal to the specified process. |
8429d022 MK |
603 | * If the signal has an action, the action is usually performed |
604 | * by the target process rather than the caller; we simply add | |
605 | * the signal to the set of pending signals for the process. | |
22585170 MT |
606 | * Exceptions: |
607 | * o When a stop signal is sent to a sleeping process that takes the default | |
608 | * action, the process is stopped without awakening it. | |
609 | * o SIGCONT restarts stopped processes (or puts them back to sleep) | |
610 | * regardless of the signal action (eg, blocked or ignored). | |
611 | * Other ignored signals are discarded immediately. | |
687880f9 | 612 | */ |
8429d022 | 613 | void |
687880f9 BJ |
614 | psignal(p, sig) |
615 | register struct proc *p; | |
616 | register int sig; | |
617 | { | |
8429d022 | 618 | register int s, prop; |
f4af9a5b | 619 | register sig_t action; |
feff6b5a | 620 | int mask; |
687880f9 | 621 | |
f4af9a5b MK |
622 | if ((unsigned)sig >= NSIG || sig == 0) |
623 | panic("psignal sig"); | |
feff6b5a | 624 | mask = sigmask(sig); |
8429d022 | 625 | prop = sigprop[sig]; |
687880f9 BJ |
626 | |
627 | /* | |
628 | * If proc is traced, always give parent a chance. | |
687880f9 BJ |
629 | */ |
630 | if (p->p_flag & STRC) | |
631 | action = SIG_DFL; | |
632 | else { | |
687880f9 | 633 | /* |
dd012d1e SL |
634 | * If the signal is being ignored, |
635 | * then we forget about it immediately. | |
f4af9a5b MK |
636 | * (Note: we don't set SIGCONT in p_sigignore, |
637 | * and if it is set to SIG_IGN, | |
638 | * action will be SIG_DFL here.) | |
687880f9 | 639 | */ |
feff6b5a | 640 | if (p->p_sigignore & mask) |
687880f9 | 641 | return; |
feff6b5a | 642 | if (p->p_sigmask & mask) |
dd012d1e | 643 | action = SIG_HOLD; |
feff6b5a | 644 | else if (p->p_sigcatch & mask) |
dd012d1e | 645 | action = SIG_CATCH; |
e51c8e4a | 646 | else |
dd012d1e | 647 | action = SIG_DFL; |
687880f9 | 648 | } |
687880f9 | 649 | |
8429d022 MK |
650 | if (p->p_nice > NZERO && (sig == SIGKILL || |
651 | sig == SIGTERM && (p->p_flag&STRC || action != SIG_DFL))) | |
652 | p->p_nice = NZERO; | |
687880f9 | 653 | |
8429d022 | 654 | if (prop & SA_CONT) |
f4af9a5b | 655 | p->p_sig &= ~stopsigmask; |
f4af9a5b | 656 | |
8429d022 | 657 | if (prop & SA_STOP) { |
faf9c963 MK |
658 | /* |
659 | * If sending a tty stop signal to a member of an orphaned | |
660 | * process group, discard the signal here if the action | |
661 | * is default; don't stop the process below if sleeping, | |
662 | * and don't clear any pending SIGCONT. | |
663 | */ | |
8429d022 MK |
664 | if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 && |
665 | action == SIG_DFL) | |
9db58063 | 666 | return; |
8429d022 | 667 | p->p_sig &= ~contsigmask; |
687880f9 | 668 | } |
f4af9a5b MK |
669 | p->p_sig |= mask; |
670 | ||
687880f9 | 671 | /* |
f4af9a5b MK |
672 | * Defer further processing for signals which are held, |
673 | * except that stopped processes must be continued by SIGCONT. | |
687880f9 | 674 | */ |
8429d022 | 675 | if (action == SIG_HOLD && ((prop & SA_CONT) == 0 || p->p_stat != SSTOP)) |
687880f9 | 676 | return; |
feff6b5a | 677 | s = splhigh(); |
687880f9 BJ |
678 | switch (p->p_stat) { |
679 | ||
680 | case SSLEEP: | |
681 | /* | |
22585170 | 682 | * If process is sleeping uninterruptibly |
687880f9 BJ |
683 | * we can't interrupt the sleep... the signal will |
684 | * be noticed when the process returns through | |
685 | * trap() or syscall(). | |
686 | */ | |
22585170 | 687 | if ((p->p_flag & SSINTR) == 0) |
687880f9 BJ |
688 | goto out; |
689 | /* | |
690 | * Process is sleeping and traced... make it runnable | |
691 | * so it can discover the signal in issig() and stop | |
692 | * for the parent. | |
693 | */ | |
694 | if (p->p_flag&STRC) | |
695 | goto run; | |
f4af9a5b MK |
696 | /* |
697 | * When a sleeping process receives a stop | |
698 | * signal, process immediately if possible. | |
699 | * All other (caught or default) signals | |
700 | * cause the process to run. | |
701 | */ | |
8429d022 | 702 | if (prop & SA_STOP) { |
687880f9 | 703 | if (action != SIG_DFL) |
f4af9a5b | 704 | goto runfast; |
687880f9 | 705 | /* |
8429d022 MK |
706 | * If a child holding parent blocked, |
707 | * stopping could cause deadlock. | |
687880f9 | 708 | */ |
8429d022 | 709 | if (p->p_flag&SPPWAIT) |
687880f9 | 710 | goto out; |
feff6b5a | 711 | p->p_sig &= ~mask; |
19dec745 | 712 | p->p_xstat = sig; |
f4af9a5b MK |
713 | if ((p->p_pptr->p_flag & SNOCLDSTOP) == 0) |
714 | psignal(p->p_pptr, SIGCHLD); | |
687880f9 BJ |
715 | stop(p); |
716 | goto out; | |
f4af9a5b MK |
717 | } else |
718 | goto runfast; | |
687880f9 BJ |
719 | /*NOTREACHED*/ |
720 | ||
721 | case SSTOP: | |
722 | /* | |
723 | * If traced process is already stopped, | |
724 | * then no further action is necessary. | |
725 | */ | |
726 | if (p->p_flag&STRC) | |
727 | goto out; | |
687880f9 | 728 | |
8429d022 MK |
729 | /* |
730 | * Kill signal always sets processes running. | |
731 | */ | |
732 | if (sig == SIGKILL) | |
f4af9a5b | 733 | goto runfast; |
687880f9 | 734 | |
8429d022 | 735 | if (prop & SA_CONT) { |
687880f9 | 736 | /* |
f4af9a5b MK |
737 | * If SIGCONT is default (or ignored), we continue |
738 | * the process but don't leave the signal in p_sig, | |
739 | * as it has no further action. If SIGCONT is held, | |
740 | * continue the process and leave the signal in p_sig. | |
687880f9 BJ |
741 | * If the process catches SIGCONT, let it handle |
742 | * the signal itself. If it isn't waiting on | |
743 | * an event, then it goes back to run state. | |
744 | * Otherwise, process goes back to sleep state. | |
745 | */ | |
f4af9a5b MK |
746 | if (action == SIG_DFL) |
747 | p->p_sig &= ~mask; | |
748 | if (action == SIG_CATCH) | |
749 | goto runfast; | |
750 | if (p->p_wchan == 0) | |
687880f9 BJ |
751 | goto run; |
752 | p->p_stat = SSLEEP; | |
753 | goto out; | |
8429d022 | 754 | } |
687880f9 | 755 | |
8429d022 | 756 | if (prop & SA_STOP) { |
687880f9 BJ |
757 | /* |
758 | * Already stopped, don't need to stop again. | |
759 | * (If we did the shell could get confused.) | |
760 | */ | |
feff6b5a | 761 | p->p_sig &= ~mask; /* take it away */ |
687880f9 | 762 | goto out; |
687880f9 | 763 | } |
8429d022 MK |
764 | |
765 | /* | |
766 | * If process is sleeping interruptibly, then | |
767 | * simulate a wakeup so that when it is continued, | |
768 | * it will be made runnable and can look at the signal. | |
769 | * But don't setrun the process, leave it stopped. | |
770 | */ | |
771 | if (p->p_wchan && p->p_flag & SSINTR) | |
772 | unsleep(p); | |
773 | goto out; | |
687880f9 BJ |
774 | |
775 | default: | |
776 | /* | |
777 | * SRUN, SIDL, SZOMB do nothing with the signal, | |
778 | * other than kicking ourselves if we are running. | |
779 | * It will either never be noticed, or noticed very soon. | |
780 | */ | |
35493b0f | 781 | if (p == curproc) |
8e6cd807 | 782 | signotify(p); |
687880f9 BJ |
783 | goto out; |
784 | } | |
785 | /*NOTREACHED*/ | |
f4af9a5b MK |
786 | |
787 | runfast: | |
687880f9 BJ |
788 | /* |
789 | * Raise priority to at least PUSER. | |
790 | */ | |
791 | if (p->p_pri > PUSER) | |
e4f89871 | 792 | p->p_pri = PUSER; |
f4af9a5b | 793 | run: |
687880f9 BJ |
794 | setrun(p); |
795 | out: | |
796 | splx(s); | |
797 | } | |
798 | ||
799 | /* | |
22585170 MT |
800 | * If the current process has a signal to process (should be caught |
801 | * or cause termination, should interrupt current syscall), | |
802 | * return the signal number. Stop signals with default action | |
803 | * are processed immediately, then cleared; they aren't returned. | |
8429d022 MK |
804 | * This is checked after each entry to the system for a syscall |
805 | * or trap (though this can usually be done without actually calling | |
806 | * issig by checking the pending signal masks in the CURSIG macro.) | |
807 | * The normal call sequence is | |
808 | * | |
809 | * while (sig = CURSIG(curproc)) | |
810 | * psig(sig); | |
687880f9 | 811 | */ |
8429d022 MK |
812 | issig(p) |
813 | register struct proc *p; | |
687880f9 | 814 | { |
8429d022 | 815 | register int sig, mask, prop; |
687880f9 | 816 | |
687880f9 | 817 | for (;;) { |
f4af9a5b | 818 | mask = p->p_sig &~ p->p_sigmask; |
8429d022 | 819 | if (p->p_flag&SPPWAIT) |
f4af9a5b | 820 | mask &= ~stopsigmask; |
22585170 MT |
821 | if (mask == 0) /* no signal to send */ |
822 | return (0); | |
f4af9a5b | 823 | sig = ffs((long)mask); |
feff6b5a | 824 | mask = sigmask(sig); |
8429d022 | 825 | prop = sigprop[sig]; |
22585170 MT |
826 | /* |
827 | * We should see pending but ignored signals | |
828 | * only if STRC was on when they were posted. | |
829 | */ | |
830 | if (mask & p->p_sigignore && (p->p_flag&STRC) == 0) { | |
831 | p->p_sig &= ~mask; | |
832 | continue; | |
833 | } | |
8429d022 | 834 | if (p->p_flag&STRC && (p->p_flag&SPPWAIT) == 0) { |
687880f9 BJ |
835 | /* |
836 | * If traced, always stop, and stay | |
837 | * stopped until released by the parent. | |
838 | */ | |
19dec745 | 839 | p->p_xstat = sig; |
ad6c75cb | 840 | psignal(p->p_pptr, SIGCHLD); |
687880f9 BJ |
841 | do { |
842 | stop(p); | |
843 | swtch(); | |
1bfd8b20 | 844 | } while (!procxmt(p) && p->p_flag&STRC); |
687880f9 BJ |
845 | |
846 | /* | |
f99e4a3a | 847 | * If the traced bit got turned off, |
22585170 | 848 | * go back up to the top to rescan signals. |
35493b0f MK |
849 | * This ensures that p_sig* and ps_sigact |
850 | * are consistent. | |
687880f9 | 851 | */ |
22585170 | 852 | if ((p->p_flag&STRC) == 0) |
687880f9 | 853 | continue; |
687880f9 BJ |
854 | |
855 | /* | |
856 | * If parent wants us to take the signal, | |
19dec745 | 857 | * then it will leave it in p->p_xstat; |
687880f9 BJ |
858 | * otherwise we just look for signals again. |
859 | */ | |
22585170 | 860 | p->p_sig &= ~mask; /* clear the old signal */ |
19dec745 | 861 | sig = p->p_xstat; |
687880f9 BJ |
862 | if (sig == 0) |
863 | continue; | |
f99e4a3a SL |
864 | |
865 | /* | |
22585170 MT |
866 | * Put the new signal into p_sig. |
867 | * If signal is being masked, | |
868 | * look for other signals. | |
f99e4a3a | 869 | */ |
feff6b5a | 870 | mask = sigmask(sig); |
22585170 MT |
871 | p->p_sig |= mask; |
872 | if (p->p_sigmask & mask) | |
f99e4a3a | 873 | continue; |
687880f9 | 874 | } |
22585170 MT |
875 | |
876 | /* | |
877 | * Decide whether the signal should be returned. | |
878 | * Return the signal's number, or fall through | |
879 | * to clear it from the pending mask. | |
880 | */ | |
8429d022 | 881 | switch ((int)p->p_sigacts->ps_sigact[sig]) { |
687880f9 BJ |
882 | |
883 | case SIG_DFL: | |
884 | /* | |
885 | * Don't take default actions on system processes. | |
886 | */ | |
fc080d8d RC |
887 | if (p->p_pid <= 1) { |
888 | #ifdef DIAGNOSTIC | |
889 | /* | |
890 | * Are you sure you want to ignore SIGSEGV | |
891 | * in init? XXX | |
892 | */ | |
893 | printf("Process (pid %d) got signal %d\n", | |
894 | p->p_pid, sig); | |
895 | #endif | |
22585170 | 896 | break; /* == ignore */ |
fc080d8d | 897 | } |
22585170 MT |
898 | /* |
899 | * If there is a pending stop signal to process | |
900 | * with default action, stop here, | |
e51c8e4a MK |
901 | * then clear the signal. However, |
902 | * if process is member of an orphaned | |
903 | * process group, ignore tty stop signals. | |
22585170 | 904 | */ |
8429d022 | 905 | if (prop & SA_STOP) { |
e51c8e4a MK |
906 | if (p->p_flag&STRC || |
907 | (p->p_pgrp->pg_jobc == 0 && | |
8429d022 | 908 | prop & SA_TTYSTOP)) |
22585170 | 909 | break; /* == ignore */ |
19dec745 | 910 | p->p_xstat = sig; |
687880f9 | 911 | stop(p); |
f4af9a5b MK |
912 | if ((p->p_pptr->p_flag & SNOCLDSTOP) == 0) |
913 | psignal(p->p_pptr, SIGCHLD); | |
687880f9 | 914 | swtch(); |
22585170 | 915 | break; |
8429d022 | 916 | } else if (prop & SA_IGNORE) { |
687880f9 | 917 | /* |
f4af9a5b MK |
918 | * Except for SIGCONT, shouldn't get here. |
919 | * Default action is to ignore; drop it. | |
687880f9 | 920 | */ |
22585170 | 921 | break; /* == ignore */ |
f4af9a5b | 922 | } else |
22585170 | 923 | return (sig); |
687880f9 BJ |
924 | /*NOTREACHED*/ |
925 | ||
687880f9 BJ |
926 | case SIG_IGN: |
927 | /* | |
f4af9a5b MK |
928 | * Masking above should prevent us ever trying |
929 | * to take action on an ignored signal other | |
930 | * than SIGCONT, unless process is traced. | |
687880f9 | 931 | */ |
8429d022 | 932 | if ((prop & SA_CONT) == 0 && (p->p_flag&STRC) == 0) |
687880f9 | 933 | printf("issig\n"); |
22585170 | 934 | break; /* == ignore */ |
687880f9 BJ |
935 | |
936 | default: | |
937 | /* | |
938 | * This signal has an action, let | |
939 | * psig process it. | |
940 | */ | |
22585170 | 941 | return (sig); |
687880f9 | 942 | } |
22585170 | 943 | p->p_sig &= ~mask; /* take the signal! */ |
687880f9 | 944 | } |
22585170 | 945 | /* NOTREACHED */ |
687880f9 BJ |
946 | } |
947 | ||
687880f9 BJ |
948 | /* |
949 | * Put the argument process into the stopped | |
ad6c75cb MK |
950 | * state and notify the parent via wakeup. |
951 | * Signals are handled elsewhere. | |
22585170 | 952 | * The process must not be on the run queue. |
687880f9 BJ |
953 | */ |
954 | stop(p) | |
955 | register struct proc *p; | |
956 | { | |
957 | ||
958 | p->p_stat = SSTOP; | |
959 | p->p_flag &= ~SWTED; | |
960 | wakeup((caddr_t)p->p_pptr); | |
687880f9 BJ |
961 | } |
962 | ||
963 | /* | |
8429d022 MK |
964 | * Take the action for the specified signal |
965 | * from the current set of pending signals. | |
687880f9 | 966 | */ |
8429d022 | 967 | void |
22585170 MT |
968 | psig(sig) |
969 | register int sig; | |
687880f9 | 970 | { |
8429d022 MK |
971 | register struct proc *p = curproc; |
972 | register struct sigacts *ps = p->p_sigacts; | |
f4af9a5b | 973 | register sig_t action; |
8429d022 | 974 | int mask, returnmask; |
f4af9a5b | 975 | |
22585170 | 976 | #ifdef DIAGNOSTIC |
8429d022 MK |
977 | if (sig == 0) |
978 | panic("psig"); | |
22585170 | 979 | #endif |
8429d022 MK |
980 | mask = sigmask(sig); |
981 | p->p_sig &= ~mask; | |
982 | action = ps->ps_sigact[sig]; | |
22585170 | 983 | #ifdef KTRACE |
8429d022 | 984 | if (KTRPOINT(p, KTR_PSIG)) |
ebf08548 | 985 | ktrpsig(p->p_tracep, sig, action, ps->ps_flags & SAS_OLDMASK ? |
8429d022 | 986 | ps->ps_oldmask : p->p_sigmask, 0); |
22585170 | 987 | #endif |
8429d022 MK |
988 | if (action == SIG_DFL) { |
989 | /* | |
990 | * Default action, where the default is to kill | |
991 | * the process. (Other cases were ignored above.) | |
8429d022 | 992 | */ |
35493b0f | 993 | sigexit(p, sig); |
8429d022 MK |
994 | /* NOTREACHED */ |
995 | } else { | |
996 | /* | |
997 | * If we get here, the signal must be caught. | |
998 | */ | |
f4af9a5b | 999 | #ifdef DIAGNOSTIC |
8429d022 MK |
1000 | if (action == SIG_IGN || (p->p_sigmask & mask)) |
1001 | panic("psig action"); | |
f4af9a5b | 1002 | #endif |
8429d022 MK |
1003 | /* |
1004 | * Set the new mask value and also defer further | |
1005 | * occurences of this signal. | |
1006 | * | |
1007 | * Special case: user has done a sigpause. Here the | |
1008 | * current mask is not of interest, but rather the | |
1009 | * mask from before the sigpause is what we want | |
1010 | * restored after the signal processing is completed. | |
1011 | */ | |
1012 | (void) splhigh(); | |
ebf08548 | 1013 | if (ps->ps_flags & SAS_OLDMASK) { |
8429d022 | 1014 | returnmask = ps->ps_oldmask; |
ebf08548 | 1015 | ps->ps_flags &= ~SAS_OLDMASK; |
8429d022 MK |
1016 | } else |
1017 | returnmask = p->p_sigmask; | |
1018 | p->p_sigmask |= ps->ps_catchmask[sig] | mask; | |
1019 | (void) spl0(); | |
1020 | p->p_stats->p_ru.ru_nsignals++; | |
8429d022 | 1021 | sendsig(action, sig, returnmask, 0); |
8429d022 | 1022 | } |
687880f9 BJ |
1023 | } |
1024 | ||
35493b0f MK |
1025 | /* |
1026 | * Force the current process to exit with the specified | |
1027 | * signal, dumping core if appropriate. We bypass the normal | |
1028 | * tests for masked and caught signals, allowing unrecoverable | |
1029 | * failures to terminate the process without changing signal state. | |
1030 | * Mark the accounting record with the signal termination. | |
1031 | * If dumping core, save the signal number for the debugger. | |
1032 | * Calls exit and does not return. | |
1033 | */ | |
1034 | sigexit(p, sig) | |
1035 | register struct proc *p; | |
1036 | int sig; | |
1037 | { | |
1038 | ||
1039 | p->p_acflag |= AXSIG; | |
1040 | if (sigprop[sig] & SA_CORE) { | |
1041 | p->p_sigacts->ps_sig = sig; | |
1042 | if (coredump(p) == 0) | |
1043 | sig |= WCOREFLAG; | |
1044 | } | |
1045 | exit(p, W_EXITCODE(0, sig)); | |
1046 | /* NOTREACHED */ | |
1047 | } | |
1048 | ||
687880f9 | 1049 | /* |
8429d022 | 1050 | * Create a core dump. |
bdb4bae9 | 1051 | * The file name is "core.progname". |
a91cddfd | 1052 | * Core dumps are not created if the process is setuid. |
687880f9 | 1053 | */ |
8429d022 MK |
1054 | coredump(p) |
1055 | register struct proc *p; | |
687880f9 | 1056 | { |
9342689a JH |
1057 | USES_VOP_GETATTR; |
1058 | USES_VOP_SETATTR; | |
1059 | USES_VOP_UNLOCK; | |
c4ec2128 | 1060 | register struct vnode *vp; |
8429d022 MK |
1061 | register struct pcred *pcred = p->p_cred; |
1062 | register struct ucred *cred = pcred->pc_ucred; | |
1063 | register struct vmspace *vm = p->p_vmspace; | |
d86a61ec | 1064 | struct vattr vattr; |
79583d0d | 1065 | int error, error1; |
8429d022 | 1066 | struct nameidata nd; |
bdb4bae9 | 1067 | char name[MAXCOMLEN+6]; /* core.progname */ |
687880f9 | 1068 | |
8429d022 MK |
1069 | if (pcred->p_svuid != pcred->p_ruid || |
1070 | pcred->p_svgid != pcred->p_rgid) | |
d86a61ec | 1071 | return (EFAULT); |
8429d022 MK |
1072 | if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >= |
1073 | p->p_rlimit[RLIMIT_CORE].rlim_cur) | |
d86a61ec | 1074 | return (EFAULT); |
bdb4bae9 | 1075 | sprintf(name, "core.%s", p->p_comm); |
0c9db509 JH |
1076 | NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p); |
1077 | if (error = vn_open(&nd, O_CREAT|FWRITE, 0644)) | |
d86a61ec | 1078 | return (error); |
8429d022 | 1079 | vp = nd.ni_vp; |
6bcdc4f3 | 1080 | if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) || |
d86a61ec | 1081 | vattr.va_nlink != 1) { |
79583d0d KM |
1082 | error = EFAULT; |
1083 | goto out; | |
7b0cb7cb | 1084 | } |
3ee1461b | 1085 | VATTR_NULL(&vattr); |
d86a61ec | 1086 | vattr.va_size = 0; |
4fcc40ae | 1087 | LEASE_CHECK(vp, p, cred, LEASE_WRITE); |
6bcdc4f3 | 1088 | VOP_SETATTR(vp, &vattr, cred, p); |
8429d022 | 1089 | p->p_acflag |= ACORE; |
8e6cd807 MK |
1090 | bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc)); |
1091 | fill_eproc(p, &p->p_addr->u_kproc.kp_eproc); | |
7b2c7fa0 | 1092 | error = cpu_coredump(p, vp, cred); |
d86a61ec | 1093 | if (error == 0) |
8429d022 MK |
1094 | error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr, |
1095 | (int)ctob(vm->vm_dsize), (off_t)ctob(UPAGES), UIO_USERSPACE, | |
8e6cd807 | 1096 | IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); |
d86a61ec KM |
1097 | if (error == 0) |
1098 | error = vn_rdwr(UIO_WRITE, vp, | |
8e6cd807 | 1099 | (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)), |
8429d022 MK |
1100 | round_page(ctob(vm->vm_ssize)), |
1101 | (off_t)ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE, | |
8e6cd807 | 1102 | IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p); |
79583d0d KM |
1103 | out: |
1104 | VOP_UNLOCK(vp); | |
1105 | error1 = vn_close(vp, FWRITE, cred, p); | |
bdb4bae9 | 1106 | if (error == 0) |
79583d0d | 1107 | error = error1; |
d86a61ec | 1108 | return (error); |
687880f9 | 1109 | } |
f4af9a5b MK |
1110 | |
1111 | /* | |
1112 | * Nonexistent system call-- signal process (may want to handle it). | |
1113 | * Flag error in case process won't see signal immediately (blocked or ignored). | |
1114 | */ | |
8eea23a6 KM |
1115 | /* ARGSUSED */ |
1116 | nosys(p, args, retval) | |
1117 | struct proc *p; | |
1118 | void *args; | |
1119 | int *retval; | |
f4af9a5b MK |
1120 | { |
1121 | ||
8eea23a6 | 1122 | psignal(p, SIGSYS); |
d9c2f47f | 1123 | return (EINVAL); |
f4af9a5b | 1124 | } |