Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
/*
 * Send a signal to process.
 */
void
sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp * const l = curlwp;
	struct proc * const p = l->l_proc;
	struct sigacts * const sa = p->p_sigacts;
	struct trapframe * const tf = l->l_md.md_utf;
	const int signo = ksi->ksi_signo;
	const sig_t catcher = SIGACTION(p, signo).sa_handler;
	bool onstack;
	struct COMPATNAME2(sigframe_siginfo) *sf =
	    cpu_sendsig_getframe(l, signo, &onstack);
	struct COMPATNAME2(sigframe_siginfo) ksf;

	sf--;		// allocate sigframe

	COPY_SIGINFO(&ksf, ksi);
	ksf.sf_uc.uc_flags = _UC_SIGMASK
	    | (l->l_sigstk.ss_flags & SS_ONSTACK ? _UC_SETSTACK : _UC_CLRSTACK);
	ksf.sf_uc.uc_sigmask = *mask;
	UCLINK_SET(&ksf.sf_uc, l->l_ctxlink);
	memset(&ksf.sf_uc.uc_stack, 0, sizeof(ksf.sf_uc.uc_stack));
	sendsig_reset(l, signo);

	mutex_exit(p->p_lock);
	COMPATNAME2(cpu_getmcontext)(l, &ksf.sf_uc.uc_mcontext,
	     &ksf.sf_uc.uc_flags);
	int error = copyout(&ksf, sf, sizeof(ksf));
	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 */
	}

	/*
	 * Set up the registers to directly invoke the signal
	 * handler.  The return address will be set up to point
	 * to the signal trampoline to bounce us back.
	 */
	tf->tf_a0 = signo;
	tf->tf_a1 = (intptr_t)&sf->sf_si;
	tf->tf_a2 = (intptr_t)&sf->sf_uc;

	tf->tf_pc = (intptr_t)catcher;
	tf->tf_sp = (intptr_t)sf;
	tf->tf_ra = (intptr_t)sa->sa_sigdesc[signo].sd_tramp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
Ejemplo n.º 3
0
/*
 * Stack is set up to allow sigcode stored
 * in u. to call routine, followed by kcall
 * to sigreturn routine below.  After sigreturn
 * resets the signal mask, the stack, and the
 * frame pointer, it returns to the user
 * specified pc, psl.
 */
static void
sendsig_sigcontext(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_info._signo;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sigframe_sigcontext *fp, frame;
	int onstack, error;

	fp = getframe(l, sig, &onstack);
	--fp;

	/* Save register context. */
	frame.sf_sc.sc_ssr = tf->tf_ssr;
	frame.sf_sc.sc_spc = tf->tf_spc;
	frame.sf_sc.sc_pr = tf->tf_pr;
	frame.sf_sc.sc_r15 = tf->tf_r15;
	frame.sf_sc.sc_r14 = tf->tf_r14;
	frame.sf_sc.sc_r13 = tf->tf_r13;
	frame.sf_sc.sc_r12 = tf->tf_r12;
	frame.sf_sc.sc_r11 = tf->tf_r11;
	frame.sf_sc.sc_r10 = tf->tf_r10;
	frame.sf_sc.sc_r9 = tf->tf_r9;
	frame.sf_sc.sc_r8 = tf->tf_r8;
	frame.sf_sc.sc_r7 = tf->tf_r7;
	frame.sf_sc.sc_r6 = tf->tf_r6;
	frame.sf_sc.sc_r5 = tf->tf_r5;
	frame.sf_sc.sc_r4 = tf->tf_r4;
	frame.sf_sc.sc_r3 = tf->tf_r3;
	frame.sf_sc.sc_r2 = tf->tf_r2;
	frame.sf_sc.sc_r1 = tf->tf_r1;
	frame.sf_sc.sc_r0 = tf->tf_r0;
	frame.sf_sc.sc_expevt = tf->tf_expevt;

	/* Save signal stack. */
	frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	frame.sf_sc.sc_mask = *mask;

	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	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 */
	}

	/*
	 * Build context to run handler in.  We invoke the handler
	 * directly, only returning via the trampoline.
	 */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		tf->tf_pr = (int)p->p_sigctx.ps_sigcode;
		break;

	case 1:
		tf->tf_pr = (int)ps->sa_sigdesc[sig].sd_tramp;
		break;

	default:
		/* Don't know what trampoline version; kill it. */
		printf("sendsig_sigcontext: bad version %d\n",
		       ps->sa_sigdesc[sig].sd_vers);
		sigexit(l, SIGILL);
	}

	tf->tf_r4 = sig;
	tf->tf_r5 = ksi->ksi_code;
	tf->tf_r6 = (int)&fp->sf_sc;
 	tf->tf_spc = (int)catcher;
	tf->tf_r15 = (int)fp;

	/* Remember if we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
Ejemplo n.º 4
0
void
linux32_rt_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct trapframe *tf;
	struct linux32_rt_sigframe *fp, frame;
	int onstack, error;
	linux32_siginfo_t *lsi;
	int sig = ksi->ksi_signo;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sigaltstack *sas = &l->l_sigstk;

	tf = l->l_md.md_regs;
	/* Do we need to jump onto the signal stack? */
	onstack = (sas->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;


	/* Allocate space for the signal handler context. */
	if (onstack)
		fp = (struct linux32_rt_sigframe *)((char *)sas->ss_sp +
		    sas->ss_size);
	else
		fp = (struct linux32_rt_sigframe *)tf->tf_rsp;
	fp--;

	/* Build stack frame for signal trampoline. */
	NETBSD32PTR32(frame.sf_handler, catcher);
	frame.sf_sig = native_to_linux32_signo[sig];
	NETBSD32PTR32(frame.sf_sip, &fp->sf_si);
	NETBSD32PTR32(frame.sf_ucp, &fp->sf_uc);

	DPRINTF(("rt: onstack = %d, fp = %p sig = %d rip = 0x%lx\n",
	    onstack, fp, sig, tf->tf_rip));

	lsi = &frame.sf_si;
	(void)memset(lsi, 0, sizeof(frame.sf_si));
	lsi->lsi_errno = native_to_linux32_errno[ksi->ksi_errno];
	lsi->lsi_code = native_to_linux_si_code(ksi->ksi_code);
	lsi->lsi_signo = frame.sf_sig;
	switch (lsi->lsi_signo) {
	case LINUX32_SIGILL:
	case LINUX32_SIGFPE:
	case LINUX32_SIGSEGV:
	case LINUX32_SIGBUS:
	case LINUX32_SIGTRAP:
		NETBSD32PTR32(lsi->lsi_addr, ksi->ksi_addr);
		break;
	case LINUX32_SIGCHLD:
		lsi->lsi_uid = ksi->ksi_uid;
		lsi->lsi_pid = ksi->ksi_pid;
		lsi->lsi_utime = ksi->ksi_utime;
		lsi->lsi_stime = ksi->ksi_stime;
		lsi->lsi_status = native_to_linux_si_status(ksi->ksi_code,
		    ksi->ksi_status);
		break;
	case LINUX32_SIGIO:
		lsi->lsi_band = ksi->ksi_band;
		lsi->lsi_fd = ksi->ksi_fd;
		break;
	default:
		lsi->lsi_uid = ksi->ksi_uid;
		lsi->lsi_pid = ksi->ksi_pid;
		if (lsi->lsi_signo == LINUX32_SIGALRM ||
		    lsi->lsi_signo >= LINUX32_SIGRTMIN)
			NETBSD32PTR32(lsi->lsi_value.sival_ptr,
			     ksi->ksi_value.sival_ptr);
		break;
	}

	/* Save register context. */
	linux32_save_ucontext(l, tf, mask, sas, &frame.sf_uc);
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	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 */
	}

	/*
	 * Build context to run handler in.
	 */
	tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff;
	tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff;
	tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff;
	tf->tf_rip = (((long)p->p_sigctx.ps_sigcode) +
	    (linux32_rt_sigcode - linux32_sigcode)) & 0xffffffff;
	tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL) & 0xffffffff;
	tf->tf_rflags &= ~PSL_CLEARSIG & 0xffffffff;
	tf->tf_rsp = (long)fp & 0xffffffff;
	tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		sas->ss_flags |= SS_ONSTACK;

	return;
}
Ejemplo n.º 5
0
void
linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	const int sig = ksi->ksi_signo;
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct trapframe *tf;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct linux_sigregs frame;
	struct linux_pt_regs linux_regs;
	struct linux_sigcontext sc;
	register_t fp;
	int onstack, error;
	int i;

	tf = trapframe(l);

	/*
	 * Do we need to jump onto the signal stack?
	 */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/*
	 * Signal stack is broken (see at the end of linux_sigreturn), so we do
	 * not use it yet. XXX fix this.
	 */
	onstack=0;

	/*
	 * Allocate space for the signal handler context.
	 */
	if (onstack) {
		fp = (register_t)
		    ((char *)l->l_sigstk.ss_sp +
		    l->l_sigstk.ss_size);
	} else {
		fp = tf->tf_fixreg[1];
	}
#ifdef DEBUG_LINUX
	printf("fp at start of linux_sendsig = %x\n", fp);
#endif
	fp -= sizeof(struct linux_sigregs);
	fp &= ~0xf;

	/*
	 * Prepare a sigcontext for later.
	 */
	memset(&sc, 0, sizeof sc);
	sc.lsignal = (int)native_to_linux_signo[sig];
	sc.lhandler = (unsigned long)catcher;
	native_to_linux_old_extra_sigset(&sc.lmask, &sc._unused[3], mask);
	sc.lregs = (struct linux_pt_regs*)fp;

	/*
	 * Setup the signal stack frame as Linux does it in
	 * arch/ppc/kernel/signal.c:setup_frame()
	 *
	 * Save register context.
	 */
	for (i = 0; i < 32; i++)
		linux_regs.lgpr[i] = tf->tf_fixreg[i];
	linux_regs.lnip = tf->tf_srr0;
	linux_regs.lmsr = tf->tf_srr1 & PSL_USERSRR1;
	linux_regs.lorig_gpr3 = tf->tf_fixreg[3]; /* XXX Is that right? */
	linux_regs.lctr = tf->tf_ctr;
	linux_regs.llink = tf->tf_lr;
	linux_regs.lxer = tf->tf_xer;
	linux_regs.lccr = tf->tf_cr;
	linux_regs.lmq = 0;  			/* Unused, 601 only */
	linux_regs.ltrap = tf->tf_exc;
	linux_regs.ldar = tf->tf_dar;
	linux_regs.ldsisr = tf->tf_dsisr;
	linux_regs.lresult = 0;

	memset(&frame, 0, sizeof(frame));
	memcpy(&frame.lgp_regs, &linux_regs, sizeof(linux_regs));

#ifdef PPC_HAVE_FPU
	fpu_save();
#endif
	memcpy(&frame.lfp_regs, curpcb->pcb_fpu.fpreg, sizeof(frame.lfp_regs));

	/*
	 * Copy Linux's signal trampoline on the user stack It should not
	 * be used, but Linux binaries might expect it to be there.
	 */
	frame.ltramp[0] = 0x38997777; /* li r0, 0x7777 */
	frame.ltramp[1] = 0x44000002; /* sc */

	/*
	 * Move it to the user stack
	 * There is a little trick here, about the LINUX_ABIGAP: the
	 * linux_sigreg structure has a 56 int gap to support rs6000/xcoff
	 * binaries. But the Linux kernel seems to do without it, and it
	 * just skip it when building the stack frame. Hence the LINUX_ABIGAP.
	 */
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	error = copyout(&frame, (void *)fp, sizeof (frame) - LINUX_ABIGAP);

	if (error != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		mutex_enter(p->p_lock);
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/*
	 * Add a sigcontext on the stack
	 */
	fp -= sizeof(struct linux_sigcontext);
	error = copyout(&sc, (void *)fp, sizeof (struct linux_sigcontext));
	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 */
	}

	/*
	 * Set the registers according to how the Linux process expects them.
	 * "Mind the gap" Linux expects a gap here.
	 */
	tf->tf_fixreg[1] = fp - LINUX__SIGNAL_FRAMESIZE;
	tf->tf_lr = (int)catcher;
	tf->tf_fixreg[3] = (int)native_to_linux_signo[sig];
	tf->tf_fixreg[4] = fp;
	tf->tf_srr0 = (int)p->p_sigctx.ps_sigcode;

#ifdef DEBUG_LINUX
	printf("fp at end of linux_sendsig = %x\n", fp);
#endif
	/*
	 * Remember that we're now on the signal stack.
	 */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
#ifdef DEBUG_LINUX
	printf("linux_sendsig: exiting. fp=0x%lx\n",(long)fp);
#endif
}
Ejemplo n.º 6
0
/*
 * Send an interrupt to process.
 */
void
sendsig_sigcontext(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 frame *frame = (struct frame *)l->l_md.md_regs;
	int onstack, error;
	int sig = ksi->ksi_signo;
	u_long code = KSI_TRAPCODE(ksi);
	struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), kf;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	short ft = frame->f_format;

	fp--;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n",
		    p->p_pid, sig, &onstack, fp, &fp->sf_sc, ft);
#endif

	/* Build stack frame for signal trampoline. */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		kf.sf_ra = (int)p->p_sigctx.ps_sigcode;
		break;

	case 1:
		kf.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp;
		break;

	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}

	kf.sf_signum = sig;
	kf.sf_code = code;
	kf.sf_scp = &fp->sf_sc;

	/*
	 * Save necessary hardware state.  Currently this includes:
	 *	- general registers
	 *	- original exception frame (if not a "normal" frame)
	 *	- FP coprocessor state
	 */
	kf.sf_state.ss_flags = SS_USERREGS;
	memcpy(kf.sf_state.ss_frame.f_regs, frame->f_regs,
	    sizeof(frame->f_regs));
	if (ft >= FMT4) {
#ifdef DEBUG
		if (ft > 15 || exframesize[ft] < 0)
			panic("sendsig: bogus frame type");
#endif
		kf.sf_state.ss_flags |= SS_RTEFRAME;
		kf.sf_state.ss_frame.f_format = frame->f_format;
		kf.sf_state.ss_frame.f_vector = frame->f_vector;
		memcpy(&kf.sf_state.ss_frame.F_u, &frame->F_u,
		    (size_t) exframesize[ft]);
		/*
		 * Leave an indicator that we need to clean up the kernel
		 * stack.  We do this by setting the "pad word" above the
		 * hardware stack frame to the amount the stack must be
		 * adjusted by.
		 *
		 * N.B. we increment rather than just set f_stackadj in
		 * case we are called from syscall when processing a
		 * sigreturn.  In that case, f_stackadj may be non-zero.
		 */
		frame->f_stackadj += exframesize[ft];
		frame->f_format = frame->f_vector = 0;
#ifdef DEBUG
		if (sigdebug & SDB_FOLLOW)
			printf("sendsig(%d): copy out %d of frame %d\n",
			    p->p_pid, exframesize[ft], ft);
#endif
	}

	if (fputype) {
		kf.sf_state.ss_flags |= SS_FPSTATE;
		m68881_save(&kf.sf_state.ss_fpstate);
	}
#ifdef DEBUG
	if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_state.ss_fpstate)
		printf("sendsig(%d): copy out FP state (%x) to %p\n",
		    p->p_pid, *(u_int *)&kf.sf_state.ss_fpstate,
		    &kf.sf_state.ss_fpstate);
#endif

	/* Build the signal context to be used by sigreturn. */
	kf.sf_sc.sc_sp = frame->f_regs[SP];
	kf.sf_sc.sc_fp = frame->f_regs[A6];
	kf.sf_sc.sc_ap = (int)&fp->sf_state;
	kf.sf_sc.sc_pc = frame->f_pc;
	kf.sf_sc.sc_ps = frame->f_sr;

	/* Save signal stack. */
	kf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	kf.sf_sc.sc_mask = *mask;

#ifdef COMPAT_13
	/*
	 * XXX We always have to save an old style signal mask because
	 * XXX we might be delivering a signal to a process which will
	 * XXX escape from the signal in a non-standard way and invoke
	 * XXX sigreturn() directly.
	 */
	native_sigset_to_sigset13(mask, &kf.sf_sc.__sc_mask13);
#endif
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	error = copyout(&kf, fp, sizeof(kf));
	mutex_enter(p->p_lock);

	if (error != 0) {
#ifdef DEBUG
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig(%d): copyout failed on sig %d\n",
			    p->p_pid, sig);
#endif
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n",
		    p->p_pid, sig, kf.sf_scp, fp,
		    kf.sf_sc.sc_sp, kf.sf_sc.sc_ap);
#endif

	buildcontext(l, catcher, fp);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig(%d): sig %d returns\n",
		    p->p_pid, sig);
#endif
}
/*
 * Send a signal to process.
 */
void
sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *returnmask)
{
	int sig = ksi->ksi_signo;
	struct lwp * const l = curlwp;
	struct proc * const p = l->l_proc;
	struct sigacts * const ps = p->p_sigacts;
	struct pcb * const pcb = lwp_getpcb(l);
	int onstack, error;
	struct sigcontext *scp = getframe(l, sig, &onstack);
	struct sigcontext ksc;
	struct trapframe * const tf = l->l_md.md_utf;
	sig_t catcher = SIGACTION(p, sig).sa_handler;

#if !defined(__mips_o32)
	if (p->p_md.md_abi != _MIPS_BSD_API_O32)
		sigexit(l, SIGILL);
#endif

	scp--;

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW) ||
	    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
		printf("sendsig(%d): sig %d ssp %p scp %p\n",
		       p->p_pid, sig, &onstack, scp);
#endif

	/* Build stack frame for signal trampoline. */
	ksc.sc_pc = tf->tf_regs[_R_PC];
	ksc.mullo = tf->tf_regs[_R_MULLO];
	ksc.mulhi = tf->tf_regs[_R_MULHI];

	/* Save register context. */
	ksc.sc_regs[_R_ZERO] = 0xACEDBADE;		/* magic number */
#if defined(__mips_o32)
	memcpy(&ksc.sc_regs[1], &tf->tf_regs[1],
	    sizeof(ksc.sc_regs) - sizeof(ksc.sc_regs[0]));
#else
	for (size_t i = 1; i < 32; i++)
		ksc.sc_regs[i] = tf->tf_regs[i];
#endif

	/* Save the FP state, if necessary, then copy it. */
	ksc.sc_fpused = fpu_used_p();
#if !defined(NOFPU)
	if (ksc.sc_fpused) {
		/* if FPU has current state, save it first */
		fpu_save();
	}
#endif
	*(struct fpreg *)ksc.sc_fpregs = *(struct fpreg *)&pcb->pcb_fpregs;

	/* Save signal stack. */
	ksc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	ksc.sc_mask = *returnmask;

#if defined(COMPAT_13) || defined(COMPAT_ULTRIX)
	/*
	 * XXX We always have to save an old style signal mask because
	 * XXX we might be delivering a signal to a process which will
	 * XXX escape from the signal in a non-standard way and invoke
	 * XXX sigreturn() directly.
	 */
	native_sigset_to_sigset13(returnmask, &ksc.__sc_mask13);
#endif

	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	error = copyout(&ksc, (void *)scp, sizeof(ksc));
	mutex_enter(p->p_lock);

	if (error != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		if ((sigdebug & SDB_FOLLOW) ||
		    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
			printf("sendsig(%d): copyout failed on sig %d\n",
			    p->p_pid, sig);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/*
	 * Set up the registers to directly invoke the signal
	 * handler.  The return address will be set up to point
	 * to the signal trampoline to bounce us back.
	 */
	tf->tf_regs[_R_A0] = sig;
	tf->tf_regs[_R_A1] = ksi->ksi_trap;
	tf->tf_regs[_R_A2] = (intptr_t)scp;
	tf->tf_regs[_R_A3] = (intptr_t)catcher;		/* XXX ??? */

	tf->tf_regs[_R_PC] = (intptr_t)catcher;
	tf->tf_regs[_R_T9] = (intptr_t)catcher;
	tf->tf_regs[_R_SP] = (intptr_t)scp;

	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		tf->tf_regs[_R_RA] = (intptr_t)p->p_sigctx.ps_sigcode;
		break;
#ifdef COMPAT_16
	case 1:
		tf->tf_regs[_R_RA] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp;
		break;
#endif
	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW) ||
	    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
		printf("sendsig(%d): sig %d returns\n",
		       p->p_pid, sig);
#endif
}
Ejemplo n.º 8
0
static void
netbsd32_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;
	int onstack;
	int sig = ksi->ksi_signo;
	ucontext32_t uc;
	struct sparc32_sigframe_siginfo *fp;
	siginfo32_t si32;	
	netbsd32_intptr_t catcher;
	struct trapframe64 *tf = l->l_md.md_tf;
	struct rwindow32 *oldsp, *newsp;
	register32_t sp;
	int ucsz, error;

	/* Need to attempt to zero extend this 32-bit pointer */
	oldsp = (struct rwindow32*)(u_long)(u_int)tf->tf_out[6];
	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context. */
	if (onstack)
		fp = (struct sparc32_sigframe_siginfo *)
		    ((char *)l->l_sigstk.ss_sp +
					  l->l_sigstk.ss_size);
	else
		fp = (struct sparc32_sigframe_siginfo *)oldsp;
	fp = (struct sparc32_sigframe_siginfo*)((u_long)(fp - 1) & ~7);

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	memset(&uc, 0, sizeof uc);
	uc.uc_flags = _UC_SIGMASK |
		((l->l_sigstk.ss_flags & SS_ONSTACK)
			? _UC_SETSTACK : _UC_CLRSTACK);
	uc.uc_sigmask = *mask;
	uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink;

	sendsig_reset(l, sig);

	/*
	 * Now copy the stack contents out to user space.
	 * We need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 * Since we're calling the handler directly, allocate a full size
	 * C stack frame.
	 */
	mutex_exit(p->p_lock);
	cpu_getmcontext32(l, &uc.uc_mcontext, &uc.uc_flags);
	netbsd32_si_to_si32(&si32, (const siginfo_t *)&ksi->ksi_info);
	ucsz = (int)(intptr_t)&uc.__uc_pad - (int)(intptr_t)&uc;
	newsp = (struct rwindow32*)((intptr_t)fp - sizeof(struct frame32));
	sp = NETBSD32PTR32I(oldsp);
	error = (copyout(&si32, &fp->sf_si, sizeof si32) ||
	    copyout(&uc, &fp->sf_uc, ucsz) ||
	    copyout(&sp, &newsp->rw_in[6], sizeof(sp)));
	mutex_enter(p->p_lock);

	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	switch (ps->sa_sigdesc[sig].sd_vers) {
	default:
		/* Unsupported trampoline version; kill the process. */
		sigexit(l, SIGILL);
	case 2:
		/*
		 * Arrange to continue execution at the user's handler.
		 * It needs a new stack pointer, a return address and
		 * three arguments: (signo, siginfo *, ucontext *).
		 */
		catcher = (intptr_t)SIGACTION(p, sig).sa_handler;
		tf->tf_pc = catcher;
		tf->tf_npc = catcher + 4;
		tf->tf_out[0] = sig;
		tf->tf_out[1] = (intptr_t)&fp->sf_si;
		tf->tf_out[2] = (intptr_t)&fp->sf_uc;
		tf->tf_out[6] = (intptr_t)newsp;
		tf->tf_out[7] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp - 8;
		break;
	}

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
Ejemplo n.º 9
0
void
linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
    const int sig = ksi->ksi_signo;
    struct lwp *l = curlwp;
    struct proc *p = l->l_proc;
    struct sigacts *ps = p->p_sigacts;
    struct linux_rt_sigframe *fp;
    struct frame *f;
    int i, onstack, error;
    struct linux_rt_sigframe sf;

#ifdef DEBUG_LINUX
    printf("linux_sendsig()\n");
#endif /* DEBUG_LINUX */
    f = (struct frame *)l->l_md.md_regs;

    /*
     * Do we need to jump onto the signal stack?
     */
    onstack =
        (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
        (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

    /*
     * Allocate space for the signal handler context.
     */
    if (onstack)
        panic("linux_sendsig: onstack notyet");
    else
        fp = (struct linux_rt_sigframe *)(u_int32_t)f->f_regs[_R_SP];

    /*
     * Build stack frame for signal trampoline.
     */
    memset(&sf, 0, sizeof sf);

#if LINUX_SYS_rt_sigreturn > 127
#error LINUX_SYS_rt_sigreturn does not fit in a 16-bit opcode.
#endif

    /*
     * This is the signal trampoline used by Linux, we don't use it,
     * but we set it up in case an application expects it to be there.
     *
     * 	mov	r8, LINUX_SYS_rt_sigreturn
     * 	scall
     */
    sf.lrs_code = (0x3008d733 | LINUX_SYS_rt_sigreturn << 20);

    /*
     * The user context.
     */
    native_to_linux_sigset(&sf.lrs_uc.luc_sigmask, mask);
    sf.lrs_uc.luc_flags = 0;
    sf.lrs_uc.luc_link = NULL;

    /* This is used regardless of SA_ONSTACK in Linux AVR32. */
    sf.lrs_uc.luc_stack.ss_sp = l->l_sigstk.ss_sp;
    sf.lrs_uc.luc_stack.ss_size = l->l_sigstk.ss_size;
    sf.lrs_uc.luc_stack.ss_flags = 0;
    if (l->l_sigstk.ss_flags & SS_ONSTACK)
        sf.lrs_uc.luc_stack.ss_flags |= LINUX_SS_ONSTACK;
    if (l->l_sigstk.ss_flags & SS_DISABLE)
        sf.lrs_uc.luc_stack.ss_flags |= LINUX_SS_DISABLE;
    memcpy(sf.lrs_uc.luc_mcontext.lsc_regs, f->f_regs,
           sizeof(sf.lrs_uc.luc_mcontext.lsc_regs));
    sendsig_reset(l, sig);

    /*
     * Install the sigframe onto the stack.
     */
    fp -= sizeof(struct linux_rt_sigframe);
    mutex_exit(p->p_lock);
    error = copyout(&sf, fp, sizeof(sf));
    mutex_enter(p->p_lock);

    if (error != 0) {
        /*
         * Process has trashed its stack; give it an illegal
         * instruction to halt it in its tracks.
         */
#ifdef DEBUG_LINUX
        printf("linux_sendsig: stack trashed\n");
#endif /* DEBUG_LINUX */
        sigexit(l, SIGILL);
        /* NOTREACHED */
    }

#ifdef DEBUG_LINUX
    printf("sigcontext is at %p\n", &fp->lrs_sc);
#endif /* DEBUG_LINUX */

    /* Set up the registers to return to sigcode. */
    f->f_regs[_R_SP] = (register_t)fp;
    f->f_regs[_R_R12] = native_to_linux_signo[sig];
    f->f_regs[_R_R11] = 0;
    f->f_regs[_R_R10] = (register_t)&fp->lrs_uc;
    f->f_regs[_R_PC] = (register_t)SIGACTION(p, sig).sa_handler;

#define RESTORER(p, sig) \
	(p->p_sigacts->sa_sigdesc[(sig)].sd_tramp)

    if (ps->sa_sigdesc[sig].sd_vers != 0)
        f->f_regs[_R_LR] = (register_t)RESTORER(p, sig);
    else
        panic("linux_sendsig: SA_RESTORER");

    /* Remember that we're now on the signal stack. */
    if (onstack)
        l->l_sigstk.ss_flags |= SS_ONSTACK;

    return;
}
static void
netbsd32_sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct trapframe *tf;
	int sig = ksi->ksi_signo;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct netbsd32_sigframe_sigcontext *fp, frame;
	int onstack, error;
	struct sigacts *ps = p->p_sigacts;

	tf = l->l_md.md_regs;

	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context. */
	if (onstack)
		fp = (struct netbsd32_sigframe_sigcontext *)
		    ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		fp = (struct netbsd32_sigframe_sigcontext *)tf->tf_rsp;
	fp--;

	/* Build stack frame for signal trampoline. */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:
		frame.sf_ra = (uint32_t)(u_long)p->p_sigctx.ps_sigcode;
		break;
	case 1:
		frame.sf_ra = (uint32_t)(u_long)ps->sa_sigdesc[sig].sd_tramp;
		break;
	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}
	frame.sf_signum = sig;
	frame.sf_code = ksi->ksi_trap;
	frame.sf_scp = (uint32_t)(u_long)&fp->sf_sc;

	frame.sf_sc.sc_ds = tf->tf_ds;
	frame.sf_sc.sc_es = tf->tf_es;
	frame.sf_sc.sc_fs = tf->tf_fs;
	frame.sf_sc.sc_gs = tf->tf_gs;

	frame.sf_sc.sc_eflags = tf->tf_rflags;
	frame.sf_sc.sc_edi = tf->tf_rdi;
	frame.sf_sc.sc_esi = tf->tf_rsi;
	frame.sf_sc.sc_ebp = tf->tf_rbp;
	frame.sf_sc.sc_ebx = tf->tf_rbx;
	frame.sf_sc.sc_edx = tf->tf_rdx;
	frame.sf_sc.sc_ecx = tf->tf_rcx;
	frame.sf_sc.sc_eax = tf->tf_rax;
	frame.sf_sc.sc_eip = tf->tf_rip;
	frame.sf_sc.sc_cs = tf->tf_cs;
	frame.sf_sc.sc_esp = tf->tf_rsp;
	frame.sf_sc.sc_ss = tf->tf_ss;
	frame.sf_sc.sc_trapno = tf->tf_trapno;
	frame.sf_sc.sc_err = tf->tf_err;

	/* Save signal stack. */
	frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	frame.sf_sc.sc_mask = *mask;

	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	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 */
	}

	/*
	 * Build context to run handler in.
	 */
	tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL);
	tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL);
	tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL);
	tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL);

	/* Ensure FP state is reset, if FP is used. */
	l->l_md.md_flags &= ~MDL_USEDFPU;

	tf->tf_rip = (uint64_t)catcher;
	tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL);
	tf->tf_rflags &= ~PSL_CLEARSIG;
	tf->tf_rsp = (uint64_t)fp;
	tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
	if ((vaddr_t)catcher >= VM_MAXUSER_ADDRESS32) {
		/*
		 * process has given an invalid address for the
		 * handler. Stop it, but do not do it before so
		 * we can return the right info to userland (or in core dump)
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
}
Ejemplo n.º 11
0
/*
 * Send an interrupt to process.
 *
 * Stack is set up to allow sigcode stored
 * in u. to call routine. After the handler is
 * done svr4 will call setcontext for us
 * with the user context we just set up, and we
 * will return to the user pc, psl.
 */
void
svr4_32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	int sig = ksi->ksi_signo;
	register struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	register struct trapframe64 *tf;
	struct svr4_32_sigframe *fp, frame;
	int onstack, error;
	vaddr_t oldsp, newsp, addr;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	sigset_t tmask;

	tf = (struct trapframe64 *)l->l_md.md_tf;
	oldsp = tf->tf_out[6];

	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/*
	 * Allocate space for the signal handler context.
	 */
	if (onstack)
		fp = (struct svr4_32_sigframe *)((char *)l->l_sigstk.ss_sp +
						l->l_sigstk.ss_size);
	else
		fp = (struct svr4_32_sigframe *)oldsp;
	fp = (struct svr4_32_sigframe *) ((long) (fp - 1) & ~7);

#ifdef DEBUG
	sigpid = p->p_pid;
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		printf("svr4_32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_uc, (void *)(u_long)oldsp);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
	}
#endif
	/*
	 * Build the argument list for the signal handler.
	 */
	svr4_32_getsiginfo(&frame.sf_si, sig, ksi->ksi_trap,
	    (void *)(u_long)tf->tf_pc);

	/* Build stack frame for signal trampoline. */
	frame.sf_signum = frame.sf_si.si_signo;
	NETBSD32PTR32(frame.sf_sip, &fp->sf_si);
	NETBSD32PTR32(frame.sf_ucp, &fp->sf_uc);
	frame.sf_handler = catcher;

	DPRINTF(("svr4_32_sendsig signum=%d si = %p uc = %p handler = %p\n",
	         frame.sf_signum, frame.sf_sip,
		 frame.sf_ucp, frame.sf_handler));
	/*
	 * Modify the signal context to be used by sigreturn.
	 */
	tmask = *mask;
	sendsig_reset(l, sig);
	frame.sf_uc.uc_mcontext.greg[SVR4_SPARC_SP] = oldsp;
	newsp = (u_long)fp - sizeof(struct rwindow32);
	mutex_exit(p->p_lock);
	svr4_32_getcontext(l, &frame.sf_uc, &tmask);
	write_user_windows();

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK))
	    printf("svr4_32_sendsig: saving sf to %p, setting stack pointer %p to %p\n",
		   fp, &(((struct rwindow32 *)newsp)->rw_in[6]), (void *)(u_long)oldsp);
#endif
	error = (rwindow_save(l) || copyout(&frame, fp, sizeof(frame)) != 0 ||
	    copyout(&oldsp, &((struct rwindow32 *)newsp)->rw_in[6], sizeof(oldsp)));
	mutex_enter(p->p_lock);

	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		mutex_exit(p->p_lock);
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("svr4_32_sendsig: window save or copyout error\n");
		printf("svr4_32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
#ifdef DDB
		Debugger();
#endif
		mutex_enter(p->p_lock);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW) {
		printf("svr4_32_sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_uc);
	}
#endif
	/*
	 * Build context to run handler in.
	 */
	addr = (vaddr_t)p->p_sigctx.ps_sigcode;
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_global[1] = (vaddr_t)catcher;
	tf->tf_out[6] = newsp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("svr4_32_sendsig: about to return to catcher %p thru %p\n", 
		       catcher, (void *)(u_long)addr);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
		mutex_enter(p->p_lock);
	}
#endif
}
Ejemplo n.º 12
0
void
sunos32_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	int sig = ksi->ksi_signo;
	struct lwp *l = curlwp;	/* XXX */
	struct proc *p = l->l_proc;
	struct sunos32_sigframe *fp;
	struct trapframe64 *tf;
	struct rwindow32 *oldsp, *newsp;
	struct sunos32_sigframe sf;
	struct sunos32_sigcontext *scp;
	uint32_t addr, oldsp32;
	int onstack, error; 
	sig_t catcher = SIGACTION(p, sig).sa_handler;

	tf = l->l_md.md_tf;
	/* Need to attempt to zero extend this 32-bit pointer */
	oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
	oldsp32 = (uint32_t)(u_long)oldsp;

	/*
	 * Compute new user stack addresses, subtract off
	 * one signal frame, and align.
	 */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	if (onstack)
		fp = (struct sunos32_sigframe *)
		     ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		fp = (struct sunos32_sigframe *)oldsp;

	fp = (struct sunos32_sigframe *)((u_long)(fp - 1) & ~7);

#ifdef DEBUG
	sigpid = p->p_pid;
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("sunos32_sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
		mutex_enter(p->p_lock);
	}
#endif
	/*
	 * Now set up the signal frame.  We build it in kernel space
	 * and then copy it out.  We probably ought to just build it
	 * directly in user space....
	 */
	sf.sf_signo = sig;
	sf.sf_code = (uint32_t)ksi->ksi_trap;
	scp = &fp->sf_sc;
	if ((u_long)scp >= 0x100000000)
		printf("sunos32_sendsig: sf_scp overflow %p > 0x100000000\n", scp);
	sf.sf_scp = (uint32_t)(u_long)scp;
	sf.sf_addr = 0;			/* XXX */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;
	native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask);
	sf.sf_sc.sc_sp = (u_int)(u_long)oldsp;
	sf.sf_sc.sc_pc = tf->tf_pc;
	sf.sf_sc.sc_npc = tf->tf_npc;
	sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
	sf.sf_sc.sc_g1 = tf->tf_global[1];
	sf.sf_sc.sc_o0 = tf->tf_out[0];

	/*
	 * Put the stack in a consistent state before we whack away
	 * at it.  Note that write_user_windows may just dump the
	 * registers into the pcb; we need them in the process's memory.
	 * We also need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 */
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
	write_user_windows();
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK))
	    printf("sunos32_sendsig: saving sf to %p, setting stack pointer %p to %p\n",
		   fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp);
#endif
	error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) || 
	    copyout((void *)&oldsp32, &(((struct rwindow32 *)newsp)->rw_in[6]), sizeof oldsp32));
	mutex_enter(p->p_lock);
	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		mutex_exit(p->p_lock);
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sunos32_sendsig: window save or copyout error\n");
		printf("sunos32_sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
		mutex_enter(p->p_lock);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW)) {
		printf("sunos32_sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_sc);
	}
#endif
	/*
	 * Arrange to continue execution at the code copied out in exec().
	 * It needs the function to call in %g1, and a new stack pointer.
	 */
	addr = (uint32_t)(u_long)catcher;	/* user does his own trampolining */
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp;
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("sunos32_sendsig: about to return to catcher %p thru %p\n", 
		       catcher, (void *)(u_long)addr);
#ifdef DDB
		if (sigdebug & SDB_DDB) Debugger();
#endif
		mutex_enter(p->p_lock);
	}
#endif
}
Ejemplo n.º 13
0
void
linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	const int sig = ksi->ksi_signo;
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct linux_sigframe *fp;
	struct frame *f;
	int i, onstack, error;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct linux_sigframe sf;

#ifdef DEBUG_LINUX
	printf("linux_sendsig()\n");
#endif /* DEBUG_LINUX */
	f = (struct frame *)l->l_md.md_regs;

	/*
	 * Do we need to jump onto the signal stack?
	 */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/*
	 * Signal stack is broken (see at the end of linux_sigreturn), so we do
	 * not use it yet. XXX fix this.
	 */
	onstack=0;

	/*
	 * Allocate space for the signal handler context.
	 */
	if (onstack)
		fp = (struct linux_sigframe *)
		    ((uint8_t *)l->l_sigstk.ss_sp
		    + l->l_sigstk.ss_size);
	else
		/* cast for _MIPS_BSD_API == _MIPS_BSD_API_LP32_64CLEAN case */
		fp = (struct linux_sigframe *)(u_int32_t)f->f_regs[_R_SP];

	/*
	 * Build stack frame for signal trampoline.
	 */
	memset(&sf, 0, sizeof sf);

	/*
	 * This is the signal trampoline used by Linux, we don't use it,
	 * but we set it up in case an application expects it to be there
	 */
	sf.lsf_code[0] = 0x24020000;	/* li	v0, __NR_sigreturn	*/
	sf.lsf_code[1] = 0x0000000c;	/* syscall			*/

	native_to_linux_sigset(&sf.lsf_mask, mask);
	for (i=0; i<32; i++) {
		sf.lsf_sc.lsc_regs[i] = f->f_regs[i];
	}
	sf.lsf_sc.lsc_mdhi = f->f_regs[_R_MULHI];
	sf.lsf_sc.lsc_mdlo = f->f_regs[_R_MULLO];
	sf.lsf_sc.lsc_pc = f->f_regs[_R_PC];
	sf.lsf_sc.lsc_status = f->f_regs[_R_SR];
	sf.lsf_sc.lsc_cause = f->f_regs[_R_CAUSE];
	sf.lsf_sc.lsc_badvaddr = f->f_regs[_R_BADVADDR];
	sendsig_reset(l, sig);

	/*
	 * Save signal stack.  XXX broken
	 */
	/* kregs.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK; */

	/*
	 * Install the sigframe onto the stack
	 */
	fp -= sizeof(struct linux_sigframe);
	mutex_exit(p->p_lock);
	error = copyout(&sf, fp, sizeof(sf));
	mutex_enter(p->p_lock);

	if (error != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG_LINUX
		printf("linux_sendsig: stack trashed\n");
#endif /* DEBUG_LINUX */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/* Set up the registers to return to sigcode. */
	f->f_regs[_R_A0] = native_to_linux_signo[sig];
	f->f_regs[_R_A1] = 0;
	f->f_regs[_R_A2] = (unsigned long)&fp->lsf_sc;

#ifdef DEBUG_LINUX
	printf("sigcontext is at %p\n", &fp->lsf_sc);
#endif /* DEBUG_LINUX */

	f->f_regs[_R_SP] = (unsigned long)fp;
	/* Signal trampoline code is at base of user stack. */
	f->f_regs[_R_RA] = (unsigned long)p->p_sigctx.ps_sigcode;
	f->f_regs[_R_T9] = (unsigned long)catcher;
	f->f_regs[_R_PC] = (unsigned long)catcher;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

	return;
}
Ejemplo n.º 14
0
void
linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;
	int onstack, error;
	int sig = ksi->ksi_signo;
	struct linux_rt_sigframe *sfp, sigframe;
	struct linux__fpstate *fpsp, fpstate;
	struct fpreg fpregs;
	struct trapframe *tf = l->l_md.md_regs;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	linux_sigset_t lmask;
	char *sp;

	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
	
	/* Allocate space for the signal handler context. */
	if (onstack)
		sp = ((char *)l->l_sigstk.ss_sp +
		    l->l_sigstk.ss_size);
	else
		sp = (char *)tf->tf_rsp - 128;

	/* 
	 * Save FPU state, if any 
	 */
	if (l->l_md.md_flags & MDP_USEDFPU) {
		sp = (char *)
		    (((long)sp - sizeof(struct linux__fpstate)) & ~0xfUL);
		fpsp = (struct linux__fpstate *)sp;
	} else
		fpsp = NULL;

	/* 
	 * Populate the rt_sigframe 
	 */
	sp = (char *)
	    ((((long)sp - sizeof(struct linux_rt_sigframe)) & ~0xfUL) - 8);
	sfp = (struct linux_rt_sigframe *)sp;

	bzero(&sigframe, sizeof(sigframe));
	if (ps->sa_sigdesc[sig].sd_vers != 0)
		sigframe.pretcode = 
		    (char *)(u_long)ps->sa_sigdesc[sig].sd_tramp;
	else
		sigframe.pretcode = NULL;

	/* 
	 * The user context 
	 */
	sigframe.uc.luc_flags = 0;
	sigframe.uc.luc_link = NULL;

	/* This is used regardless of SA_ONSTACK in Linux */
	sigframe.uc.luc_stack.ss_sp = l->l_sigstk.ss_sp;
	sigframe.uc.luc_stack.ss_size = l->l_sigstk.ss_size;
	sigframe.uc.luc_stack.ss_flags = 0;
	if (l->l_sigstk.ss_flags & SS_ONSTACK)
		sigframe.uc.luc_stack.ss_flags |= LINUX_SS_ONSTACK;
	if (l->l_sigstk.ss_flags & SS_DISABLE)
		sigframe.uc.luc_stack.ss_flags |= LINUX_SS_DISABLE;

	sigframe.uc.luc_mcontext.r8 = tf->tf_r8;
	sigframe.uc.luc_mcontext.r9 = tf->tf_r9;
	sigframe.uc.luc_mcontext.r10 = tf->tf_r10;
	sigframe.uc.luc_mcontext.r11 = tf->tf_r11;
	sigframe.uc.luc_mcontext.r12 = tf->tf_r12;
	sigframe.uc.luc_mcontext.r13 = tf->tf_r13;
	sigframe.uc.luc_mcontext.r14 = tf->tf_r14;
	sigframe.uc.luc_mcontext.r15 = tf->tf_r15;
	sigframe.uc.luc_mcontext.rdi = tf->tf_rdi;
	sigframe.uc.luc_mcontext.rsi = tf->tf_rsi;
	sigframe.uc.luc_mcontext.rbp = tf->tf_rbp;
	sigframe.uc.luc_mcontext.rbx = tf->tf_rbx;
	sigframe.uc.luc_mcontext.rdx = tf->tf_rdx;
	sigframe.uc.luc_mcontext.rax = tf->tf_rax;
	sigframe.uc.luc_mcontext.rcx = tf->tf_rcx;
	sigframe.uc.luc_mcontext.rsp = tf->tf_rsp;
	sigframe.uc.luc_mcontext.rip = tf->tf_rip;
	sigframe.uc.luc_mcontext.eflags = tf->tf_rflags;
	sigframe.uc.luc_mcontext.cs = tf->tf_cs;
	sigframe.uc.luc_mcontext.gs = tf->tf_gs;
	sigframe.uc.luc_mcontext.fs = tf->tf_fs;
	sigframe.uc.luc_mcontext.err = tf->tf_err;
	sigframe.uc.luc_mcontext.trapno = tf->tf_trapno;
	native_to_linux_sigset(&lmask, mask);
	sigframe.uc.luc_mcontext.oldmask = lmask.sig[0];
	sigframe.uc.luc_mcontext.cr2 = (long)l->l_addr->u_pcb.pcb_onfault;
	sigframe.uc.luc_mcontext.fpstate = fpsp;
	native_to_linux_sigset(&sigframe.uc.luc_sigmask, mask);

	/* 
	 * the siginfo structure
	 */
	sigframe.info.lsi_signo = native_to_linux_signo[sig];
	sigframe.info.lsi_errno = native_to_linux_errno[ksi->ksi_errno];
	sigframe.info.lsi_code = native_to_linux_si_code(ksi->ksi_code);

	/* XXX This is a rought conversion, taken from i386 code */
	switch (sigframe.info.lsi_signo) {
	case LINUX_SIGILL:
	case LINUX_SIGFPE:
	case LINUX_SIGSEGV:
	case LINUX_SIGBUS:
	case LINUX_SIGTRAP:
		sigframe.info._sifields._sigfault._addr = ksi->ksi_addr;
		break;
	case LINUX_SIGCHLD:
		sigframe.info._sifields._sigchld._pid = ksi->ksi_pid;
		sigframe.info._sifields._sigchld._uid = ksi->ksi_uid;
		sigframe.info._sifields._sigchld._utime = ksi->ksi_utime;
		sigframe.info._sifields._sigchld._stime = ksi->ksi_stime;

		if (WCOREDUMP(ksi->ksi_status)) {
			sigframe.info.lsi_code = LINUX_CLD_DUMPED;
			sigframe.info._sifields._sigchld._status =
			    _WSTATUS(ksi->ksi_status);
		} else if (_WSTATUS(ksi->ksi_status)) {
			sigframe.info.lsi_code = LINUX_CLD_KILLED;
			sigframe.info._sifields._sigchld._status =
			    _WSTATUS(ksi->ksi_status);
		} else {
			sigframe.info.lsi_code = LINUX_CLD_EXITED;
			sigframe.info._sifields._sigchld._status =
			    ((ksi->ksi_status & 0xff00U) >> 8);
		}
		break;
	case LINUX_SIGIO:
		sigframe.info._sifields._sigpoll._band = ksi->ksi_band;
		sigframe.info._sifields._sigpoll._fd = ksi->ksi_fd;
		break;
	default:
		sigframe.info._sifields._sigchld._pid = ksi->ksi_pid;
		sigframe.info._sifields._sigchld._uid = ksi->ksi_uid;
		if ((sigframe.info.lsi_signo == LINUX_SIGALRM) ||
		    (sigframe.info.lsi_signo >= LINUX_SIGRTMIN))
			sigframe.info._sifields._timer._sigval.sival_ptr =
			     ksi->ksi_value.sival_ptr;
		break;
	}

	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	error = 0;

	/* 
	 * Save FPU state, if any 
	 */
	if (fpsp != NULL) {
		(void)process_read_fpregs(l, &fpregs);
		bzero(&fpstate, sizeof(fpstate));
		fpstate.cwd = fpregs.fp_fcw;
		fpstate.swd = fpregs.fp_fsw;
		fpstate.twd = fpregs.fp_ftw;
		fpstate.fop = fpregs.fp_fop;
		fpstate.rip = fpregs.fp_rip;
		fpstate.rdp = fpregs.fp_rdp;
		fpstate.mxcsr = fpregs.fp_mxcsr;
		fpstate.mxcsr_mask = fpregs.fp_mxcsr_mask;
		memcpy(&fpstate.st_space, &fpregs.fp_st, 
		    sizeof(fpstate.st_space));
		memcpy(&fpstate.xmm_space, &fpregs.fp_xmm, 
		    sizeof(fpstate.xmm_space));
		error = copyout(&fpstate, fpsp, sizeof(fpstate));
	}

	if (error == 0)
		error = copyout(&sigframe, sp, sizeof(sigframe));

	mutex_enter(p->p_lock);

	if (error != 0) {
		sigexit(l, SIGILL);
		return;
	}	

	linux_buildcontext(l, catcher, sp);
	tf->tf_rdi = sigframe.info.lsi_signo;
	tf->tf_rax = 0;
	tf->tf_rsi = (long)&sfp->info;
	tf->tf_rdx = (long)&sfp->uc;

	/*
	 * Remember we use signal stack
	 */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
	return;
}
/*
 * Send an interrupt to process.
 *
 * Stack is set up to allow sigcode stored
 * in u. to call routine, followed by kcall
 * to sigreturn routine below.  After sigreturn
 * resets the signal mask, the stack, and the
 * frame pointer, it returns to the user
 * specified pc, psl.
 */
void
freebsd_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	int sig = ksi->ksi_signo;
	u_long code = KSI_TRAPCODE(ksi);
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	int onstack, error;
	struct freebsd_sigframe *fp = getframe(l, sig, &onstack), frame;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct trapframe *tf = l->l_md.md_regs;

	fp--;

	/* Build stack frame for signal trampoline. */
	frame.sf_signum = sig;
	frame.sf_code = code;
	frame.sf_scp = &fp->sf_sc;
	frame.sf_addr = (char *)rcr2();
	frame.sf_handler = catcher;

	/* Save context. */
#ifdef VM86
	if (tf->tf_eflags & PSL_VM) {
		frame.sf_sc.sc_gs = tf->tf_vm86_gs;
		frame.sf_sc.sc_fs = tf->tf_vm86_fs;
		frame.sf_sc.sc_es = tf->tf_vm86_es;
		frame.sf_sc.sc_ds = tf->tf_vm86_ds;
		frame.sf_sc.sc_efl = get_vflags(l);
		(*p->p_emul->e_syscall_intern)(p);
	} else
#endif
	{
		frame.sf_sc.sc_gs = tf->tf_gs;
		frame.sf_sc.sc_fs = tf->tf_fs;
		frame.sf_sc.sc_es = tf->tf_es;
		frame.sf_sc.sc_ds = tf->tf_ds;
		frame.sf_sc.sc_efl = tf->tf_eflags;
	}
	frame.sf_sc.sc_edi = tf->tf_edi;
	frame.sf_sc.sc_esi = tf->tf_esi;
	frame.sf_sc.sc_ebp = tf->tf_ebp;
	frame.sf_sc.sc_isp = 0; /* don't have to pass kernel sp to user. */
	frame.sf_sc.sc_ebx = tf->tf_ebx;
	frame.sf_sc.sc_edx = tf->tf_edx;
	frame.sf_sc.sc_ecx = tf->tf_ecx;
	frame.sf_sc.sc_eax = tf->tf_eax;
	frame.sf_sc.sc_eip = tf->tf_eip;
	frame.sf_sc.sc_cs = tf->tf_cs;
	frame.sf_sc.sc_esp = tf->tf_esp;
	frame.sf_sc.sc_ss = tf->tf_ss;

	/* Save signal stack. */
	frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	/* XXX freebsd_osigcontext compat? */
	frame.sf_sc.sc_mask = *mask;

	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	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 */
	}

	buildcontext(l, GUCODEBIG_SEL, p->p_sigctx.ps_sigcode, fp);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
Ejemplo n.º 16
0
void setup_linux_sigframe(struct trapframe *tf, const ksiginfo_t *ksi,
    const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct linux_sigframe *sfp, sigframe;
	int onstack, error;
	int fsize, rndfsize;
	int sig = ksi->ksi_signo;
	extern char linux_sigcode[], linux_esigcode[];

	/* Do we need to jump onto the signal stack? */
	onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
		  (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context.  */
	fsize = sizeof(struct linux_sigframe);
	rndfsize = ((fsize + 15) / 16) * 16;

	if (onstack)
		sfp = (struct linux_sigframe *)
		    ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		sfp = (struct linux_sigframe *)(alpha_pal_rdusp());
	sfp = (struct linux_sigframe *)((char *)sfp - rndfsize);

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && (p->p_pid == sigpid))
		printf("linux_sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
		    sig, &onstack, sfp);
#endif /* DEBUG */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	memset(&sigframe.sf_sc, 0, sizeof(struct linux_sigcontext));
	sigframe.sf_sc.sc_onstack = onstack;
	native_to_linux_old_sigset(&sigframe.sf_sc.sc_mask, mask);
	sigframe.sf_sc.sc_pc = tf->tf_regs[FRAME_PC];
	sigframe.sf_sc.sc_ps = ALPHA_PSL_USERMODE;
	frametoreg(tf, (struct reg *)sigframe.sf_sc.sc_regs);
	sigframe.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp();

	if (l == fpcurlwp) {
		struct pcb *pcb = lwp_getpcb(l);

		alpha_pal_wrfen(1);
		savefpstate(&pcb->pcb_fp);
		alpha_pal_wrfen(0);
		sigframe.sf_sc.sc_fpcr = pcb->pcb_fp.fpr_cr;
		fpcurlwp = NULL;
	}
	/* XXX ownedfp ? etc...? */

	sigframe.sf_sc.sc_traparg_a0 = tf->tf_regs[FRAME_A0];
	sigframe.sf_sc.sc_traparg_a1 = tf->tf_regs[FRAME_A1];
	sigframe.sf_sc.sc_traparg_a2 = tf->tf_regs[FRAME_A2];

	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	error = copyout((void *)&sigframe, (void *)sfp, fsize);
	mutex_enter(p->p_lock);

	if (error != 0) {
#ifdef DEBUG
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig(%d): copyout failed on sig %d\n",
			    p->p_pid, sig);
#endif
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/* Pass pointers to sigcontext in the regs */
	tf->tf_regs[FRAME_A1] = 0;
	tf->tf_regs[FRAME_A2] = (unsigned long)&sfp->sf_sc;

	/* Address of trampoline code.  End up at this PC after mi_switch */
	tf->tf_regs[FRAME_PC] =
	    (u_int64_t)(p->p_psstrp - (linux_esigcode - linux_sigcode));

	/* Adjust the stack */
	alpha_pal_wrusp((unsigned long)sfp);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
static void
netbsd32_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;
	int onstack, error;
	int sig = ksi->ksi_signo;
	struct netbsd32_sigframe_siginfo *fp, frame;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct trapframe *tf = l->l_md.md_regs;

	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context. */
	if (onstack)
		fp = (struct netbsd32_sigframe_siginfo *)
		    ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		fp = (struct netbsd32_sigframe_siginfo *)tf->tf_rsp;

	fp--;

	/* Build stack frame for signal trampoline. */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* handled by sendsig_sigcontext */
	case 1:		/* handled by sendsig_sigcontext */
	default:	/* unknown version */
		printf("nsendsig: bad version %d\n",
		    ps->sa_sigdesc[sig].sd_vers);
		sigexit(l, SIGILL);
	case 2:
		break;
	}

	frame.sf_ra = (uint32_t)(uintptr_t)ps->sa_sigdesc[sig].sd_tramp;
	frame.sf_signum = sig;
	frame.sf_sip = (uint32_t)(uintptr_t)&fp->sf_si;
	frame.sf_ucp = (uint32_t)(uintptr_t)&fp->sf_uc;
	netbsd32_si_to_si32(&frame.sf_si, (const siginfo_t *)&ksi->ksi_info);
	frame.sf_uc.uc_flags = _UC_SIGMASK;
	frame.sf_uc.uc_sigmask = *mask;
	frame.sf_uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink;
	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_getmcontext32(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 */
	}

	/*
	 * Build context to run handler in.
	 */
	tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL);
	tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL);
	tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL);
	tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL);

	tf->tf_rip = (uint64_t)catcher;
	tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL);
	tf->tf_rflags &= ~PSL_CLEARSIG;
	tf->tf_rsp = (uint64_t)fp;
	tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL);

	/* Ensure FP state is reset, if FP is used. */
	l->l_md.md_flags &= ~MDL_USEDFPU;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
	if ((vaddr_t)catcher >= VM_MAXUSER_ADDRESS32) {
		/*
		 * process has given an invalid address for the
		 * handler. Stop it, but do not do it before so
		 * we can return the right info to userland (or in core dump)
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
}
Ejemplo n.º 18
0
static void
netbsd32_sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	int sig = ksi->ksi_signo;
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sparc32_sigframe *fp;
	struct trapframe64 *tf;
	int addr, onstack, error;
	struct rwindow32 *oldsp, *newsp;
	register32_t sp;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sparc32_sigframe sf;
	extern char netbsd32_sigcode[], netbsd32_esigcode[];
#define	szsigcode	(netbsd32_esigcode - netbsd32_sigcode)

	tf = l->l_md.md_tf;
	/* Need to attempt to zero extend this 32-bit pointer */
	oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
	if (onstack) {
		fp = (struct sparc32_sigframe *)((char *)l->l_sigstk.ss_sp +
					l->l_sigstk.ss_size);
		l->l_sigstk.ss_flags |= SS_ONSTACK;
	} else
		fp = (struct sparc32_sigframe *)oldsp;
	fp = (struct sparc32_sigframe *)((u_long)(fp - 1) & ~7);

#ifdef DEBUG
	sigpid = p->p_pid;
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
		if (sigdebug & SDB_DDB) Debugger();
	}
#endif
	/*
	 * Now set up the signal frame.  We build it in kernel space
	 * and then copy it out.  We probably ought to just build it
	 * directly in user space....
	 */
	sf.sf_signo = sig;
	sf.sf_code = (u_int)ksi->ksi_trap;
#if defined(COMPAT_SUNOS) || defined(MODULAR)
	sf.sf_scp = (u_long)&fp->sf_sc;
#endif
	sf.sf_addr = 0;			/* XXX */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	sf.sf_sc.sc_onstack = onstack;
	sf.sf_sc.sc_mask = *mask;
	sf.sf_sc.sc_sp = (u_long)oldsp;
	sf.sf_sc.sc_pc = tf->tf_pc;
	sf.sf_sc.sc_npc = tf->tf_npc;
	sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
	sf.sf_sc.sc_g1 = tf->tf_global[1];
	sf.sf_sc.sc_o0 = tf->tf_out[0];

	/*
	 * Put the stack in a consistent state before we whack away
	 * at it.  Note that write_user_windows may just dump the
	 * registers into the pcb; we need them in the process's memory.
	 * We also need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 */
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
	write_user_windows();
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK))
	    printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n",
		   fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp);
#endif
	sp = NETBSD32PTR32I(oldsp);
	error = (rwindow_save(l) || 
	    copyout(&sf, fp, sizeof sf) || 
	    copyout(&sp, &(((struct rwindow32 *)newsp)->rw_in[6]),
	        sizeof(sp)));
	mutex_enter(p->p_lock);
	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		mutex_exit(p->p_lock);
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig: window save or copyout error\n");
		printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
		if (sigdebug & SDB_DDB) Debugger();
		mutex_enter(p->p_lock);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW) {
		printf("sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_sc);
	}
#endif
	/*
	 * Arrange to continue execution at the code copied out in exec().
	 * It needs the function to call in %g1, and a new stack pointer.
	 */
	addr = p->p_psstrp - szsigcode;
	tf->tf_global[1] = (long)catcher;
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("sendsig: about to return to catcher %p thru %p\n", 
		       catcher, addr);
		if (sigdebug & SDB_DDB) Debugger();
		mutex_enter(p->p_lock);
	}
#endif
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
void sunos_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sunos_sigframe *fp;
	struct trapframe *tf;
	int addr, onstack, oldsp, newsp, error;
	int sig = ksi->ksi_signo;
	u_long code = ksi->ksi_code;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sunos_sigframe sf;

	tf = l->l_md.md_tf;
	oldsp = tf->tf_out[6];

	/*
	 * Compute new user stack addresses, subtract off
	 * one signal frame, and align.
	 */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	if (onstack)
		fp = (struct sunos_sigframe *)
		     ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		fp = (struct sunos_sigframe *)oldsp;

	fp = (struct sunos_sigframe *)((int)(fp - 1) & ~7);

#ifdef DEBUG
	if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid)
		printf("sendsig: %s[%d] sig %d newusp %p scp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_sc);
#endif
	/*
	 * Now set up the signal frame.  We build it in kernel space
	 * and then copy it out.  We probably ought to just build it
	 * directly in user space....
	 */
	sf.sf_signo = sig;
	sf.sf_code = code;
	sf.sf_scp = &fp->sf_sc;
	sf.sf_addr = 0;			/* XXX */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	sf.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;
	native_sigset_to_sigset13(mask, &sf.sf_sc.sc_mask);
	sf.sf_sc.sc_sp = oldsp;
	sf.sf_sc.sc_pc = tf->tf_pc;
	sf.sf_sc.sc_npc = tf->tf_npc;
	sf.sf_sc.sc_psr = tf->tf_psr;
	sf.sf_sc.sc_g1 = tf->tf_global[1];
	sf.sf_sc.sc_o0 = tf->tf_out[0];

	/*
	 * Put the stack in a consistent state before we whack away
	 * at it.  Note that write_user_windows may just dump the
	 * registers into the pcb; we need them in the process's memory.
	 * We also need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 */
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	newsp = (int)fp - sizeof(struct rwindow);
	write_user_windows();
	error = (rwindow_save(l) || copyout((void *)&sf, (void *)fp, sizeof sf) ||
	    suword(&((struct rwindow *)newsp)->rw_in[6], oldsp));
	mutex_enter(p->p_lock);

	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid)
			printf("sendsig: window save or copyout error\n");
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
#ifdef DEBUG
	if (sunos_sigdebug & SDB_FOLLOW)
		printf("sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_sc);
#endif
	/*
	 * Arrange to continue execution at the code copied out in exec().
	 * It needs the function to call in %g1, and a new stack pointer.
	 */
	addr = (int)catcher;	/* user does his own trampolining */
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_out[6] = newsp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sunos_sigdebug & SDB_KSTACK) && p->p_pid == sunos_sigpid)
		printf("sendsig: about to return to catcher\n");
#endif
}
Ejemplo n.º 21
0
static void
linux_rt_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct trapframe *tf;
	struct linux_rt_sigframe *fp, frame;
	int onstack, error;
	linux_siginfo_t *lsi;
	int sig = ksi->ksi_signo;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sigaltstack *sas = &l->l_sigstk;

	tf = l->l_md.md_regs;
	/* Do we need to jump onto the signal stack? */
	onstack = (sas->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;


	/* Allocate space for the signal handler context. */
	if (onstack)
		fp = (struct linux_rt_sigframe *)((char *)sas->ss_sp +
		    sas->ss_size);
	else
		fp = (struct linux_rt_sigframe *)tf->tf_esp;
	fp--;

	DPRINTF(("rt: onstack = %d, fp = %p sig = %d eip = 0x%x cr2 = 0x%x\n",
	    onstack, fp, sig, tf->tf_eip, l->l_addr->u_pcb.pcb_cr2));

	/* Build stack frame for signal trampoline. */
	frame.sf_handler = catcher;
	frame.sf_sig = native_to_linux_signo[sig];
	frame.sf_sip = &fp->sf_si;
	frame.sf_ucp = &fp->sf_uc;

	/*
	 * XXX: the following code assumes that the constants for
	 * siginfo are the same between linux and NetBSD.
	 */
	(void)memset(lsi = &frame.sf_si, 0, sizeof(frame.sf_si));
	lsi->lsi_errno = native_to_linux_errno[ksi->ksi_errno];
	lsi->lsi_code = ksi->ksi_code;
	switch (lsi->lsi_signo = frame.sf_sig) {
	case LINUX_SIGILL:
	case LINUX_SIGFPE:
	case LINUX_SIGSEGV:
	case LINUX_SIGBUS:
	case LINUX_SIGTRAP:
		lsi->lsi_addr = ksi->ksi_addr;
		break;
	case LINUX_SIGCHLD:
		lsi->lsi_uid = ksi->ksi_uid;
		lsi->lsi_pid = ksi->ksi_pid;
		lsi->lsi_utime = ksi->ksi_utime;
		lsi->lsi_stime = ksi->ksi_stime;
		/* XXX is that right? */
		lsi->lsi_status = WEXITSTATUS(ksi->ksi_status);
		break;
	case LINUX_SIGIO:
		lsi->lsi_band = ksi->ksi_band;
		lsi->lsi_fd = ksi->ksi_fd;
		break;
	default:
		lsi->lsi_uid = ksi->ksi_uid;
		lsi->lsi_pid = ksi->ksi_pid;
		if (lsi->lsi_signo == LINUX_SIGALRM ||
		    lsi->lsi_signo >= LINUX_SIGRTMIN)
			lsi->lsi_value.sival_ptr = ksi->ksi_value.sival_ptr;
		break;
	}

	/* Save register context. */
	linux_save_ucontext(l, tf, mask, sas, &frame.sf_uc);
	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	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 */
	}

	/*
	 * Build context to run handler in.
	 */
	tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_eip = ((int)p->p_sigctx.ps_sigcode) +
	    (linux_rt_sigcode - linux_sigcode);
	tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
	tf->tf_eflags &= ~PSL_CLEARSIG;
	tf->tf_esp = (int)fp;
	tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		sas->ss_flags |= SS_ONSTACK;
}
Ejemplo n.º 22
0
static void
linux_old_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct trapframe *tf;
	struct linux_sigframe *fp, frame;
	int onstack, error;
	int sig = ksi->ksi_signo;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sigaltstack *sas = &l->l_sigstk;

	tf = l->l_md.md_regs;

	/* Do we need to jump onto the signal stack? */
	onstack = (sas->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context. */
	if (onstack)
		fp = (struct linux_sigframe *) ((char *)sas->ss_sp +
		    sas->ss_size);
	else
		fp = (struct linux_sigframe *)tf->tf_esp;
	fp--;

	DPRINTF(("old: onstack = %d, fp = %p sig = %d eip = 0x%x cr2 = 0x%x\n",
	    onstack, fp, sig, tf->tf_eip,
	    ((struct pcb *)lwp_getpcb(l))->pcb_cr2));

	/* Build stack frame for signal trampoline. */
	frame.sf_handler = catcher;
	frame.sf_sig = native_to_linux_signo[sig];

	linux_save_sigcontext(l, tf, mask, &frame.sf_sc);
	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	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 */
	}

	/*
	 * Build context to run handler in.
	 */
	tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_eip = (int)p->p_sigctx.ps_sigcode;
	tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL);
	tf->tf_eflags &= ~PSL_CLEARSIG;
	tf->tf_esp = (int)fp;
	tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		sas->ss_flags |= SS_ONSTACK;
}
Ejemplo n.º 23
0
/*
 * Send an interrupt to process.
 *
 * Stack is set up to allow sigcode stored
 * in u. to call routine, followed by kcall
 * to sigreturn routine below.  After sigreturn
 * resets the signal mask, the stack, and the
 * frame pointer, it returns to the user
 * specified pc, psl.
 */
void
sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map);
	int sel = pmap->pm_hiexec > I386_MAX_EXE_ADDR ?
	    GUCODEBIG_SEL : GUCODE_SEL;
	struct sigacts *ps = p->p_sigacts;
	struct trapframe *tf = l->l_md.md_regs;
	int onstack, error;
	int sig = ksi->ksi_signo;
	u_long code = KSI_TRAPCODE(ksi);
	struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), frame;
	sig_t catcher = SIGACTION(p, sig).sa_handler;

	fp--;

	/* Build stack frame for signal trampoline. */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		frame.sf_ra = (int)p->p_sigctx.ps_sigcode;
		break;

	case 1:
		frame.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp;
		break;

	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}

	frame.sf_signum = sig;
	frame.sf_code = code;
	frame.sf_scp = &fp->sf_sc;

	/* Save register context. */
#ifdef VM86
	if (tf->tf_eflags & PSL_VM) {
		frame.sf_sc.sc_gs = tf->tf_vm86_gs;
		frame.sf_sc.sc_fs = tf->tf_vm86_fs;
		frame.sf_sc.sc_es = tf->tf_vm86_es;
		frame.sf_sc.sc_ds = tf->tf_vm86_ds;
		frame.sf_sc.sc_eflags = get_vflags(l);
		(*p->p_emul->e_syscall_intern)(p);
	} else
#endif
	{
		frame.sf_sc.sc_gs = tf->tf_gs;
		frame.sf_sc.sc_fs = tf->tf_fs;
		frame.sf_sc.sc_es = tf->tf_es;
		frame.sf_sc.sc_ds = tf->tf_ds;
		frame.sf_sc.sc_eflags = tf->tf_eflags;
	}
	frame.sf_sc.sc_edi = tf->tf_edi;
	frame.sf_sc.sc_esi = tf->tf_esi;
	frame.sf_sc.sc_ebp = tf->tf_ebp;
	frame.sf_sc.sc_ebx = tf->tf_ebx;
	frame.sf_sc.sc_edx = tf->tf_edx;
	frame.sf_sc.sc_ecx = tf->tf_ecx;
	frame.sf_sc.sc_eax = tf->tf_eax;
	frame.sf_sc.sc_eip = tf->tf_eip;
	frame.sf_sc.sc_cs = tf->tf_cs;
	frame.sf_sc.sc_esp = tf->tf_esp;
	frame.sf_sc.sc_ss = tf->tf_ss;
	frame.sf_sc.sc_trapno = tf->tf_trapno;
	frame.sf_sc.sc_err = tf->tf_err;

	/* Save signal stack. */
	frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	frame.sf_sc.sc_mask = *mask;

#ifdef COMPAT_13
	/*
	 * XXX We always have to save an old style signal mask because
	 * XXX we might be delivering a signal to a process which will
	 * XXX escape from the signal in a non-standard way and invoke
	 * XXX sigreturn() directly.
	 */
	native_sigset_to_sigset13(mask, &frame.sf_sc.__sc_mask13);
#endif

	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	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 */
	}

	int svufpu = l->l_md.md_flags & MDL_USEDFPU;
	buildcontext(l, sel, catcher, fp);
	l->l_md.md_flags |= svufpu;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}