Ejemplo n.º 1
0
void
native_to_linux_siginfo(linux_siginfo_t *lsi, const struct _ksiginfo *ksi)
{
	memset(lsi, 0, sizeof(*lsi));

	lsi->lsi_signo = native_to_linux_signo[ksi->_signo];
	lsi->lsi_errno = native_to_linux_errno[ksi->_errno];
	lsi->lsi_code = native_to_linux_si_code(ksi->_code);

	switch (ksi->_code) {
	case SI_NOINFO:
		break;

	case SI_USER:
		lsi->lsi_pid = ksi->_reason._rt._pid;
		lsi->lsi_uid = ksi->_reason._rt._uid;
		if (lsi->lsi_signo == LINUX_SIGALRM ||
		    lsi->lsi_signo >= LINUX_SIGRTMIN)
			lsi->lsi_value.sival_ptr =
			    ksi->_reason._rt._value.sival_ptr;
		break;

	case SI_TIMER:
	case SI_QUEUE:
		lsi->lsi_uid = ksi->_reason._rt._uid;
		lsi->lsi_uid = ksi->_reason._rt._uid;
		lsi->lsi_value.sival_ptr = ksi->_reason._rt._value.sival_ptr;
		break;

	case SI_ASYNCIO:
	case SI_MESGQ:
		lsi->lsi_value.sival_ptr = ksi->_reason._rt._value.sival_ptr;
		break;

	default:
		switch (ksi->_signo) {
		case SIGCHLD:
			lsi->lsi_uid = ksi->_reason._child._uid;
			lsi->lsi_pid = ksi->_reason._child._pid;
			lsi->lsi_status = native_to_linux_si_status(
			    ksi->_code, ksi->_reason._child._status);
			lsi->lsi_utime = ksi->_reason._child._utime;
			lsi->lsi_stime = ksi->_reason._child._stime;
			break;

		case SIGILL:
		case SIGFPE:
		case SIGSEGV:
		case SIGBUS:
		case SIGTRAP:
			lsi->lsi_addr = ksi->_reason._fault._addr;
			break;

		case SIGIO:
			lsi->lsi_fd = ksi->_reason._poll._fd;
			lsi->lsi_band = ksi->_reason._poll._band;
			break;
		default:
			break;
		}
	}
}
Ejemplo n.º 2
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.º 3
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;
}