Пример #1
0
/*
 * Setup invocation of signal handler
 */
static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
			 sigset_t *oldset, struct pt_regs *regs)
{
	int rc;

	/*
	 * If we're handling a signal that aborted a system call,
	 * set up the error return value before adding the signal
	 * frame to the stack.
	 */

	if (regs->syscall_nr >= 0) {
		switch (regs->r00) {
		case -ERESTART_RESTARTBLOCK:
		case -ERESTARTNOHAND:
			regs->r00 = -EINTR;
			break;
		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				regs->r00 = -EINTR;
				break;
			}
			/* Fall through */
		case -ERESTARTNOINTR:
			regs->r06 = regs->syscall_nr;
			pt_set_elr(regs, pt_elr(regs) - 4);
			regs->r00 = regs->restart_r0;
			break;
		default:
			break;
		}
	}

	/*
	 * Set up the stack frame; not doing the SA_SIGINFO thing.  We
	 * only set up the rt_frame flavor.
	 */
	rc = setup_rt_frame(sig, ka, info, oldset, regs);

	/* If there was an error on setup, no signal was delivered. */
	if (rc)
		return rc;

	block_sigmask(ka, sig);

	return 0;
}
/*
 * OK, we're invoking a handler
 */
static int
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
	      sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
{
	int ret;

	/* Set up the stack frame */
	if (ka->sa.sa_flags & SA_SIGINFO)
		ret = setup_rt_frame(sig, ka, info, oldset, regs);
	else
		ret = setup_frame(sig, ka, oldset, regs);

	if (ret == 0)
		block_sigmask(ka, sig);

	return ret;
}
Пример #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;

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

		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				regs->regs[0] = -EINTR;
				break;
			}
			/* fallthrough */
		case -ERESTARTNOINTR:
			/* Reload caller-saves to restore r0..r5 and r10. */
			regs->flags |= PT_FLAGS_CALLER_SAVES;
			regs->regs[0] = regs->orig_r0;
			regs->pc -= 8;
		}
	}

	/* Set up the stack frame */
#ifdef CONFIG_COMPAT
	if (is_compat_task())
		ret = compat_setup_rt_frame(sig, ka, info, oldset, regs);
	else
#endif
		ret = setup_rt_frame(sig, ka, info, oldset, regs);
	if (ret == 0) {
		/* This code is only called from system calls or from
		 * the work_pending path in the return-to-user code, and
		 * either way we can re-enable interrupts unconditionally.
		 */
		block_sigmask(ka, sig);
	}

	return ret;
}
Пример #4
0
/*
 * OK, we're invoking a handler
 */	
static int
handle_signal(unsigned long sig, struct k_sigaction *ka,
	      siginfo_t *info, sigset_t *oldset,
	      struct pt_regs * regs)
{
	struct thread_info *thread = current_thread_info();
	struct task_struct *tsk = current;
	int usig = sig;
	int ret;

	/*
	 * translate the signal
	 */
	if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
		usig = thread->exec_domain->signal_invmap[usig];

	/*
	 * Set up the stack frame
	 */
	if (ka->sa.sa_flags & SA_SIGINFO)
		ret = setup_rt_frame(usig, ka, info, oldset, regs);
	else
		ret = setup_frame(usig, ka, oldset, regs);

	/*
	 * Check that the resulting registers are actually sane.
	 */
	ret |= !valid_user_regs(regs);

	if (ret != 0) {
#ifdef CONFIG_SHLOG_SYSTEM
		rlog_app_start( current, 0, 0, sig, 0, regs );
#endif /* CONFIG_SHLOG_SYSTEM */
		force_sigsegv(sig, tsk);
		return ret;
	}

	/*
	 * Block the signal if we were successful.
	 */
	block_sigmask(ka, sig);

	return 0;
}
Пример #5
0
/*
 * OK, we're invoking a handler
 */
static int
handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
	      sigset_t *oldset, struct pt_regs *regs)
{
	int ret;

	/* are we from a system call? to see pt_regs->orig_p0 */
	if (regs->orig_p0 >= 0)
		/* If so, check system call restarting.. */
		handle_restart(regs, ka, 1);

	/* set up the stack frame */
	ret = setup_rt_frame(sig, ka, info, oldset, regs);

	if (ret == 0)
		block_sigmask(ka, sig);

	return ret;
}
Пример #6
0
static inline int
handle_signal(unsigned long signr, struct k_sigaction *ka,
	      siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{
	int err;

	if (ka->sa.sa_flags & SA_SIGINFO)
		err = setup_rt_frame(ka, regs, signr, oldset, info);
	else
		err = setup_frame(ka, regs, signr, oldset);

	if (err)
		return err;

	block_sigmask(ka, signr);
	tracehook_signal_handler(signr, info, ka, regs, 0);

	return 0;
}
Пример #7
0
static int handle_signal(unsigned long sig, siginfo_t *info,
			 struct k_sigaction *ka, sigset_t *oldset,
			 struct pt_regs *regs)
{
	int ret;

	
	if (regs->faultnum == INT_SWINT_1) {
		
		switch (regs->regs[0]) {
		case -ERESTART_RESTARTBLOCK:
		case -ERESTARTNOHAND:
			regs->regs[0] = -EINTR;
			break;

		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				regs->regs[0] = -EINTR;
				break;
			}
			
		case -ERESTARTNOINTR:
			
			regs->flags |= PT_FLAGS_CALLER_SAVES;
			regs->regs[0] = regs->orig_r0;
			regs->pc -= 8;
		}
	}

	
#ifdef CONFIG_COMPAT
	if (is_compat_task())
		ret = compat_setup_rt_frame(sig, ka, info, oldset, regs);
	else
#endif
		ret = setup_rt_frame(sig, ka, info, oldset, regs);
	if (ret == 0) {
		block_sigmask(ka, sig);
	}

	return ret;
}
static int handle_signal(unsigned long sig, siginfo_t *info,
	struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
{
	int ret;
	struct mips_abi *abi = current->thread.abi;
	void *vdso = current->mm->context.vdso;

	if (regs->regs[0]) {
		switch(regs->regs[2]) {
		case ERESTART_RESTARTBLOCK:
		case ERESTARTNOHAND:
			regs->regs[2] = EINTR;
			break;
		case ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				regs->regs[2] = EINTR;
				break;
			}
		/* fallthrough */
		case ERESTARTNOINTR:
			regs->regs[7] = regs->regs[26];
			regs->regs[2] = regs->regs[0];
			regs->cp0_epc -= 4;
		}

		regs->regs[0] = 0;		/* Don't deal with this again.  */
	}

	if (sig_uses_siginfo(ka))
		ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
					  ka, regs, sig, oldset, info);
	else
		ret = abi->setup_frame(vdso + abi->signal_return_offset,
				       ka, regs, sig, oldset);

	if (ret)
		return ret;

	block_sigmask(ka, sig);

	return ret;
}
Пример #9
0
/*
 * handle the actual delivery of a signal to userspace
 */
static int handle_signal(int sig,
			 siginfo_t *info, struct k_sigaction *ka,
			 sigset_t *oldset, struct pt_regs *regs)
{
	int ret;

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

		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				regs->d0 = -EINTR;
				break;
			}

			/* fallthrough */
		case -ERESTARTNOINTR:
			regs->d0 = regs->orig_d0;
			stepback(regs);
		}
	}

	/* Set up the stack frame */
	if (ka->sa.sa_flags & SA_SIGINFO)
		ret = setup_rt_frame(sig, ka, info, oldset, regs);
	else
		ret = setup_frame(sig, ka, oldset, regs);

	if (ret == 0)
		block_sigmask(ka, sig);

	return ret;
}
Пример #10
0
static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
			 sigset_t *oldset, struct pt_regs *regs)
{
	int rc;


	if (regs->syscall_nr >= 0) {
		switch (regs->r00) {
		case -ERESTART_RESTARTBLOCK:
		case -ERESTARTNOHAND:
			regs->r00 = -EINTR;
			break;
		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				regs->r00 = -EINTR;
				break;
			}
			
		case -ERESTARTNOINTR:
			regs->r06 = regs->syscall_nr;
			pt_set_elr(regs, pt_elr(regs) - 4);
			regs->r00 = regs->restart_r0;
			break;
		default:
			break;
		}
	}

	rc = setup_rt_frame(sig, ka, info, oldset, regs);

	
	if (rc)
		return rc;

	block_sigmask(ka, sig);

	return 0;
}
Пример #11
0
/*
 * OK, we're invoking a handler
 */
static int handle_signal(unsigned long sig, struct k_sigaction *ka,
                         siginfo_t *info, sigset_t *oldset,
                         struct pt_regs *regs, int syscall)
{
    struct thread_info *thread = current_thread_info();
    struct task_struct *tsk = current;
    sigset_t blocked;
    int usig = sig;
    int ret;

    /*
     * If we were from a system call, check for system call restarting...
     */
    if (syscall) {
        switch (regs->UCreg_00) {
        case -ERESTART_RESTARTBLOCK:
        case -ERESTARTNOHAND:
            regs->UCreg_00 = -EINTR;
            break;
        case -ERESTARTSYS:
            if (!(ka->sa.sa_flags & SA_RESTART)) {
                regs->UCreg_00 = -EINTR;
                break;
            }
        /* fallthrough */
        case -ERESTARTNOINTR:
            setup_syscall_restart(regs);
        }
    }

    /*
     * translate the signal
     */
    if (usig < 32 && thread->exec_domain
            && thread->exec_domain->signal_invmap)
        usig = thread->exec_domain->signal_invmap[usig];

    /*
     * Set up the stack frame
     */
    if (ka->sa.sa_flags & SA_SIGINFO)
        ret = setup_rt_frame(usig, ka, info, oldset, regs);
    else
        ret = setup_frame(usig, ka, oldset, regs);

    /*
     * Check that the resulting registers are actually sane.
     */
    ret |= !valid_user_regs(regs);

    if (ret != 0) {
        force_sigsegv(sig, tsk);
        return ret;
    }

    /*
     * Block the signal if we were successful.
     */
    block_sigmask(ka, sig);

    return 0;
}
Пример #12
0
static int do_signal(struct pt_regs *regs)
{
	sigset_t *oldset;
	siginfo_t info;
	int signr;
	struct k_sigaction ka;
	int ret;
	int is32 = is_32bit_task();

	if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
		oldset = &current->saved_sigmask;
	else
		oldset = &current->blocked;

	signr = get_signal_to_deliver(&info, &ka, regs, NULL);

	/* Is there any syscall restart business here ? */
	check_syscall_restart(regs, &ka, signr > 0);

	if (signr <= 0) {
		struct thread_info *ti = current_thread_info();
		/* No signal to deliver -- put the saved sigmask back */
		if (ti->local_flags & _TLF_RESTORE_SIGMASK) {
			ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
		}
		regs->trap = 0;
		return 0;               /* no signals delivered */
	}

#ifndef CONFIG_PPC_ADV_DEBUG_REGS
        /*
	 * Reenable the DABR before delivering the signal to
	 * user space. The DABR will have been cleared if it
	 * triggered inside the kernel.
	 */
	if (current->thread.dabr)
		set_dabr(current->thread.dabr);
#endif
	/* Re-enable the breakpoints for the signal stack */
	thread_change_pc(current, regs);

	if (is32) {
        	if (ka.sa.sa_flags & SA_SIGINFO)
			ret = handle_rt_signal32(signr, &ka, &info, oldset,
					regs);
		else
			ret = handle_signal32(signr, &ka, &info, oldset,
					regs);
	} else {
		ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
	}

	regs->trap = 0;
	if (ret) {
		block_sigmask(&ka, signr);

		/*
		 * A signal was successfully delivered; the saved sigmask is in
		 * its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
		 */
		current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;

		/*
		 * Let tracing know that we've done the handler setup.
		 */
		tracehook_signal_handler(signr, &info, &ka, regs,
					 test_thread_flag(TIF_SINGLESTEP));
	}

	return ret;
}