Check for out of space condition before extending ifile.
[unix-history] / usr / src / sys / kern / kern_sig.c
index 13b4e92..9a2fc94 100644 (file)
@@ -4,7 +4,7 @@
  *
  * %sccs.include.redist.c%
  *
  *
  * %sccs.include.redist.c%
  *
- *     @(#)kern_sig.c  7.37 (Berkeley) %G%
+ *     @(#)kern_sig.c  7.50 (Berkeley) %G%
  */
 
 #define        SIGPROP         /* include signal properties table */
  */
 
 #define        SIGPROP         /* include signal properties table */
            (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \
            ((signo) == SIGCONT && (q)->p_session == (p)->p_session))
 
            (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \
            ((signo) == SIGCONT && (q)->p_session == (p)->p_session))
 
+struct sigaction_args {
+       int     signo;
+       struct  sigaction *nsa;
+       struct  sigaction *osa;
+};
 /* ARGSUSED */
 sigaction(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 sigaction(p, uap, retval)
        struct proc *p;
-       register struct args {
-               int     signo;
-               struct  sigaction *nsa;
-               struct  sigaction *osa;
-       } *uap;
+       register struct sigaction_args *uap;
        int *retval;
 {
        struct sigaction vec;
        int *retval;
 {
        struct sigaction vec;
@@ -108,6 +109,12 @@ setsigvec(p, sig, sa)
                ps->ps_sigonstack |= bit;
        else
                ps->ps_sigonstack &= ~bit;
                ps->ps_sigonstack |= bit;
        else
                ps->ps_sigonstack &= ~bit;
+#ifdef COMPAT_SUNOS
+       if (sa->sa_flags & SA_USERTRAMP)
+               ps->ps_usertramp |= bit;
+       else
+               ps->ps_usertramp &= ~bit;
+#endif
        if (sig == SIGCHLD) {
                if (sa->sa_flags & SA_NOCLDSTOP)
                        p->p_flag |= SNOCLDSTOP;
        if (sig == SIGCHLD) {
                if (sa->sa_flags & SA_NOCLDSTOP)
                        p->p_flag |= SNOCLDSTOP;
@@ -181,9 +188,10 @@ execsigs(p)
         * Reset stack state to the user stack.
         * Clear set of signals caught on the signal stack.
         */
         * Reset stack state to the user stack.
         * Clear set of signals caught on the signal stack.
         */
-       ps->ps_onstack = 0;
-       ps->ps_sigsp = 0;
-       ps->ps_sigonstack = 0;
+       ps->ps_sigstk.ss_flags = SA_DISABLE;
+       ps->ps_sigstk.ss_size = 0;
+       ps->ps_sigstk.ss_base = 0;
+       ps->ps_flags = 0;
 }
 
 /*
 }
 
 /*
@@ -192,12 +200,13 @@ execsigs(p)
  * and return old mask as return value;
  * the library stub does the rest.
  */
  * and return old mask as return value;
  * the library stub does the rest.
  */
+struct sigprocmask_args {
+       int     how;
+       sigset_t mask;
+};
 sigprocmask(p, uap, retval)
        register struct proc *p;
 sigprocmask(p, uap, retval)
        register struct proc *p;
-       struct args {
-               int     how;
-               sigset_t mask;
-       } *uap;
+       struct sigprocmask_args *uap;
        int *retval;
 {
        int error = 0;
        int *retval;
 {
        int error = 0;
@@ -226,10 +235,13 @@ sigprocmask(p, uap, retval)
        return (error);
 }
 
        return (error);
 }
 
+struct sigpending_args {
+       int     dummy;
+};
 /* ARGSUSED */
 sigpending(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 sigpending(p, uap, retval)
        struct proc *p;
-       void *uap;
+       struct sigpending_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -237,18 +249,19 @@ sigpending(p, uap, retval)
        return (0);
 }
 
        return (0);
 }
 
-#ifdef COMPAT_43
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
 /*
  * Generalized interface signal handler, 4.3-compatible.
  */
 /*
  * Generalized interface signal handler, 4.3-compatible.
  */
+struct osigvec_args {
+       int     signo;
+       struct  sigvec *nsv;
+       struct  sigvec *osv;
+};
 /* ARGSUSED */
 osigvec(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 osigvec(p, uap, retval)
        struct proc *p;
-       register struct args {
-               int     signo;
-               struct  sigvec *nsv;
-               struct  sigvec *osv;
-       } *uap;
+       register struct osigvec_args *uap;
        int *retval;
 {
        struct sigvec vec;
        int *retval;
 {
        struct sigvec vec;
@@ -270,8 +283,10 @@ osigvec(p, uap, retval)
                        sv->sv_flags |= SV_ONSTACK;
                if ((ps->ps_sigintr & bit) != 0)
                        sv->sv_flags |= SV_INTERRUPT;
                        sv->sv_flags |= SV_ONSTACK;
                if ((ps->ps_sigintr & bit) != 0)
                        sv->sv_flags |= SV_INTERRUPT;
+#ifndef COMPAT_SUNOS
                if (p->p_flag & SNOCLDSTOP)
                        sv->sv_flags |= SA_NOCLDSTOP;
                if (p->p_flag & SNOCLDSTOP)
                        sv->sv_flags |= SA_NOCLDSTOP;
+#endif
                if (error = copyout((caddr_t)sv, (caddr_t)uap->osv,
                    sizeof (vec)))
                        return (error);
                if (error = copyout((caddr_t)sv, (caddr_t)uap->osv,
                    sizeof (vec)))
                        return (error);
@@ -280,17 +295,28 @@ osigvec(p, uap, retval)
                if (error = copyin((caddr_t)uap->nsv, (caddr_t)sv,
                    sizeof (vec)))
                        return (error);
                if (error = copyin((caddr_t)uap->nsv, (caddr_t)sv,
                    sizeof (vec)))
                        return (error);
+#ifdef COMPAT_SUNOS
+               /*
+                * SunOS uses this bit (4, aka SA_DISABLE) as SV_RESETHAND,
+                * `reset to SIG_DFL on delivery'. We have no such option
+                * now or ever!
+                */
+               if (sv->sv_flags & SA_DISABLE)
+                       return (EINVAL);
+               sv->sv_flags |= SA_USERTRAMP;
+#endif
                sv->sv_flags ^= SA_RESTART;     /* opposite of SV_INTERRUPT */
                setsigvec(p, sig, (struct sigaction *)sv);
        }
        return (0);
 }
 
                sv->sv_flags ^= SA_RESTART;     /* opposite of SV_INTERRUPT */
                setsigvec(p, sig, (struct sigaction *)sv);
        }
        return (0);
 }
 
+struct osigblock_args {
+       int     mask;
+};
 osigblock(p, uap, retval)
        register struct proc *p;
 osigblock(p, uap, retval)
        register struct proc *p;
-       struct args {
-               int     mask;
-       } *uap;
+       struct osigblock_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -301,11 +327,12 @@ osigblock(p, uap, retval)
        return (0);
 }
 
        return (0);
 }
 
+struct osigsetmask_args {
+       int     mask;
+};
 osigsetmask(p, uap, retval)
        struct proc *p;
 osigsetmask(p, uap, retval)
        struct proc *p;
-       struct args {
-               int     mask;
-       } *uap;
+       struct osigsetmask_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -315,19 +342,20 @@ osigsetmask(p, uap, retval)
        (void) spl0();
        return (0);
 }
        (void) spl0();
        return (0);
 }
-#endif
+#endif /* COMPAT_43 || COMPAT_SUNOS */
 
 /*
  * Suspend process until signal, providing mask to be set
  * in the meantime.  Note nonstandard calling convention:
  * libc stub passes mask, not pointer, to save a copyin.
  */
 
 /*
  * Suspend process until signal, providing mask to be set
  * in the meantime.  Note nonstandard calling convention:
  * libc stub passes mask, not pointer, to save a copyin.
  */
+struct sigsuspend_args {
+       sigset_t mask;
+};
 /* ARGSUSED */
 sigsuspend(p, uap, retval)
        register struct proc *p;
 /* ARGSUSED */
 sigsuspend(p, uap, retval)
        register struct proc *p;
-       struct args {
-               sigset_t mask;
-       } *uap;
+       struct sigsuspend_args *uap;
        int *retval;
 {
        register struct sigacts *ps = p->p_sigacts;
        int *retval;
 {
        register struct sigacts *ps = p->p_sigacts;
@@ -336,45 +364,95 @@ sigsuspend(p, uap, retval)
         * When returning from sigpause, we want
         * the old mask to be restored after the
         * signal handler has finished.  Thus, we
         * When returning from sigpause, we want
         * the old mask to be restored after the
         * signal handler has finished.  Thus, we
-        * save it here and mark the proc structure
-        * to indicate this (should be in sigacts).
+        * save it here and mark the sigacts structure
+        * to indicate this.
         */
        ps->ps_oldmask = p->p_sigmask;
         */
        ps->ps_oldmask = p->p_sigmask;
-       ps->ps_flags |= SA_OLDMASK;
+       ps->ps_flags |= SAS_OLDMASK;
        p->p_sigmask = uap->mask &~ sigcantmask;
        (void) tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0);
        /* always return EINTR rather than ERESTART... */
        return (EINTR);
 }
 
        p->p_sigmask = uap->mask &~ sigcantmask;
        (void) tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0);
        /* always return EINTR rather than ERESTART... */
        return (EINTR);
 }
 
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
+struct osigstack_args {
+       struct  sigstack *nss;
+       struct  sigstack *oss;
+};
 /* ARGSUSED */
 /* ARGSUSED */
-sigstack(p, uap, retval)
+osigstack(p, uap, retval)
        struct proc *p;
        struct proc *p;
-       register struct args {
-               struct  sigstack *nss;
-               struct  sigstack *oss;
-       } *uap;
+       register struct osigstack_args *uap;
        int *retval;
 {
        struct sigstack ss;
        int *retval;
 {
        struct sigstack ss;
+       struct sigacts *psp;
        int error = 0;
 
        int error = 0;
 
-       if (uap->oss && (error = copyout((caddr_t)&p->p_sigacts->ps_sigstack,
-           (caddr_t)uap->oss, sizeof (struct sigstack))))
+       psp = p->p_sigacts;
+       ss.ss_sp = psp->ps_sigstk.ss_base;
+       ss.ss_onstack = psp->ps_sigstk.ss_flags & SA_ONSTACK;
+       if (uap->oss && (error = copyout((caddr_t)&ss, (caddr_t)uap->oss,
+           sizeof (struct sigstack))))
                return (error);
        if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss,
                return (error);
        if (uap->nss && (error = copyin((caddr_t)uap->nss, (caddr_t)&ss,
-           sizeof (ss))) == 0)
-               p->p_sigacts->ps_sigstack = ss;
+           sizeof (ss))) == 0) {
+               psp->ps_sigstk.ss_base = ss.ss_sp;
+               psp->ps_sigstk.ss_size = 0;
+               psp->ps_sigstk.ss_flags |= ss.ss_onstack & SA_ONSTACK;
+               psp->ps_flags |= SAS_ALTSTACK;
+       }
        return (error);
 }
        return (error);
 }
+#endif /* COMPAT_43 || COMPAT_SUNOS */
 
 
+struct sigaltstack_args {
+       struct  sigaltstack *nss;
+       struct  sigaltstack *oss;
+};
+/* ARGSUSED */
+sigaltstack(p, uap, retval)
+       struct proc *p;
+       register struct sigaltstack_args *uap;
+       int *retval;
+{
+       struct sigacts *psp;
+       struct sigaltstack ss;
+       int error;
+
+       psp = p->p_sigacts;
+       if ((psp->ps_flags & SAS_ALTSTACK) == 0)
+               psp->ps_sigstk.ss_flags |= SA_DISABLE;
+       if (uap->oss && (error = copyout((caddr_t)&psp->ps_sigstk,
+           (caddr_t)uap->oss, sizeof (struct sigaltstack))))
+               return (error);
+       if (uap->nss == 0)
+               return (0);
+       if (error = copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)))
+               return (error);
+       if (ss.ss_flags & SA_DISABLE) {
+               if (psp->ps_sigstk.ss_flags & SA_ONSTACK)
+                       return (EINVAL);
+               psp->ps_flags &= ~SAS_ALTSTACK;
+               psp->ps_sigstk.ss_flags = ss.ss_flags;
+               return (0);
+       }
+       if (ss.ss_size < MINSIGSTKSZ)
+               return (ENOMEM);
+       psp->ps_flags |= SAS_ALTSTACK;
+       psp->ps_sigstk= ss;
+       return (0);
+}
+
+struct kill_args {
+       int     pid;
+       int     signo;
+};
 /* ARGSUSED */
 kill(cp, uap, retval)
        register struct proc *cp;
 /* ARGSUSED */
 kill(cp, uap, retval)
        register struct proc *cp;
-       register struct args {
-               int     pid;
-               int     signo;
-       } *uap;
+       register struct kill_args *uap;
        int *retval;
 {
        register struct proc *p;
        int *retval;
 {
        register struct proc *p;
@@ -404,14 +482,15 @@ kill(cp, uap, retval)
        /* NOTREACHED */
 }
 
        /* NOTREACHED */
 }
 
-#ifdef COMPAT_43
+#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
+struct okillpg_args {
+       int     pgid;
+       int     signo;
+};
 /* ARGSUSED */
 okillpg(p, uap, retval)
        struct proc *p;
 /* ARGSUSED */
 okillpg(p, uap, retval)
        struct proc *p;
-       register struct args {
-               int     pgid;
-               int     signo;
-       } *uap;
+       register struct okillpg_args *uap;
        int *retval;
 {
 
        int *retval;
 {
 
@@ -419,7 +498,7 @@ okillpg(p, uap, retval)
                return (EINVAL);
        return (killpg1(p, uap->signo, uap->pgid, 0));
 }
                return (EINVAL);
        return (killpg1(p, uap->signo, uap->pgid, 0));
 }
-#endif
+#endif /* COMPAT_43 || COMPAT_SUNOS */
 
 /*
  * Common code for kill process group/broadcast kill.
 
 /*
  * Common code for kill process group/broadcast kill.
@@ -438,7 +517,7 @@ killpg1(cp, signo, pgid, all)
                /* 
                 * broadcast 
                 */
                /* 
                 * broadcast 
                 */
-               for (p = allproc; p != NULL; p = p->p_nxt) {
+               for (p = (struct proc *)allproc; p != NULL; p = p->p_nxt) {
                        if (p->p_pid <= 1 || p->p_flag&SSYS || 
                            p == cp || !CANSIGNAL(cp, pc, p, signo))
                                continue;
                        if (p->p_pid <= 1 || p->p_flag&SSYS || 
                            p == cp || !CANSIGNAL(cp, pc, p, signo))
                                continue;
@@ -917,7 +996,7 @@ psig(sig)
        action = ps->ps_sigact[sig];
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_PSIG))
        action = ps->ps_sigact[sig];
 #ifdef KTRACE
        if (KTRPOINT(p, KTR_PSIG))
-               ktrpsig(p->p_tracep, sig, action, ps->ps_flags & SA_OLDMASK ?
+               ktrpsig(p->p_tracep, sig, action, ps->ps_flags & SAS_OLDMASK ?
                    ps->ps_oldmask : p->p_sigmask, 0);
 #endif
        if (action == SIG_DFL) {
                    ps->ps_oldmask : p->p_sigmask, 0);
 #endif
        if (action == SIG_DFL) {
@@ -945,9 +1024,9 @@ psig(sig)
                 * restored after the signal processing is completed.
                 */
                (void) splhigh();
                 * restored after the signal processing is completed.
                 */
                (void) splhigh();
-               if (ps->ps_flags & SA_OLDMASK) {
+               if (ps->ps_flags & SAS_OLDMASK) {
                        returnmask = ps->ps_oldmask;
                        returnmask = ps->ps_oldmask;
-                       ps->ps_flags &= ~SA_OLDMASK;
+                       ps->ps_flags &= ~SAS_OLDMASK;
                } else
                        returnmask = p->p_sigmask;
                p->p_sigmask |= ps->ps_catchmask[sig] | mask;
                } else
                        returnmask = p->p_sigmask;
                p->p_sigmask |= ps->ps_catchmask[sig] | mask;
@@ -1005,9 +1084,8 @@ coredump(p)
            p->p_rlimit[RLIMIT_CORE].rlim_cur)
                return (EFAULT);
        sprintf(name, "core.%s", p->p_comm);
            p->p_rlimit[RLIMIT_CORE].rlim_cur)
                return (EFAULT);
        sprintf(name, "core.%s", p->p_comm);
-       nd.ni_dirp = name;
-       nd.ni_segflg = UIO_SYSSPACE;
-       if (error = vn_open(&nd, p, O_CREAT|FWRITE, 0644))
+       NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
+       if (error = vn_open(&nd, O_CREAT|FWRITE, 0644))
                return (error);
        vp = nd.ni_vp;
        if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) ||
                return (error);
        vp = nd.ni_vp;
        if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) ||
@@ -1017,23 +1095,12 @@ coredump(p)
        }
        VATTR_NULL(&vattr);
        vattr.va_size = 0;
        }
        VATTR_NULL(&vattr);
        vattr.va_size = 0;
+       LEASE_CHECK(vp, p, cred, LEASE_WRITE);
        VOP_SETATTR(vp, &vattr, cred, p);
        p->p_acflag |= ACORE;
        bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc));
        fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
        VOP_SETATTR(vp, &vattr, cred, p);
        p->p_acflag |= ACORE;
        bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc));
        fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
-#ifdef HPUXCOMPAT
-       /*
-        * BLETCH!  If we loaded from an HPUX format binary file
-        * we have to dump an HPUX style user struct so that the
-        * HPUX debuggers can grok it.
-        */
-       if (p->p_addr->u_pcb.pcb_flags & PCB_HPUXBIN)
-               error = hpuxdumpu(vp, cred);
-       else
-#endif
-       error = vn_rdwr(UIO_WRITE, vp, (caddr_t) p->p_addr, ctob(UPAGES),
-           (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL,
-           p);
+       error = cpu_coredump(p, vp, cred);
        if (error == 0)
                error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
                    (int)ctob(vm->vm_dsize), (off_t)ctob(UPAGES), UIO_USERSPACE,
        if (error == 0)
                error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
                    (int)ctob(vm->vm_dsize), (off_t)ctob(UPAGES), UIO_USERSPACE,
@@ -1056,10 +1123,13 @@ out:
  * Nonexistent system call-- signal process (may want to handle it).
  * Flag error in case process won't see signal immediately (blocked or ignored).
  */
  * Nonexistent system call-- signal process (may want to handle it).
  * Flag error in case process won't see signal immediately (blocked or ignored).
  */
+struct nosys_args {
+       int     dummy;
+};
 /* ARGSUSED */
 nosys(p, args, retval)
        struct proc *p;
 /* ARGSUSED */
 nosys(p, args, retval)
        struct proc *p;
-       void *args;
+       struct nosys_args *args;
        int *retval;
 {
 
        int *retval;
 {