static void sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp *l = curlwp; struct proc *p = l->l_proc; struct sigacts *ps = p->p_sigacts; struct trapframe *tf = l->l_md.md_regs; int sig = ksi->ksi_signo, error; sig_t catcher = SIGACTION(p, sig).sa_handler; struct sigframe_siginfo *fp, frame; int onstack; switch (ps->sa_sigdesc[sig].sd_vers) { case 0: /* FALLTHROUGH */ /* handled by sendsig_sigcontext */ case 1: /* FALLTHROUGH */ /* handled by sendsig_sigcontext */ default: /* unknown version */ printf("sendsig_siginfo: bad version %d\n", ps->sa_sigdesc[sig].sd_vers); sigexit(l, SIGILL); /* NOTREACHED */ case 2: break; } fp = getframe(l, sig, &onstack); --fp; frame.sf_si._info = ksi->ksi_info; frame.sf_uc.uc_link = l->l_ctxlink; frame.sf_uc.uc_sigmask = *mask; frame.sf_uc.uc_flags = _UC_SIGMASK; frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK) ? _UC_SETSTACK : _UC_CLRSTACK; memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack)); sendsig_reset(l, sig); mutex_exit(p->p_lock); cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags); error = copyout(&frame, fp, sizeof(frame)); mutex_enter(p->p_lock); if (error != 0) { /* * Process has trashed its stack; give it an illegal * instruction to halt it in its tracks. */ sigexit(l, SIGILL); /* NOTREACHED */ } tf->tf_r4 = sig; /* "signum" argument for handler */ tf->tf_r5 = (int)&fp->sf_si; /* "sip" argument for handler */ tf->tf_r6 = (int)&fp->sf_uc; /* "ucp" argument for handler */ tf->tf_spc = (int)catcher; tf->tf_r15 = (int)fp; tf->tf_pr = (int)ps->sa_sigdesc[sig].sd_tramp; /* Remember if we're now on the signal stack. */ if (onstack) l->l_sigstk.ss_flags |= SS_ONSTACK; }
static vaddr_t setupstack_siginfo3(const ksiginfo_t *ksi, const sigset_t *mask, int vers, struct lwp *l, struct trapframe *tf, vaddr_t sp, int onstack, vaddr_t handler) { struct trampoline3 tramp; ucontext_t uc; /* * Arguments given to the signal handler. */ tramp.narg = 3; tramp.sig = ksi->ksi_signo; sp -= sizeof(uc); tramp.ucp = sp; sp -= sizeof(siginfo_t); tramp.sip = sp; sp -= sizeof(tramp); /* Save register context. */ uc.uc_flags = _UC_SIGMASK; uc.uc_sigmask = *mask; uc.uc_link = NULL; memset(&uc.uc_stack, 0, sizeof(uc.uc_stack)); cpu_getmcontext(l, &uc.uc_mcontext, &uc.uc_flags); tf->fp = handler; /* Copy the context to the stack. */ if (copyout(&uc, (char *)tramp.ucp, sizeof(uc)) != 0 || copyout(&ksi->ksi_info, (char *)tramp.sip, sizeof(ksi->ksi_info)) != 0 || copyout(&tramp, (char *)sp, sizeof(tramp)) != 0) sigexit(l, SIGILL); return sp; };
void sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask) { struct lwp * const l = curlwp; struct proc * const p = l->l_proc; struct trapframe * const tf = l->l_md.md_utf; struct sigaltstack * const ss = &l->l_sigstk; const struct sigact_sigdesc * const sd = &p->p_sigacts->sa_sigdesc[ksi->ksi_signo]; const uintptr_t handler = (uintptr_t) sd->sd_sigact.sa_handler; const bool onstack_p = (ss->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 && (sd->sd_sigact.sa_flags & SA_ONSTACK) != 0; vaddr_t sp; sp = onstack_p ? ((vaddr_t)ss->ss_sp + ss->ss_size) & -16 : tf->tf_sp; sp -= sizeof(ucontext_t); const vaddr_t ucp = sp; sp -= roundup(sizeof(siginfo_t), 16); const vaddr_t sip = sp; ucontext_t uc; memset(&uc, 0, sizeof(uc)); uc.uc_flags = _UC_SIGMASK; uc.uc_sigmask = *mask; uc.uc_link = l->l_ctxlink; sendsig_reset(l, ksi->ksi_signo); mutex_exit(p->p_lock); cpu_getmcontext(l, &uc.uc_mcontext, &uc.uc_flags); /* * Copy the siginfo and ucontext onto the user's stack. */ int error = copyout(&ksi->ksi_info, (void *)sip, sizeof(ksi->ksi_info)); if (error == 0) { error = copyout(&uc, (void *)ucp, sizeof(uc)); } mutex_enter(p->p_lock); if (error || sd->sd_vers != 2) { /* * Thread has trashed its stack. Blow it away. */ if (error == 0) { printf("pid %d.%d(%s): %p(sig %d): bad version %d\n", p->p_pid, l->l_lid, p->p_comm, __func__, ksi->ksi_signo, sd->sd_vers); } sigexit(l, SIGILL); /* NOTREACHED */ } tf->tf_reg[0] = ksi->ksi_signo; tf->tf_reg[1] = sip; tf->tf_reg[2] = ucp; tf->tf_reg[28] = ucp; /* put in a callee saved register */ tf->tf_sp = sp; tf->tf_lr = sd->sd_tramp; tf->tf_pc = handler; /* * Remember if we'ere now on the signal stack. */ if (onstack_p) ss->ss_flags |= SS_ONSTACK; }