/*
 * OK, we're invoking a handler
 */
static int handle_signal(struct pt_regs *regs, unsigned long signr,
			 struct k_sigaction *ka, siginfo_t *info,
			 sigset_t *oldset)
{
	unsigned long sp;
	int err;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

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

		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				PT_REGS_SYSCALL_RET(regs) = -EINTR;
				break;
			}
		/* fallthrough */
		case -ERESTARTNOINTR:
			PT_REGS_RESTART_SYSCALL(regs);
			PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
			break;
		}
	}

	sp = PT_REGS_SP(regs);
	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
		sp = current->sas_ss_sp + current->sas_ss_size;

#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
	if (!(ka->sa.sa_flags & SA_SIGINFO))
		err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
	else
#endif
		err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);

	if (err)
		force_sigsegv(signr, current);
	else
		block_sigmask(ka, signr);

	return err;
}
示例#2
0
文件: signal.c 项目: AllenWeb/linux
/*
 * OK, we're invoking a handler
 */
static void handle_signal(struct pt_regs *regs, unsigned long signr,
			 struct k_sigaction *ka, siginfo_t *info)
{
	sigset_t *oldset = sigmask_to_save();
	unsigned long sp;
	int err;

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

		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				PT_REGS_SYSCALL_RET(regs) = -EINTR;
				break;
			}
		/* fallthrough */
		case -ERESTARTNOINTR:
			PT_REGS_RESTART_SYSCALL(regs);
			PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
			break;
		}
	}

	sp = PT_REGS_SP(regs);
	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
		sp = current->sas_ss_sp + current->sas_ss_size;

#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
	if (!(ka->sa.sa_flags & SA_SIGINFO))
		err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
	else
#endif
		err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);

	if (err)
		force_sigsegv(signr, current);
	else
		signal_delivered(signr, info, ka, regs, 0);
}
示例#3
0
#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
if(!(ka->sa.sa_flags & SA_SIGINFO))
		err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
	else
#endif
		err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
示例#4
0
/*
 * OK, we're invoking a handler
 */	
static int handle_signal(struct pt_regs *regs, unsigned long signr, 
			 struct k_sigaction *ka, siginfo_t *info, 
			 sigset_t *oldset, int error)
{
        __sighandler_t handler;
	void (*restorer)(void);
	unsigned long sp;
	sigset_t save;
	int err, ret;

	ret = 0;
	switch(error){
	case -ERESTART_RESTARTBLOCK:
		current_thread_info()->restart_block.fn = 
			do_no_restart_syscall;
	case -ERESTARTNOHAND:
		ret = -EINTR;
		break;

	case -ERESTARTSYS:
		if (!(ka->sa.sa_flags & SA_RESTART)) {
			ret = -EINTR;
			break;
		}
		/* fallthrough */
	case -ERESTARTNOINTR:
		PT_REGS_RESTART_SYSCALL(regs);
		PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);

		/* This is because of the UM_SET_SYSCALL_RETURN and the fact
		 * that on i386 the system call number and return value are
		 * in the same register.  When the system call restarts, %eax
		 * had better have the system call number in it.  Since the
		 * return value doesn't matter (except that it shouldn't be
		 * -ERESTART*), we'll stick the system call number there.
		 */
		ret = PT_REGS_SYSCALL_NR(regs);
		break;
	}

	handler = ka->sa.sa_handler;
	save = *oldset;

	if (ka->sa.sa_flags & SA_ONESHOT)
		ka->sa.sa_handler = SIG_DFL;

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

	sp = PT_REGS_SP(regs);

	if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
		sp = current->sas_ss_sp + current->sas_ss_size;
	
	if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret);

	if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer;
	else restorer = NULL;

	if(ka->sa.sa_flags & SA_SIGINFO)
		err = setup_signal_stack_si(sp, signr, (unsigned long) handler,
					    restorer, regs, info, &save);
	else
		err = setup_signal_stack_sc(sp, signr, (unsigned long) handler,
					    restorer, regs, &save);
	if(err) goto segv;

	return(0);
 segv:
	force_segv(signr);
	return(1);
}