1: /* 2: * Copyright (c) 1982, 1986, 1989, 1991, 1993 3: * The Regents of the University of California. All rights reserved. 4: * (c) UNIX System Laboratories, Inc. 5: * All or some portions of this file are derived from material licensed 6: * to the University of California by American Telephone and Telegraph 7: * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8: * the permission of UNIX System Laboratories, Inc. 9: * 10: * Redistribution and use in source and binary forms, with or without 11: * modification, are permitted provided that the following conditions 12: * are met: 13: * 1. Redistributions of source code must retain the above copyright 14: * notice, this list of conditions and the following disclaimer. 15: * 2. Redistributions in binary form must reproduce the above copyright 16: * notice, this list of conditions and the following disclaimer in the 17: * documentation and/or other materials provided with the distribution. 18: * 3. All advertising materials mentioning features or use of this software 19: * must display the following acknowledgement: 20: * This product includes software developed by the University of 21: * California, Berkeley and its contributors. 22: * 4. Neither the name of the University nor the names of its contributors 23: * may be used to endorse or promote products derived from this software 24: * without specific prior written permission. 25: * 26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36: * SUCH DAMAGE. 37: * 38: * @(#)kern_sig.c 8.14.2 (2.11BSD) 1999/9/9 39: */ 40: 41: /* 42: * This module is a hacked down version of kern_sig.c from 4.4BSD. The 43: * original signal handling code is still present in 2.11's kern_sig.c. This 44: * was done because large modules are very hard to fit into the kernel's 45: * overlay structure. A smaller kern_sig2.c fits more easily into an overlaid 46: * kernel. 47: */ 48: 49: #define SIGPROP /* include signal properties table */ 50: #include <sys/param.h> 51: #include <sys/signal.h> 52: #include <sys/signalvar.h> 53: #include <sys/dir.h> 54: #include <sys/namei.h> 55: #include <sys/time.h> 56: #include <sys/resource.h> 57: #include <sys/proc.h> 58: #include <sys/systm.h> 59: #include <sys/kernel.h> 60: #include <sys/user.h> /* for coredump */ 61: 62: static void stop(); 63: 64: int 65: sigaction() 66: { 67: register struct a { 68: int (*sigtramp)(); 69: int signum; 70: struct sigaction *nsa; 71: struct sigaction *osa; 72: } *uap = (struct a *)u.u_ap; 73: struct sigaction vec; 74: register struct sigaction *sa; 75: register int signum; 76: u_long bit; 77: int error = 0; 78: 79: u.u_pcb.pcb_sigc = uap->sigtramp; /* save trampoline address */ 80: 81: signum = uap->signum; 82: if (signum <= 0 || signum >= NSIG) 83: { 84: error = EINVAL; 85: goto out; 86: } 87: if (uap->nsa && (signum == SIGKILL || signum == SIGSTOP)) 88: { 89: error = EINVAL; 90: goto out; 91: } 92: sa = &vec; 93: if (uap->osa) { 94: sa->sa_handler = u.u_signal[signum]; 95: sa->sa_mask = u.u_sigmask[signum]; 96: bit = sigmask(signum); 97: sa->sa_flags = 0; 98: if ((u.u_sigonstack & bit) != 0) 99: sa->sa_flags |= SA_ONSTACK; 100: if ((u.u_sigintr & bit) == 0) 101: sa->sa_flags |= SA_RESTART; 102: if (u.u_procp->p_flag & P_NOCLDSTOP) 103: sa->sa_flags |= SA_NOCLDSTOP; 104: if ((error = copyout(sa, uap->osa, sizeof(vec))) != 0) 105: goto out; 106: } 107: if (uap->nsa) { 108: if ((error = copyin(uap->nsa, sa, sizeof(vec))) != 0) 109: goto out; 110: setsigvec(signum, sa); 111: } 112: out: 113: return(u.u_error = error); 114: } 115: 116: void 117: setsigvec(signum, sa) 118: int signum; 119: register struct sigaction *sa; 120: { 121: unsigned long bit; 122: register struct proc *p = u.u_procp; 123: 124: bit = sigmask(signum); 125: /* 126: * Change setting atomically. 127: */ 128: (void) splhigh(); 129: u.u_signal[signum] = sa->sa_handler; 130: u.u_sigmask[signum] = sa->sa_mask &~ sigcantmask; 131: if ((sa->sa_flags & SA_RESTART) == 0) 132: u.u_sigintr |= bit; 133: else 134: u.u_sigintr &= ~bit; 135: if (sa->sa_flags & SA_ONSTACK) 136: u.u_sigonstack |= bit; 137: else 138: u.u_sigonstack &= ~bit; 139: if (signum == SIGCHLD) { 140: if (sa->sa_flags & SA_NOCLDSTOP) 141: p->p_flag |= P_NOCLDSTOP; 142: else 143: p->p_flag &= ~P_NOCLDSTOP; 144: } 145: /* 146: * Set bit in p_sigignore for signals that are set to SIG_IGN, 147: * and for signals set to SIG_DFL where the default is to ignore. 148: * However, don't put SIGCONT in p_sigignore, 149: * as we have to restart the process. 150: */ 151: if (sa->sa_handler == SIG_IGN || 152: (sigprop[signum] & SA_IGNORE && sa->sa_handler == SIG_DFL)) { 153: p->p_sig &= ~bit; /* never to be seen again */ 154: if (signum != SIGCONT) 155: p->p_sigignore |= bit; /* easier in psignal */ 156: p->p_sigcatch &= ~bit; 157: } else { 158: p->p_sigignore &= ~bit; 159: if (sa->sa_handler == SIG_DFL) 160: p->p_sigcatch &= ~bit; 161: else 162: p->p_sigcatch |= bit; 163: } 164: (void) spl0(); 165: } 166: 167: /* 168: * Kill current process with the specified signal in an uncatchable manner; 169: * used when process is too confused to continue, or we are unable to 170: * reconstruct the process state safely. 171: */ 172: void 173: fatalsig(signum) 174: int signum; 175: { 176: unsigned long mask; 177: register struct proc *p = u.u_procp; 178: 179: u.u_signal[signum] = SIG_DFL; 180: mask = sigmask(signum); 181: p->p_sigignore &= ~mask; 182: p->p_sigcatch &= ~mask; 183: p->p_sigmask &= ~mask; 184: psignal(p, signum); 185: } 186: 187: /* 188: * Initialize signal state for process 0; 189: * set to ignore signals that are ignored by default. 190: */ 191: void 192: siginit(p) 193: register struct proc *p; 194: { 195: register int i; 196: 197: for (i = 0; i < NSIG; i++) 198: if (sigprop[i] & SA_IGNORE && i != SIGCONT) 199: p->p_sigignore |= sigmask(i); 200: } 201: 202: /* 203: * Manipulate signal mask. 204: * Unlike 4.4BSD we do not receive a pointer to the new and old mask areas and 205: * do a copyin/copyout instead of storing indirectly thru a 'retval' parameter. 206: * This is because we have to return both an error indication (which is 16 bits) 207: * _AND_ the new mask (which is 32 bits). Can't do both at the same time with 208: * the 2BSD syscall return mechanism. 209: */ 210: int 211: sigprocmask() 212: { 213: register struct a { 214: int how; 215: sigset_t *set; 216: sigset_t *oset; 217: } *uap = (struct a *)u.u_ap; 218: int error = 0; 219: sigset_t oldmask, newmask; 220: register struct proc *p = u.u_procp; 221: 222: oldmask = p->p_sigmask; 223: if (!uap->set) /* No new mask, go possibly return old mask */ 224: goto out; 225: if (error = copyin(uap->set, &newmask, sizeof (newmask))) 226: goto out; 227: (void) splhigh(); 228: 229: switch (uap->how) { 230: case SIG_BLOCK: 231: p->p_sigmask |= (newmask &~ sigcantmask); 232: break; 233: case SIG_UNBLOCK: 234: p->p_sigmask &= ~newmask; 235: break; 236: case SIG_SETMASK: 237: p->p_sigmask = newmask &~ sigcantmask; 238: break; 239: default: 240: error = EINVAL; 241: break; 242: } 243: (void) spl0(); 244: out: 245: if (error == 0 && uap->oset) 246: error = copyout(&oldmask, uap->oset, sizeof (oldmask)); 247: return (u.u_error = error); 248: } 249: 250: /* 251: * sigpending and sigsuspend use the standard calling sequence unlike 4.4 which 252: * used a nonstandard (mask instead of pointer) calling convention. 253: */ 254: 255: int 256: sigpending() 257: { 258: register struct a 259: { 260: struct sigset_t *set; 261: } *uap = (struct a *)u.u_ap; 262: register int error = 0; 263: struct proc *p = u.u_procp; 264: 265: if (uap->set) 266: error = copyout((caddr_t)&p->p_sig, (caddr_t)uap->set, 267: sizeof (p->p_sig)); 268: else 269: error = EINVAL; 270: return(u.u_error = error); 271: } 272: 273: /* 274: * sigsuspend is supposed to always return EINTR so we ignore errors on the 275: * copyin by assuming a mask of 0. 276: */ 277: 278: int 279: sigsuspend() 280: { 281: register struct a 282: { 283: struct sigset_t *set; 284: } *uap = (struct a *)u.u_ap; 285: sigset_t nmask; 286: struct proc *p = u.u_procp; 287: int error; 288: 289: if (uap->set && (error = copyin(uap->set, &nmask, sizeof (nmask)))) 290: nmask = 0; 291: /* 292: * When returning from sigsuspend, we want the old mask to be restored 293: * after the signal handler has finished. Thus, we save it here and set 294: * a flag to indicate this. 295: */ 296: u.u_oldmask = p->p_sigmask; 297: u.u_psflags |= SAS_OLDMASK; 298: p->p_sigmask = nmask &~ sigcantmask; 299: while (tsleep((caddr_t)&u, PPAUSE|PCATCH, 0) == 0) 300: ; 301: /* always return EINTR rather than ERESTART */ 302: return(u.u_error = EINTR); 303: } 304: 305: int 306: sigaltstack() 307: { 308: register struct a { 309: struct sigaltstack * nss; 310: struct sigaltstack * oss; 311: } *uap = (struct a *)u.u_ap; 312: struct sigaltstack ss; 313: int error = 0; 314: 315: if ((u.u_psflags & SAS_ALTSTACK) == 0) 316: u.u_sigstk.ss_flags |= SA_DISABLE; 317: if (uap->oss && (error = copyout((caddr_t)&u.u_sigstk, 318: (caddr_t)uap->oss, sizeof (struct sigaltstack)))) 319: goto out; 320: if (uap->nss == 0) 321: goto out; 322: if ((error = copyin(uap->nss, &ss, sizeof(ss))) != 0) 323: goto out; 324: if (ss.ss_flags & SA_DISABLE) { 325: if (u.u_sigstk.ss_flags & SA_ONSTACK) 326: { 327: error = EINVAL; 328: goto out; 329: } 330: u.u_psflags &= ~SAS_ALTSTACK; 331: u.u_sigstk.ss_flags = ss.ss_flags; 332: goto out; 333: } 334: if (ss.ss_size < MINSIGSTKSZ) 335: { 336: error = ENOMEM; 337: goto out; 338: } 339: u.u_psflags |= SAS_ALTSTACK; 340: u.u_sigstk = ss; 341: out: 342: return(u.u_error = error); 343: } 344: 345: int 346: sigwait() 347: { 348: register struct a { 349: sigset_t *set; 350: int *sig; 351: } *uap = (struct a *)u.u_ap; 352: sigset_t wanted, sigsavail; 353: register struct proc *p = u.u_procp; 354: int signo, error; 355: 356: if (uap->set == 0 || uap->sig == 0) 357: { 358: error = EINVAL; 359: goto out; 360: } 361: if (error = copyin(uap->set, &wanted, sizeof (sigset_t))) 362: goto out; 363: 364: wanted |= sigcantmask; 365: while ((sigsavail = (wanted & p->p_sig)) == 0) 366: tsleep(&u.u_signal[0], PPAUSE | PCATCH, 0); 367: 368: if (sigsavail & sigcantmask) 369: { 370: error = EINTR; 371: goto out; 372: } 373: 374: signo = ffs(sigsavail); 375: p->p_sig &= ~sigmask(signo); 376: error = copyout(&signo, uap->sig, sizeof (int)); 377: out: 378: return(u.u_error = error); 379: }