]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_sig.c
xnu-517.9.5.tar.gz
[apple/xnu.git] / bsd / kern / kern_sig.c
index 21c9358d9feaf0464f89b87c8a29caa610f68765..6c593326eeb6430e6b1a6c0759e9597dc3fe03c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2000-2001 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
 #include <sys/stat.h>
 #include <sys/lock.h>
 #include <sys/kdebug.h>
 #include <sys/stat.h>
 #include <sys/lock.h>
 #include <sys/kdebug.h>
-
 #include <sys/mount.h>
 
 #include <sys/mount.h>
 
+#include <bsm/audit_kernel.h>
+
 #include <kern/cpu_number.h>
 
 #include <sys/vm.h>
 #include <kern/cpu_number.h>
 
 #include <sys/vm.h>
@@ -110,6 +111,13 @@ void psignal_lock __P((struct proc *, int, int));
 void psignal_uthread __P((thread_act_t, int));
 kern_return_t do_bsdexception(int, int, int);
 
 void psignal_uthread __P((thread_act_t, int));
 kern_return_t do_bsdexception(int, int, int);
 
+static int     filt_sigattach(struct knote *kn);
+static void    filt_sigdetach(struct knote *kn);
+static int     filt_signal(struct knote *kn, long hint);
+
+struct filterops sig_filtops =
+       { 0, filt_sigattach, filt_sigdetach, filt_signal };
+
 #if SIGNAL_DEBUG
 void ram_printf __P((int));
 int ram_debug=0;
 #if SIGNAL_DEBUG
 void ram_printf __P((int));
 int ram_debug=0;
@@ -287,6 +295,8 @@ sigaction(p, uap, retval)
                        sa->sa_flags |= SA_SIGINFO;
                if (ps->ps_signodefer & bit)
                        sa->sa_flags |= SA_NODEFER;
                        sa->sa_flags |= SA_SIGINFO;
                if (ps->ps_signodefer & bit)
                        sa->sa_flags |= SA_NODEFER;
+               if (ps->ps_64regset & bit)
+                       sa->sa_flags |= SA_64REGSET;
                if ((signum == SIGCHLD) && (p->p_flag & P_NOCLDSTOP))
                        sa->sa_flags |= SA_NOCLDSTOP;
                if ((signum == SIGCHLD) && (p->p_flag & P_NOCLDWAIT))
                if ((signum == SIGCHLD) && (p->p_flag & P_NOCLDSTOP))
                        sa->sa_flags |= SA_NOCLDSTOP;
                if ((signum == SIGCHLD) && (p->p_flag & P_NOCLDWAIT))
@@ -424,12 +434,16 @@ setsigvec(p, signum, sa)
         * Change setting atomically.
         */
        ps->ps_sigact[signum] = sa->sa_handler;
         * Change setting atomically.
         */
        ps->ps_sigact[signum] = sa->sa_handler;
-       ps->ps_trampact[signum] = sa->sa_tramp;
+       ps->ps_trampact[signum] = (sig_t) sa->sa_tramp;
        ps->ps_catchmask[signum] = sa->sa_mask &~ sigcantmask;
        if (sa->sa_flags & SA_SIGINFO)
                ps->ps_siginfo |= bit;
        else
                ps->ps_siginfo &= ~bit;
        ps->ps_catchmask[signum] = sa->sa_mask &~ sigcantmask;
        if (sa->sa_flags & SA_SIGINFO)
                ps->ps_siginfo |= bit;
        else
                ps->ps_siginfo &= ~bit;
+       if (sa->sa_flags & SA_64REGSET)
+               ps->ps_64regset |= bit;
+       else
+               ps->ps_64regset &= ~bit;
        if ((sa->sa_flags & SA_RESTART) == 0)
                ps->ps_sigintr |= bit;
        else
        if ((sa->sa_flags & SA_RESTART) == 0)
                ps->ps_sigintr |= bit;
        else
@@ -652,7 +666,6 @@ osigvec(p, uap, retval)
        register int signum;
        int bit, error=0;
 
        register int signum;
        int bit, error=0;
 
-       panic("osigvec: notsupp");
 #if 0
        signum = uap->signum;
        if (signum <= 0 || signum >= NSIG ||
 #if 0
        signum = uap->signum;
        if (signum <= 0 || signum >= NSIG ||
@@ -681,6 +694,8 @@ osigvec(p, uap, retval)
                sv->sv_flags ^= SA_RESTART;     /* opposite of SV_INTERRUPT */
                error = setsigvec(p, signum, (struct sigaction *)sv);
        }
                sv->sv_flags ^= SA_RESTART;     /* opposite of SV_INTERRUPT */
                error = setsigvec(p, signum, (struct sigaction *)sv);
        }
+#else
+error = ENOSYS;
 #endif
        return (error);
 }
 #endif
        return (error);
 }
@@ -811,8 +826,7 @@ __pthread_kill(p, uap, retval)
        }
 
        uth = (struct uthread *)get_bsdthread_info(target_act);
        }
 
        uth = (struct uthread *)get_bsdthread_info(target_act);
-       { void *tht = getshuttle_thread(target_act);
-}
+
        if (uth->uu_flag & UNO_SIGMASK) {
                error = ESRCH;
                goto out;
        if (uth->uu_flag & UNO_SIGMASK) {
                error = ESRCH;
                goto out;
@@ -1045,7 +1059,9 @@ sigaltstack(p, uap, retval)
                psp->ps_sigstk.ss_flags = ss.ss_flags;
                return (0);
        }
                psp->ps_sigstk.ss_flags = ss.ss_flags;
                return (0);
        }
-       if (ss.ss_size < MINSIGSTKSZ)
+/* The older stacksize was 8K, enforce that one so no compat problems */
+#define OLDMINSIGSTKSZ 8*1024
+       if (ss.ss_size < OLDMINSIGSTKSZ)
                return (ENOMEM);
        psp->ps_flags |= SAS_ALTSTACK;
        psp->ps_sigstk= ss;
                return (ENOMEM);
        psp->ps_flags |= SAS_ALTSTACK;
        psp->ps_sigstk= ss;
@@ -1066,12 +1082,23 @@ kill(cp, uap, retval)
        register struct proc *p;
        register struct pcred *pc = cp->p_cred;
 
        register struct proc *p;
        register struct pcred *pc = cp->p_cred;
 
+       AUDIT_ARG(pid, uap->pid);
+       AUDIT_ARG(signum, uap->signum);
        if ((u_int)uap->signum >= NSIG)
                return (EINVAL);
        if (uap->pid > 0) {
                /* kill single process */
        if ((u_int)uap->signum >= NSIG)
                return (EINVAL);
        if (uap->pid > 0) {
                /* kill single process */
-               if ((p = pfind(uap->pid)) == NULL)
+               if ((p = pfind(uap->pid)) == NULL) {
+                       if ((p = pzfind(uap->pid)) != NULL) {
+                               /*
+                                * IEEE Std 1003.1-2001: return success
+                                * when killing a zombie.
+                                */
+                               return (0);
+                       }
                        return (ESRCH);
                        return (ESRCH);
+               }
+               AUDIT_ARG(process, p);
                if (!cansignal(cp, pc, p, uap->signum))
                        return (EPERM);
                if (uap->signum)
                if (!cansignal(cp, pc, p, uap->signum))
                        return (EPERM);
                if (uap->signum)
@@ -1102,6 +1129,8 @@ okillpg(p, uap, retval)
        register_t *retval;
 {
 
        register_t *retval;
 {
 
+       AUDIT_ARG(pid, uap->pgid);
+       AUDIT_ARG(signum, uap->signum);
        if ((u_int)uap->signum >= NSIG)
                return (EINVAL);
        return (killpg1(p, uap->signum, uap->pgid, 0));
        if ((u_int)uap->signum >= NSIG)
                return (EINVAL);
        return (killpg1(p, uap->signum, uap->pgid, 0));
@@ -1373,12 +1402,11 @@ get_signalthread(struct proc *p, int signum)
        sigset_t mask = sigmask(signum);
        thread_act_t sig_thread_act;
        struct task * sig_task = p->task;
        sigset_t mask = sigmask(signum);
        thread_act_t sig_thread_act;
        struct task * sig_task = p->task;
-       thread_t sig_thread;
        kern_return_t kret;
        
        if ((p->p_flag & P_INVFORK) && p->p_vforkact) {
                sig_thread_act = p->p_vforkact; 
        kern_return_t kret;
        
        if ((p->p_flag & P_INVFORK) && p->p_vforkact) {
                sig_thread_act = p->p_vforkact; 
-               kret = check_actforsig(sig_task, sig_thread_act, &sig_thread, 1);
+               kret = check_actforsig(sig_task, sig_thread_act, 1);
                if (kret == KERN_SUCCESS) 
                        return(sig_thread_act);
                else
                if (kret == KERN_SUCCESS) 
                        return(sig_thread_act);
                else
@@ -1388,11 +1416,11 @@ get_signalthread(struct proc *p, int signum)
        TAILQ_FOREACH(uth, &p->p_uthlist, uu_list) {
                if(((uth->uu_flag & UNO_SIGMASK)== 0) && 
                        (((uth->uu_sigmask & mask) == 0) || (uth->uu_sigwait & mask))) {
        TAILQ_FOREACH(uth, &p->p_uthlist, uu_list) {
                if(((uth->uu_flag & UNO_SIGMASK)== 0) && 
                        (((uth->uu_sigmask & mask) == 0) || (uth->uu_sigwait & mask))) {
-                       if (check_actforsig(p->task, uth->uu_act, NULL, 1) == KERN_SUCCESS)
+                       if (check_actforsig(p->task, uth->uu_act, 1) == KERN_SUCCESS)
                                return(uth->uu_act);
                }
        }
                                return(uth->uu_act);
                }
        }
-       if (get_signalact(p->task, &thr_act, NULL, 1) == KERN_SUCCESS) {
+       if (get_signalact(p->task, &thr_act, 1) == KERN_SUCCESS) {
                return(thr_act);
        }
 
                return(thr_act);
        }
 
@@ -1421,10 +1449,7 @@ psignal_lock(p, signum, withlock)
        register int s, prop;
        register sig_t action;
        thread_act_t    sig_thread_act;
        register int s, prop;
        register sig_t action;
        thread_act_t    sig_thread_act;
-       thread_t        sig_thread;
        register task_t         sig_task;
        register task_t         sig_task;
-       register thread_t       cur_thread;
-       thread_act_t    cur_act;
        int mask;
        struct uthread *uth;
        kern_return_t kret;
        int mask;
        struct uthread *uth;
        kern_return_t kret;
@@ -1456,6 +1481,10 @@ psignal_lock(p, signum, withlock)
                return;
        }
 
                return;
        }
 
+        s = splhigh();
+        KNOTE(&p->p_klist, NOTE_SIGNAL | signum);
+        splx(s);
+
        /*
         * do not send signals to the process that has the thread
         * doing a reboot(). Not doing so will mark that thread aborted
        /*
         * do not send signals to the process that has the thread
         * doing a reboot(). Not doing so will mark that thread aborted
@@ -1474,7 +1503,7 @@ psignal_lock(p, signum, withlock)
         *      Deliver the signal to the first thread in the task. This
         *      allows single threaded applications which use signals to
         *      be able to be linked with multithreaded libraries.  We have
         *      Deliver the signal to the first thread in the task. This
         *      allows single threaded applications which use signals to
         *      be able to be linked with multithreaded libraries.  We have
-        *      an implicit reference to the current_thread, but need
+        *      an implicit reference to the current thread, but need
         *      an explicit one otherwise.  The thread reference keeps
         *      the corresponding task data structures around too.  This
         *      reference is released by thread_deallocate.
         *      an explicit one otherwise.  The thread reference keeps
         *      the corresponding task data structures around too.  This
         *      reference is released by thread_deallocate.
@@ -1483,9 +1512,6 @@ psignal_lock(p, signum, withlock)
        if (((p->p_flag & P_TRACED) == 0) && (p->p_sigignore & mask))
                goto psigout;
 
        if (((p->p_flag & P_TRACED) == 0) && (p->p_sigignore & mask))
                goto psigout;
 
-       cur_thread = current_thread();   /* this is a shuttle */
-       cur_act = current_act();
-        
        /* If successful return with ast set */
        sig_thread_act = get_signalthread(p, signum);
 
        /* If successful return with ast set */
        sig_thread_act = get_signalthread(p, signum);
 
@@ -1599,8 +1625,16 @@ psignal_lock(p, signum, withlock)
                 *      Wake up the thread, but don't un-suspend it
                 *      (except for SIGCONT).
                 */
                 *      Wake up the thread, but don't un-suspend it
                 *      (except for SIGCONT).
                 */
-               if (prop & SA_CONT)
-                       (void) task_resume(sig_task);
+               if (prop & SA_CONT) {
+                       if (p->p_flag & P_TTYSLEEP) {
+                               p->p_flag &= ~P_TTYSLEEP;
+                               wakeup(&p->p_siglist);
+                       } else {
+                               (void) task_resume(sig_task);
+                       }
+                       p->p_stat = SRUN;
+               } else if (p->p_stat == SSTOP)
+                       goto psigout;
                goto run;
        } else {
                /*      Default action - varies */
                goto run;
        } else {
                /*      Default action - varies */
@@ -1685,6 +1719,8 @@ psignal_lock(p, signum, withlock)
                         * All other signals wake up the process, but don't
                         * resume it.
                         */
                         * All other signals wake up the process, but don't
                         * resume it.
                         */
+                       if (p->p_stat == SSTOP)
+                               goto psigout;
                        goto run;
                }
        }
                        goto run;
                }
        }
@@ -1723,10 +1759,7 @@ psignal_uthread(thr_act, signum)
        register int s, prop;
        register sig_t action;
        thread_act_t    sig_thread_act;
        register int s, prop;
        register sig_t action;
        thread_act_t    sig_thread_act;
-       thread_t        sig_thread;
        register task_t         sig_task;
        register task_t         sig_task;
-       register thread_t       cur_thread;
-       thread_act_t    cur_act;
        int mask;
        struct uthread *uth;
        kern_return_t kret;
        int mask;
        struct uthread *uth;
        kern_return_t kret;
@@ -1769,7 +1802,7 @@ psignal_uthread(thr_act, signum)
         *      Deliver the signal to the first thread in the task. This
         *      allows single threaded applications which use signals to
         *      be able to be linked with multithreaded libraries.  We have
         *      Deliver the signal to the first thread in the task. This
         *      allows single threaded applications which use signals to
         *      be able to be linked with multithreaded libraries.  We have
-        *      an implicit reference to the current_thread, but need
+        *      an implicit reference to the current thread, but need
         *      an explicit one otherwise.  The thread reference keeps
         *      the corresponding task data structures around too.  This
         *      reference is released by thread_deallocate.
         *      an explicit one otherwise.  The thread reference keeps
         *      the corresponding task data structures around too.  This
         *      reference is released by thread_deallocate.
@@ -1778,10 +1811,7 @@ psignal_uthread(thr_act, signum)
        if (((p->p_flag & P_TRACED) == 0) && (p->p_sigignore & mask))
                goto puthout;
 
        if (((p->p_flag & P_TRACED) == 0) && (p->p_sigignore & mask))
                goto puthout;
 
-       cur_thread = current_thread();   /* this is a shuttle */
-       cur_act = current_act();
-        
-       kret = check_actforsig(sig_task, sig_thread_act, &sig_thread, 1);
+       kret = check_actforsig(sig_task, sig_thread_act, 1);
 
        if (kret != KERN_SUCCESS) {
                error = EINVAL;
 
        if (kret != KERN_SUCCESS) {
                error = EINVAL;
@@ -2004,7 +2034,7 @@ __inline__ void
 sig_lock_to_exit(
        struct proc     *p)
 {
 sig_lock_to_exit(
        struct proc     *p)
 {
-       thread_t        self = current_thread();
+       thread_t        self = current_act();
 
        p->exit_thread = self;
        (void) task_suspend(p->task);
 
        p->exit_thread = self;
        (void) task_suspend(p->task);
@@ -2014,7 +2044,7 @@ __inline__ int
 sig_try_locked(
        struct proc     *p)
 {
 sig_try_locked(
        struct proc     *p)
 {
-       thread_t        self = current_thread();
+       thread_t        self = current_act();
 
        while (p->sigwait || p->exit_thread) {
                if (p->exit_thread) {
 
        while (p->sigwait || p->exit_thread) {
                if (p->exit_thread) {
@@ -2022,7 +2052,7 @@ sig_try_locked(
                                /*
                                 * Already exiting - no signals.
                                 */
                                /*
                                 * Already exiting - no signals.
                                 */
-                               thread_abort(current_act());
+                               thread_abort(self);
                        }
                        return(0);
                }
                        }
                        return(0);
                }
@@ -2061,14 +2091,12 @@ issignal(p)
 {
        register int signum, mask, prop, sigbits;
        task_t task = p->task;
 {
        register int signum, mask, prop, sigbits;
        task_t task = p->task;
-       thread_t cur_thread;
        thread_act_t cur_act;
        int     s;
        struct uthread * ut;
        kern_return_t kret;
        struct proc *pp;
 
        thread_act_t cur_act;
        int     s;
        struct uthread * ut;
        kern_return_t kret;
        struct proc *pp;
 
-       cur_thread = current_thread();
        cur_act = current_act();
 
 #if SIGNAL_DEBUG
        cur_act = current_act();
 
 #if SIGNAL_DEBUG
@@ -2130,6 +2158,7 @@ issignal(p)
                                do_bsdexception(EXC_SOFTWARE, EXC_SOFT_SIGNAL, signum);
                                signal_lock(p);
                        } else {
                                do_bsdexception(EXC_SOFTWARE, EXC_SOFT_SIGNAL, signum);
                                signal_lock(p);
                        } else {
+//                             panic("Unsupportef gdb option \n");;
                                pp->si_pid = p->p_pid;
                                pp->si_status = p->p_xstat;
                                pp->si_code = CLD_TRAPPED;
                                pp->si_pid = p->p_pid;
                                pp->si_status = p->p_xstat;
                                pp->si_code = CLD_TRAPPED;
@@ -2174,7 +2203,7 @@ issignal(p)
                                 * clear it, since sig_lock_to_exit will
                                 * wait.
                                 */
                                 * clear it, since sig_lock_to_exit will
                                 * wait.
                                 */
-                               clear_wait(current_thread(), THREAD_INTERRUPTED);
+                               clear_wait(current_act(), THREAD_INTERRUPTED);
                                sig_lock_to_exit(p);
                                /*
                                * Since this thread will be resumed
                                sig_lock_to_exit(p);
                                /*
                                * Since this thread will be resumed
@@ -2191,7 +2220,7 @@ issignal(p)
                        /*
                         *      We may have to quit
                         */
                        /*
                         *      We may have to quit
                         */
-                       if (thread_should_abort(current_thread())) {
+                       if (thread_should_abort(current_act())) {
                                signal_unlock(p);
                                return(0);
                        }
                                signal_unlock(p);
                                return(0);
                        }
@@ -2311,14 +2340,12 @@ CURSIG(p)
 {
        register int signum, mask, prop, sigbits;
        task_t task = p->task;
 {
        register int signum, mask, prop, sigbits;
        task_t task = p->task;
-       thread_t cur_thread;
        thread_act_t cur_act;
        int     s;
        struct uthread * ut;
        int retnum = 0;
            
 
        thread_act_t cur_act;
        int     s;
        struct uthread * ut;
        int retnum = 0;
            
 
-       cur_thread = current_thread();
        cur_act = current_act();
 
        ut = get_bsdthread_info(cur_act);
        cur_act = current_act();
 
        ut = get_bsdthread_info(cur_act);
@@ -2443,6 +2470,7 @@ stop(p)
 {
        p->p_stat = SSTOP;
        p->p_flag &= ~P_WAITED;
 {
        p->p_stat = SSTOP;
        p->p_flag &= ~P_WAITED;
+       if (p->p_pptr->p_stat != SSTOP)
        wakeup((caddr_t)p->p_pptr);
        (void) task_suspend(p->task);   /*XXX*/
 }
        wakeup((caddr_t)p->p_pptr);
        (void) task_suspend(p->task);   /*XXX*/
 }
@@ -2581,6 +2609,48 @@ sigexit_locked(p, signum)
        /* NOTREACHED */
 }
 
        /* NOTREACHED */
 }
 
+
+static int
+filt_sigattach(struct knote *kn)
+{
+       struct proc *p = current_proc();
+
+       kn->kn_ptr.p_proc = p;
+       kn->kn_flags |= EV_CLEAR;               /* automatically set */
+
+       /* XXX lock the proc here while adding to the list? */
+       KNOTE_ATTACH(&p->p_klist, kn);
+
+       return (0);
+}
+
+static void
+filt_sigdetach(struct knote *kn)
+{
+       struct proc *p = kn->kn_ptr.p_proc;
+
+       KNOTE_DETACH(&p->p_klist, kn);
+}
+
+/*
+ * signal knotes are shared with proc knotes, so we apply a mask to 
+ * the hint in order to differentiate them from process hints.  This
+ * could be avoided by using a signal-specific knote list, but probably
+ * isn't worth the trouble.
+ */
+static int
+filt_signal(struct knote *kn, long hint)
+{
+
+       if (hint & NOTE_SIGNAL) {
+               hint &= ~NOTE_SIGNAL;
+
+               if (kn->kn_id == hint)
+                       kn->kn_data++;
+       }
+       return (kn->kn_data != 0);
+}
+
 void
 bsd_ast(thread_act_t thr_act)
 {
 void
 bsd_ast(thread_act_t thr_act)
 {
@@ -2602,7 +2672,7 @@ bsd_ast(thread_act_t thr_act)
                p->p_flag &= ~P_OWEUPC;
        }
 
                p->p_flag &= ~P_OWEUPC;
        }
 
-       if (CHECK_SIGNALS(p, current_thread(), ut)) {
+       if (CHECK_SIGNALS(p, current_act(), ut)) {
                while (signum = issignal(p))
                        postsig(signum);
        }
                while (signum = issignal(p))
                        postsig(signum);
        }