]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_sig.c
xnu-792.18.15.tar.gz
[apple/xnu.git] / bsd / kern / kern_sig.c
index 1492505f3f6de93ccd81dfafe8e2c10e3c13a345..2333f91fbf6dee8c6e5742d7c8586a5cca9c714e 100644 (file)
@@ -612,8 +612,11 @@ execsigs(p, thr_act)
 {
        register struct sigacts *ps = p->p_sigacts;
        register int nc, mask;
-       struct uthread *ut;
+       struct uthread *ut = (struct uthread *)0;
 
+       if (thr_act){
+               ut = (struct uthread *)get_bsdthread_info(thr_act);
+       }
        /*
         * Reset caught signals.  Held signals remain held
         * through p_sigmask (unless they were caught,
@@ -627,7 +630,6 @@ execsigs(p, thr_act)
                        if (nc != SIGCONT)
                                p->p_sigignore |= mask;
                        if (thr_act){
-                               ut = (struct uthread *)get_bsdthread_info(thr_act);
                                ut->uu_siglist &= ~mask;
                                p->p_siglist &= ~mask;
                        } else
@@ -643,6 +645,13 @@ execsigs(p, thr_act)
        ps->ps_sigstk.ss_size = 0;
        ps->ps_sigstk.ss_sp = USER_ADDR_NULL;
        ps->ps_flags = 0;
+       if (thr_act) {
+               ut->uu_sigstk.ss_flags = SA_DISABLE;
+               ut->uu_sigstk.ss_size = 0;
+               ut->uu_sigstk.ss_sp = USER_ADDR_NULL;
+               ut->uu_flag &= ~UT_ALTSTACK;
+       }
+       ps->ps_sigonstack = 0;
 }
 
 /*
@@ -1073,18 +1082,31 @@ int
 sigaltstack(struct proc *p, register struct sigaltstack_args *uap, __unused register_t *retval)
 {
        struct sigacts *psp;
+       struct user_sigaltstack *pstk;
        struct user_sigaltstack ss;
+       struct uthread *uth;
+       int uthsigaltstack = 0;
        int error;
 
+       uth = (struct uthread *)get_bsdthread_info(current_thread());
+       uthsigaltstack = p->p_lflag & P_LTHSIGSTACK;
+
        psp = p->p_sigacts;
-       if ((psp->ps_flags & SAS_ALTSTACK) == 0)
-               psp->ps_sigstk.ss_flags |= SA_DISABLE;
+       if (uthsigaltstack != 0)  {
+               pstk = &uth->uu_sigstk;
+               if ((uth->uu_flag & UT_ALTSTACK) == 0)
+                       uth->uu_sigstk.ss_flags |= SA_DISABLE;
+       } else {
+               pstk = &psp->ps_sigstk;
+               if ((psp->ps_flags & SAS_ALTSTACK) == 0)
+                       psp->ps_sigstk.ss_flags |= SA_DISABLE;
+       }
        if (uap->oss) {
                if (IS_64BIT_PROCESS(p)) {
-                       error = copyout(&psp->ps_sigstk, uap->oss, sizeof(struct user_sigaltstack));
+                       error = copyout(pstk, uap->oss, sizeof(struct user_sigaltstack));
                } else {
                        struct sigaltstack ss32;
-                       sigaltstack_64to32(&psp->ps_sigstk, &ss32);
+                       sigaltstack_64to32(pstk, &ss32);
                        error = copyout(&ss32, uap->oss, sizeof(struct sigaltstack));
                }
                if (error)
@@ -1106,18 +1128,32 @@ sigaltstack(struct proc *p, register struct sigaltstack_args *uap, __unused regi
        }
 
        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;
+               if (uthsigaltstack != 0)  {
+                       /* if we are here we are not in the signal handler ;so no need to check */
+                       if (uth->uu_sigstk.ss_flags & SA_ONSTACK)
+                               return (EINVAL);
+                       uth->uu_flag &= ~UT_ALTSTACK;
+                       uth->uu_sigstk.ss_flags = ss.ss_flags;
+               } else {
+                       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);
        }
 /* 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;
+       if (uthsigaltstack != 0)  {
+               uth->uu_flag |= UT_ALTSTACK;
+               uth->uu_sigstk= ss;
+       } else {
+               psp->ps_flags |= SAS_ALTSTACK;
+               psp->ps_sigstk= ss;
+       }
        return (0);
 }
 
@@ -1465,7 +1501,7 @@ psignal_lock(p, signum, withlock)
        register int signum;
        register int withlock;
 {
-       register int s, prop;
+       register int prop;
        register sig_t action;
        thread_t        sig_thread_act;
        register task_t         sig_task;
@@ -1500,9 +1536,7 @@ psignal_lock(p, signum, withlock)
                return;
        }
 
-        s = splhigh();
         KNOTE(&p->p_klist, NOTE_SIGNAL | signum);
-        splx(s);
 
        /*
         * do not send signals to the process that has the thread
@@ -2638,12 +2672,15 @@ static int
 filt_sigattach(struct knote *kn)
 {
        struct proc *p = current_proc();
+       boolean_t funnel_state;
 
        kn->kn_ptr.p_proc = p;
        kn->kn_flags |= EV_CLEAR;               /* automatically set */
 
-       /* XXX lock the proc here while adding to the list? */
+       /* Take the funnel to protect the proc while adding to the list */
+       funnel_state = thread_funnel_set(kernel_flock, TRUE);
        KNOTE_ATTACH(&p->p_klist, kn);
+       thread_funnel_set(kernel_flock, funnel_state);
 
        return (0);
 }
@@ -2652,8 +2689,11 @@ static void
 filt_sigdetach(struct knote *kn)
 {
        struct proc *p = kn->kn_ptr.p_proc;
+       boolean_t funnel_state;
 
+       funnel_state = thread_funnel_set(kernel_flock, TRUE);
        KNOTE_DETACH(&p->p_klist, kn);
+       thread_funnel_set(kernel_flock, funnel_state);
 }
 
 /*