Esempio n. 1
0
int
linux_sys_sigreturn(struct lwp *l, const struct linux_sys_sigreturn_args *uap, register_t *retval)
{
	/* {
		syscallarg(struct linux_sigframe *) sfp;
	} */
	struct linux_sigframe *sfp, frame;
	sigset_t mask;

	/*
	 * The trampoline code hands us the context.
	 * It is unsafe to keep track of it ourselves, in the event that a
	 * program jumps out of a signal handler.
	 */

	sfp = SCARG(uap, sfp);
	if (ALIGN(sfp) != (u_int64_t)sfp)
		return(EINVAL);

	/*
	 * Fetch the frame structure.
	 */
	if (copyin((void *)sfp, &frame, sizeof(struct linux_sigframe)) != 0)
		return(EFAULT);

	/* Grab the signal mask. */
	/* XXX use frame.extramask */
	linux_old_to_native_sigset(&mask, frame.sf_sc.sc_mask);

	return(linux_restore_sigcontext(l, frame.sf_sc, &mask));
}
Esempio n. 2
0
/*
 * Convert between Linux and BSD sigaction structures.
 */
void
linux_old_to_native_sigaction(struct sigaction *bsa, const struct linux_old_sigaction *lsa)
{
	bsa->sa_handler = lsa->linux_sa_handler;
	linux_old_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
	bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags);
}
Esempio n. 3
0
int
linux_sys_sigsuspend(struct lwp *l, const struct linux_sys_sigsuspend_args *uap, register_t *retval)
{
	/* {
		syscallarg(void *) restart;
		syscallarg(int) oldmask;
		syscallarg(int) mask;
	} */
	linux_old_sigset_t lss;
	sigset_t bss;

	lss = SCARG(uap, mask);
	linux_old_to_native_sigset(&bss, &lss);
	return (sigsuspend1(l, &bss));
}
Esempio n. 4
0
int
linux_sigprocmask1(struct lwp *l, int how, const linux_old_sigset_t *set, linux_old_sigset_t *oset)
{
	struct proc *p = l->l_proc;
	linux_old_sigset_t nlss, olss;
	sigset_t nbss, obss;
	int error;

	switch (how) {
	case LINUX_SIG_BLOCK:
		how = SIG_BLOCK;
		break;
	case LINUX_SIG_UNBLOCK:
		how = SIG_UNBLOCK;
		break;
	case LINUX_SIG_SETMASK:
		how = SIG_SETMASK;
		break;
	default:
		return (EINVAL);
	}

	if (set) {
		error = copyin(set, &nlss, sizeof(nlss));
		if (error)
			return (error);
		linux_old_to_native_sigset(&nbss, &nlss);
	}
	mutex_enter(p->p_lock);
	error = sigprocmask1(l, how,
	    set ? &nbss : NULL, oset ? &obss : NULL);
	mutex_exit(p->p_lock);
	if (error)
		return (error);
	if (oset) {
		native_to_linux_old_sigset(&olss, &obss);
		error = copyout(&olss, oset, sizeof(olss));
		if (error)
			return (error);
	}
	return (error);
}
Esempio n. 5
0
/*
 * The following three functions fiddle with a process' signal mask.
 * Convert the signal masks because of the different signal
 * values for Linux. The need for this is the reason why
 * they are here, and have not been mapped directly.
 */
int
linux_sys_sigsetmask(struct lwp *l, const struct linux_sys_sigsetmask_args *uap, register_t *retval)
{
    /* {
    	syscallarg(linux_old_sigset_t) mask;
    } */
    sigset_t nbss, obss;
    linux_old_sigset_t nlss, olss;
    struct proc *p = l->l_proc;
    int error;

    nlss = SCARG(uap, mask);
    linux_old_to_native_sigset(&nbss, &nlss);
    mutex_enter(p->p_lock);
    error = sigprocmask1(l, SIG_SETMASK, &nbss, &obss);
    mutex_exit(p->p_lock);
    if (error)
        return (error);
    native_to_linux_old_sigset(&olss, &obss);
    *retval = olss;
    return (0);
}
Esempio n. 6
0
static int
linux_restore_sigcontext(struct lwp *l, struct linux_sigcontext *scp,
    register_t *retval)
{
	struct proc *p = l->l_proc;
	struct sigaltstack *sas = &l->l_sigstk;
	struct trapframe *tf;
	sigset_t mask;
	ssize_t ss_gap;

	/* Restore register context. */
	tf = l->l_md.md_regs;
	DPRINTF(("sigreturn enter esp=0x%x eip=0x%x\n", tf->tf_esp, tf->tf_eip));

#ifdef VM86
	if (scp->sc_eflags & PSL_VM) {
		void syscall_vm86(struct trapframe *);

		tf->tf_vm86_gs = scp->sc_gs;
		tf->tf_vm86_fs = scp->sc_fs;
		tf->tf_vm86_es = scp->sc_es;
		tf->tf_vm86_ds = scp->sc_ds;
		set_vflags(l, scp->sc_eflags);
		p->p_md.md_syscall = syscall_vm86;
	} else
#endif
	{
		/*
		 * Check for security violations.  If we're returning to
		 * protected mode, the CPU will validate the segment registers
		 * automatically and generate a trap on violations.  We handle
		 * the trap, rather than doing all of the checking here.
		 */
		if (((scp->sc_eflags ^ tf->tf_eflags) & PSL_USERSTATIC) != 0 ||
		    !USERMODE(scp->sc_cs, scp->sc_eflags))
			return EINVAL;

		tf->tf_gs = scp->sc_gs;
		tf->tf_fs = scp->sc_fs;
		tf->tf_es = scp->sc_es;
		tf->tf_ds = scp->sc_ds;
#ifdef VM86
		if (tf->tf_eflags & PSL_VM)
			(*p->p_emul->e_syscall_intern)(p);
#endif
		tf->tf_eflags = scp->sc_eflags;
	}
	tf->tf_edi = scp->sc_edi;
	tf->tf_esi = scp->sc_esi;
	tf->tf_ebp = scp->sc_ebp;
	tf->tf_ebx = scp->sc_ebx;
	tf->tf_edx = scp->sc_edx;
	tf->tf_ecx = scp->sc_ecx;
	tf->tf_eax = scp->sc_eax;
	tf->tf_eip = scp->sc_eip;
	tf->tf_cs = scp->sc_cs;
	tf->tf_esp = scp->sc_esp_at_signal;
	tf->tf_ss = scp->sc_ss;

	/* Restore signal stack. */
	/*
	 * Linux really does it this way; it doesn't have space in sigframe
	 * to save the onstack flag.
	 */
	mutex_enter(p->p_lock);
	ss_gap = (ssize_t)((char *)scp->sc_esp_at_signal - (char *)sas->ss_sp);
	if (ss_gap >= 0 && ss_gap < sas->ss_size)
		sas->ss_flags |= SS_ONSTACK;
	else
		sas->ss_flags &= ~SS_ONSTACK;

	/* Restore signal mask. */
	linux_old_to_native_sigset(&mask, &scp->sc_mask);
	(void) sigprocmask1(l, SIG_SETMASK, &mask, 0);
	mutex_exit(p->p_lock);

	DPRINTF(("sigreturn exit esp=0x%x eip=0x%x\n", tf->tf_esp, tf->tf_eip));
	return EJUSTRETURN;
}