]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_sig.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / bsd / kern / kern_sig.c
index 9b42ea1e2b92a2b7cf5ea5ffea3a70a1ce4d0cc2..479b1f5e11b7b128d3bb19ea199f07df812174be 100644 (file)
@@ -606,8 +606,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,
@@ -621,7 +624,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
@@ -637,6 +639,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;
 }
 
 /*
@@ -1067,18 +1076,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)
@@ -1100,18 +1122,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);
 }
 
@@ -1459,7 +1495,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;
@@ -1494,9 +1530,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
@@ -2632,12 +2666,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);
 }
@@ -2646,8 +2683,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);
 }
 
 /*