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

📄 signal.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
		panic ("Double exception sys_sigreturn\n");	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))		goto badframe;	if (__get_user(set.sig[0], &frame->sc.oldmask)	    || (_NSIG_WORDS > 1		&& __copy_from_user(&set.sig[1], &frame->extramask,				    sizeof(frame->extramask))))		goto badframe;	sigdelsetmask(&set, ~_BLOCKABLE);	spin_lock_irq(&current->sighand->siglock);	current->blocked = set;	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);	if (restore_sigcontext(regs, &frame->sc))		goto badframe;	return regs->areg[2];badframe:	force_sig(SIGSEGV, current);	return 0;}asmlinkage int sys_rt_sigreturn(struct pt_regs *regs){	struct rt_sigframe *frame = (struct rt_sigframe *)regs->areg[1];	sigset_t set;	stack_t st;	int ret;	if (regs->depc > 64)	{		printk("!!!!!!! DEPC !!!!!!!\n");		return 0;	}	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))		goto badframe;	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))		goto badframe;	sigdelsetmask(&set, ~_BLOCKABLE);	spin_lock_irq(&current->sighand->siglock);	current->blocked = set;	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))		goto badframe;	ret = regs->areg[2];	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))		goto badframe;	/* It is more difficult to avoid calling this function than to	   call it and ignore errors.  */	do_sigaltstack(&st, NULL, regs->areg[1]);	return ret;badframe:	force_sig(SIGSEGV, current);	return 0;}/* * Set up a signal frame. *//* * Determine which stack to use.. */static inline void *get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size){	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))		sp = current->sas_ss_sp + current->sas_ss_size;	return (void *)((sp - frame_size) & -16ul);}#define USE_SIGRETURN		0#define USE_RT_SIGRETURN	1static intgen_return_code(unsigned char *codemem, unsigned int use_rt_sigreturn){	unsigned int retcall;	int err = 0;#if 0	/* Ignoring SA_RESTORER for now; it's supposed to be obsolete,	 * and the xtensa glibc doesn't use it.	 */	if (ka->sa.sa_flags & SA_RESTORER) {		regs->pr = (unsigned long) ka->sa.sa_restorer;	} else#endif /* 0 */	{#if (__NR_sigreturn > 255) || (__NR_rt_sigreturn > 255)/* The 12-bit immediate is really split up within the 24-bit MOVI * instruction.  As long as the above system call numbers fit within * 8-bits, the following code works fine. See the Xtensa ISA for * details. */#error Generating the MOVI instruction below breaks!#endif		retcall = use_rt_sigreturn ? __NR_rt_sigreturn : __NR_sigreturn;#ifdef __XTENSA_EB__   /* Big Endian version */		/* Generate instruction:  MOVI a2, retcall */		err |= __put_user(0x22, &codemem[0]);		err |= __put_user(0x0a, &codemem[1]);		err |= __put_user(retcall, &codemem[2]);		/* Generate instruction:  SYSCALL */		err |= __put_user(0x00, &codemem[3]);		err |= __put_user(0x05, &codemem[4]);		err |= __put_user(0x00, &codemem[5]);#elif defined __XTENSA_EL__   /* Little Endian version */		/* Generate instruction:  MOVI a2, retcall */		err |= __put_user(0x22, &codemem[0]);		err |= __put_user(0xa0, &codemem[1]);		err |= __put_user(retcall, &codemem[2]);		/* Generate instruction:  SYSCALL */		err |= __put_user(0x00, &codemem[3]);		err |= __put_user(0x50, &codemem[4]);		err |= __put_user(0x00, &codemem[5]);#else#error Must use compiler for Xtensa processors.#endif	}	/* Flush generated code out of the data cache */	if (err == 0)		__flush_invalidate_cache_range((unsigned long)codemem, 6UL);	return err;}static voidset_thread_state(struct pt_regs *regs, void *stack, unsigned char *retaddr,	void *handler, unsigned long arg1, void *arg2, void *arg3){	/* Set up registers for signal handler */	start_thread(regs, (unsigned long) handler, (unsigned long) stack);	/* Set up a stack frame for a call4	 * Note: PS.CALLINC is set to one by start_thread	 */	regs->areg[4] = (((unsigned long) retaddr) & 0x3fffffff) | 0x40000000;	regs->areg[6] = arg1;	regs->areg[7] = (unsigned long) arg2;	regs->areg[8] = (unsigned long) arg3;}static void setup_frame(int sig, struct k_sigaction *ka,			sigset_t *set, struct pt_regs *regs){	struct sigframe *frame;	int err = 0;	int signal;	frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));	if (regs->depc > 64)	{		printk("!!!!!!! DEPC !!!!!!!\n");		return;	}	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))		goto give_sigsegv;	signal = current_thread_info()->exec_domain		&& current_thread_info()->exec_domain->signal_invmap		&& sig < 32		? current_thread_info()->exec_domain->signal_invmap[sig]		: sig;	err |= setup_sigcontext(&frame->sc, &frame->cpstate, regs, set->sig[0]);	if (_NSIG_WORDS > 1) {		err |= __copy_to_user(frame->extramask, &set->sig[1],				      sizeof(frame->extramask));	}	/* Create sys_sigreturn syscall in stack frame */	err |= gen_return_code(frame->retcode, USE_SIGRETURN);	if (err)		goto give_sigsegv;	/* Create signal handler execution context.	 * Return context not modified until this point.	 */	set_thread_state(regs, frame, frame->retcode,		ka->sa.sa_handler, signal, &frame->sc, NULL);	/* Set access mode to USER_DS.  Nomenclature is outdated, but	 * functionality is used in uaccess.h	 */	set_fs(USER_DS);#if DEBUG_SIG	printk("SIG deliver (%s:%d): signal=%d sp=%p pc=%08x\n",		current->comm, current->pid, signal, frame, regs->pc);#endif	return;give_sigsegv:	if (sig == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV, current);}static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,			   sigset_t *set, struct pt_regs *regs){	struct rt_sigframe *frame;	int err = 0;	int signal;	frame = get_sigframe(ka, regs->areg[1], sizeof(*frame));	if (regs->depc > 64)		panic ("Double exception sys_sigreturn\n");	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))		goto give_sigsegv;	signal = current_thread_info()->exec_domain		&& current_thread_info()->exec_domain->signal_invmap		&& sig < 32		? current_thread_info()->exec_domain->signal_invmap[sig]		: sig;	err |= copy_siginfo_to_user(&frame->info, info);	/* Create the ucontext.  */	err |= __put_user(0, &frame->uc.uc_flags);	err |= __put_user(0, &frame->uc.uc_link);	err |= __put_user((void *)current->sas_ss_sp,			  &frame->uc.uc_stack.ss_sp);	err |= __put_user(sas_ss_flags(regs->areg[1]),			  &frame->uc.uc_stack.ss_flags);	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);	err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->cpstate,			        regs, set->sig[0]);	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));	/* Create sys_rt_sigreturn syscall in stack frame */	err |= gen_return_code(frame->retcode, USE_RT_SIGRETURN);	if (err)		goto give_sigsegv;	/* Create signal handler execution context.	 * Return context not modified until this point.	 */	set_thread_state(regs, frame, frame->retcode,		ka->sa.sa_handler, signal, &frame->info, &frame->uc);	/* Set access mode to USER_DS.  Nomenclature is outdated, but	 * functionality is used in uaccess.h	 */	set_fs(USER_DS);#if DEBUG_SIG	printk("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08x\n",		current->comm, current->pid, signal, frame, regs->pc);#endif	return;give_sigsegv:	if (sig == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV, current);}/* * 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. */int do_signal(struct pt_regs *regs, sigset_t *oldset){	siginfo_t info;	int signr;	struct k_sigaction ka;	if (!oldset)		oldset = &current->blocked;	signr = get_signal_to_deliver(&info, &ka, regs, NULL);	/* Are we from a system call? */	if (regs->syscall >= 0) {		/* If so, check system call restarting.. */		switch (regs->areg[2]) {			case ERESTARTNOHAND:			case ERESTART_RESTARTBLOCK:				regs->areg[2] = -EINTR;				break;			case ERESTARTSYS:				if (!(ka.sa.sa_flags & SA_RESTART)) {					regs->areg[2] = -EINTR;					break;				}			/* fallthrough */			case ERESTARTNOINTR:				regs->areg[2] = regs->syscall;				regs->pc -= 3;		}	}	if (signr == 0)		return 0;		/* no signals delivered */	/* Whee!  Actually deliver the signal.  */	/* Set up the stack frame */	if (ka.sa.sa_flags & SA_SIGINFO)		setup_rt_frame(signr, &ka, &info, oldset, regs);	else		setup_frame(signr, &ka, oldset, regs);	if (ka.sa.sa_flags & SA_ONESHOT)		ka.sa.sa_handler = SIG_DFL;	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, signr);	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);	return 1;}

⌨️ 快捷键说明

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