Exemplo n.º 1
0
static int
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
	       sigset_t *set, struct pt_regs *regs)
{
	int usig = signr_convert(sig);
	int ret;

	/* Set up the stack frame */
	if (is_ia32) {
		if (ka->sa.sa_flags & SA_SIGINFO)
			ret = ia32_setup_rt_frame(usig, ka, info, set, regs);
		else
			ret = ia32_setup_frame(usig, ka, set, regs);
	} else
		ret = __setup_rt_frame(sig, ka, info, set, regs);

	if (ret) {
		force_sigsegv(sig, current);
		return -EFAULT;
	}

	return ret;
}
Exemplo n.º 2
0
static int
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
		sigset_t *oldset, struct pt_regs *regs)
{
	int ret;

#ifdef DEBUG_SIG
	printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n",
		current->pid, sig,
		regs->rip, regs->rsp, regs);
#endif

	/* Are we from a system call? */
	if ((long)regs->orig_rax >= 0) {
		/* If so, check system call restarting.. */
		switch (regs->rax) {
		        case -ERESTART_RESTARTBLOCK:
			case -ERESTARTNOHAND:
				regs->rax = -EINTR;
				break;

			case -ERESTARTSYS:
				if (!(ka->sa.sa_flags & SA_RESTART)) {
					regs->rax = -EINTR;
					break;
				}
				/* fallthrough */
			case -ERESTARTNOINTR:
				regs->rax = regs->orig_rax;
				regs->rip -= 2;
				break;
		}
	}

	/*
	 * If TF is set due to a debugger (PT_DTRACE), clear the TF
	 * flag so that register information in the sigcontext is
	 * correct.
	 */
	if (unlikely(regs->eflags & TF_MASK)) {
		if (likely(current->ptrace & PT_DTRACE)) {
			current->ptrace &= ~PT_DTRACE;
			regs->eflags &= ~TF_MASK;
		}
	}

#ifdef CONFIG_IA32_EMULATION
	if (test_thread_flag(TIF_IA32)) {
		if (ka->sa.sa_flags & SA_SIGINFO)
			ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs);
		else
			ret = ia32_setup_frame(sig, ka, oldset, regs);
	} else 
#endif
	ret = setup_rt_frame(sig, ka, info, oldset, regs);

	if (ret == 0) {
		spin_lock_irq(&current->sighand->siglock);
		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
		if (!(ka->sa.sa_flags & SA_NODEFER))
			sigaddset(&current->blocked,sig);
		recalc_sigpending();
		spin_unlock_irq(&current->sighand->siglock);
	}

	return ret;
}
Exemplo n.º 3
0
static int
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
		sigset_t *oldset, struct pt_regs *regs)
{
	int ret;

#ifdef DEBUG_SIG
	printk("handle_signal pid:%d sig:%lu rip:%lx rsp:%lx regs=%p\n",
		current->pid, sig,
		regs->rip, regs->rsp, regs);
#endif

	/* Are we from a system call? */
	if (current_syscall(regs) >= 0) {
		/* If so, check system call restarting.. */
		switch (current_syscall_ret(regs)) {
		        case -ERESTART_RESTARTBLOCK:
			case -ERESTARTNOHAND:
				regs->rax = -EINTR;
				break;

			case -ERESTARTSYS:
				if (!(ka->sa.sa_flags & SA_RESTART)) {
					regs->rax = -EINTR;
					break;
				}
				/* fallthrough */
			case -ERESTARTNOINTR:
				regs->rax = regs->orig_rax;
				regs->rip -= 2;
				break;
		}
	}

	/*
	 * If TF is set due to a debugger (TIF_FORCED_TF), clear the TF flag so
	 * that register information in the sigcontext is correct.
	 */
	if (unlikely(regs->eflags & TF_MASK)
	    && likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
		regs->eflags &= ~TF_MASK;

#ifdef CONFIG_IA32_EMULATION
	if (test_thread_flag(TIF_IA32)) {
		if (ka->sa.sa_flags & SA_SIGINFO)
			ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs);
		else
			ret = ia32_setup_frame(sig, ka, oldset, regs);
	} else 
#endif
	ret = setup_rt_frame(sig, ka, info, oldset, regs);

	if (ret == 0) {
		spin_lock_irq(&current->sighand->siglock);
		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
		if (!(ka->sa.sa_flags & SA_NODEFER))
			sigaddset(&current->blocked,sig);
		recalc_sigpending();
		spin_unlock_irq(&current->sighand->siglock);

		/*
		 * Clear TF when entering the signal handler, but
		 * notify any tracer that was single-stepping it.
		 * The tracer may want to single-step inside the
		 * handler too.
		 */
		regs->eflags &= ~(TF_MASK | X86_EFLAGS_DF);
		tracehook_report_handle_signal(sig, ka, oldset, regs);
	}

	return ret;
}
Exemplo n.º 4
0
static int
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
          sigset_t *oldset, struct pt_regs *regs)
{
    int ret;

    /* Are we from a system call? */
    if (current_syscall(regs) >= 0) {
        /* If so, check system call restarting.. */
        switch (current_syscall_ret(regs)) {
        case -ERESTART_RESTARTBLOCK:
        case -ERESTARTNOHAND:
            regs->ax = -EINTR;
            break;

        case -ERESTARTSYS:
            if (!(ka->sa.sa_flags & SA_RESTART)) {
                regs->ax = -EINTR;
                break;
            }
        /* fallthrough */
        case -ERESTARTNOINTR:
            regs->ax = regs->orig_ax;
            regs->ip -= 2;
            break;
        }
    }

    /*
     * If TF is set due to a debugger (TIF_FORCED_TF), clear the TF
     * flag so that register information in the sigcontext is correct.
     */
    if (unlikely(regs->flags & X86_EFLAGS_TF) &&
        likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
        regs->flags &= ~X86_EFLAGS_TF;

#ifdef CONFIG_IA32_EMULATION
    if (test_thread_flag(TIF_IA32)) {
        if (ka->sa.sa_flags & SA_SIGINFO)
            ret = ia32_setup_rt_frame(sig, ka, info, oldset, regs);
        else
            ret = ia32_setup_frame(sig, ka, oldset, regs);
    } else 
#endif
    ret = setup_rt_frame(sig, ka, info, oldset, regs);

    if (ret == 0) {
        /*
         * This has nothing to do with segment registers,
         * despite the name.  This magic affects uaccess.h
         * macros' behavior.  Reset it to the normal setting.
         */
        set_fs(USER_DS);

        /*
         * Clear the direction flag as per the ABI for function entry.
         */
        regs->flags &= ~X86_EFLAGS_DF;

        /*
         * Clear TF when entering the signal handler, but
         * notify any tracer that was single-stepping it.
         * The tracer may want to single-step inside the
         * handler too.
         */
        regs->flags &= ~X86_EFLAGS_TF;
        if (test_thread_flag(TIF_SINGLESTEP))
            ptrace_notify(SIGTRAP);

        spin_lock_irq(&current->sighand->siglock);
        sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
        if (!(ka->sa.sa_flags & SA_NODEFER))
            sigaddset(&current->blocked,sig);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
    }

    return ret;
}