⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	__put_user_error(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no, err);	__put_user_error(current->thread.error_code, &sf->uc.uc_mcontext.error_code, err);	__put_user_error(current->thread.address, &sf->uc.uc_mcontext.fault_address, err);	__put_user_error(set->sig[0], &sf->uc.uc_mcontext.oldmask, err);	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));	aux = (struct aux_sigframe __user *) sf->uc.uc_regspace;#ifdef CONFIG_CRUNCH	if (err == 0)		err |= preserve_crunch_context(&aux->crunch);#endif#ifdef CONFIG_IWMMXT	if (err == 0 && test_thread_flag(TIF_USING_IWMMXT))		err |= preserve_iwmmxt_context(&aux->iwmmxt);#endif#ifdef CONFIG_VFP//	if (err == 0)//		err |= vfp_save_state(&sf->aux.vfp);#endif	__put_user_error(0, &aux->end_magic, err);	return err;}static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize){	unsigned long sp = regs->ARM_sp;	void __user *frame;	/*	 * This is the X/Open sanctioned signal stack switching.	 */	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))		sp = current->sas_ss_sp + current->sas_ss_size;	/*	 * ATPCS B01 mandates 8-byte alignment	 */	frame = (void __user *)((sp - framesize) & ~7);	/*	 * Check that we can actually write to the signal frame.	 */	if (!access_ok(VERIFY_WRITE, frame, framesize))		frame = NULL;	return frame;}static intsetup_return(struct pt_regs *regs, struct k_sigaction *ka,	     unsigned long __user *rc, void __user *frame, int usig){	unsigned long handler = (unsigned long)ka->sa.sa_handler;	unsigned long retcode;	int thumb = 0;	unsigned long cpsr = regs->ARM_cpsr & ~PSR_f;	/*	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.	 */	if (ka->sa.sa_flags & SA_THIRTYTWO)		cpsr = (cpsr & ~MODE_MASK) | USR_MODE;#ifdef CONFIG_ARM_THUMB	if (elf_hwcap & HWCAP_THUMB) {		/*		 * The LSB of the handler determines if we're going to		 * be using THUMB or ARM mode for this signal handler.		 */		thumb = handler & 1;		if (thumb)			cpsr |= PSR_T_BIT;		else			cpsr &= ~PSR_T_BIT;	}#endif	if (ka->sa.sa_flags & SA_RESTORER) {		retcode = (unsigned long)ka->sa.sa_restorer;	} else {		unsigned int idx = thumb << 1;		if (ka->sa.sa_flags & SA_SIGINFO)			idx += 3;		if (__put_user(sigreturn_codes[idx],   rc) ||		    __put_user(sigreturn_codes[idx+1], rc+1))			return 1;		if (cpsr & MODE32_BIT) {			/*			 * 32-bit code can use the new high-page			 * signal return code support.			 */			retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;		} else {			/*			 * Ensure that the instruction cache sees			 * the return code written onto the stack.			 */			flush_icache_range((unsigned long)rc,					   (unsigned long)(rc + 2));			retcode = ((unsigned long)rc) + thumb;		}	}	regs->ARM_r0 = usig;	regs->ARM_sp = (unsigned long)frame;	regs->ARM_lr = retcode;	regs->ARM_pc = handler;	regs->ARM_cpsr = cpsr;	return 0;}static intsetup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs){	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));	int err = 0;	if (!frame)		return 1;	/*	 * Set uc.uc_flags to a value which sc.trap_no would never have.	 */	__put_user_error(0x5ac3c35a, &frame->uc.uc_flags, err);	err |= setup_sigframe(frame, regs, set);	if (err == 0)		err = setup_return(regs, ka, frame->retcode, frame, usig);	return err;}static intsetup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,	       sigset_t *set, struct pt_regs *regs){	struct rt_sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));	stack_t stack;	int err = 0;	if (!frame)		return 1;	err |= copy_siginfo_to_user(&frame->info, info);	__put_user_error(0, &frame->sig.uc.uc_flags, err);	__put_user_error(NULL, &frame->sig.uc.uc_link, err);	memset(&stack, 0, sizeof(stack));	stack.ss_sp = (void __user *)current->sas_ss_sp;	stack.ss_flags = sas_ss_flags(regs->ARM_sp);	stack.ss_size = current->sas_ss_size;	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));	err |= setup_sigframe(&frame->sig, regs, set);	if (err == 0)		err = setup_return(regs, ka, frame->sig.retcode, frame, usig);	if (err == 0) {		/*		 * For realtime signals we must also set the second and third		 * arguments for the signal handler.		 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06		 */		regs->ARM_r1 = (unsigned long)&frame->info;		regs->ARM_r2 = (unsigned long)&frame->sig.uc;	}	return err;}static inline void restart_syscall(struct pt_regs *regs){	regs->ARM_r0 = regs->ARM_ORIG_r0;	regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;}/* * OK, we're invoking a handler */	static voidhandle_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;	int usig = sig;	int ret;	/*	 * If we were from a system call, check for system call restarting...	 */	if (syscall) {		switch (regs->ARM_r0) {		case -ERESTART_RESTARTBLOCK:		case -ERESTARTNOHAND:			regs->ARM_r0 = -EINTR;			break;		case -ERESTARTSYS:			if (!(ka->sa.sa_flags & SA_RESTART)) {				regs->ARM_r0 = -EINTR;				break;			}			/* fallthrough */		case -ERESTARTNOINTR:			restart_syscall(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;	}	/*	 * Block the signal if we were successful.	 */	spin_lock_irq(&tsk->sighand->siglock);	sigorsets(&tsk->blocked, &tsk->blocked,		  &ka->sa.sa_mask);	if (!(ka->sa.sa_flags & SA_NODEFER))		sigaddset(&tsk->blocked, sig);	recalc_sigpending();	spin_unlock_irq(&tsk->sighand->siglock);}/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall){	struct k_sigaction ka;	siginfo_t info;	int signr;	/*	 * We want the common case to go fast, which	 * is why we may in certain cases get here from	 * kernel mode. Just return without doing anything	 * if so.	 */	if (!user_mode(regs))		return 0;	if (try_to_freeze())		goto no_signal;	single_step_clear(current);	signr = get_signal_to_deliver(&info, &ka, regs, NULL);	if (signr > 0) {		handle_signal(signr, &ka, &info, oldset, regs, syscall);		single_step_set(current);		return 1;	} no_signal:	/*	 * No signal to deliver to the process - restart the syscall.	 */	if (syscall) {		if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {			if (thumb_mode(regs)) {				regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;				regs->ARM_pc -= 2;			} else {#if defined(CONFIG_AEABI) && !defined(CONFIG_OABI_COMPAT)				regs->ARM_r7 = __NR_restart_syscall;				regs->ARM_pc -= 4;#else				u32 __user *usp;				u32 swival = __NR_restart_syscall;				regs->ARM_sp -= 12;				usp = (u32 __user *)regs->ARM_sp;				/*				 * Either we supports OABI only, or we have				 * EABI with the OABI compat layer enabled.				 * In the later case we don't know if user				 * space is EABI or not, and if not we must				 * not clobber r7.  Always using the OABI				 * syscall solves that issue and works for				 * all those cases.				 */				swival = swival - __NR_SYSCALL_BASE + __NR_OABI_SYSCALL_BASE;				put_user(regs->ARM_pc, &usp[0]);				/* swi __NR_restart_syscall */				put_user(0xef000000 | swival, &usp[1]);				/* ldr	pc, [sp], #12 */				put_user(0xe49df00c, &usp[2]);				flush_icache_range((unsigned long)usp,						   (unsigned long)(usp + 3));				regs->ARM_pc = regs->ARM_sp + 4;#endif			}		}		if (regs->ARM_r0 == -ERESTARTNOHAND ||		    regs->ARM_r0 == -ERESTARTSYS ||		    regs->ARM_r0 == -ERESTARTNOINTR) {			restart_syscall(regs);		}	}	single_step_set(current);	return 0;}asmlinkage voiddo_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall){	if (thread_flags & _TIF_SIGPENDING)		do_signal(&current->blocked, regs, syscall);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -