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

📄 signal32.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Setup the signal information.  Solaris expects a bunch of	 * information to be passed to the signal handler, we don't provide	 * that much currently, should use siginfo.	 */	err |= __put_user(signr, &si->siginfo.signo);	err |= __put_user(SVR4_SINOINFO, &si->siginfo.code);	if (err)		goto sigsegv;	regs->u_regs[UREG_FP] = (unsigned long) sfp;	regs->tpc = (unsigned long) sa->sa_handler;	regs->tnpc = (regs->tpc + 4);	if (test_thread_flag(TIF_32BIT)) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	/* Arguments passed to signal handler */	if (regs->u_regs[14]){		struct reg_window32 __user *rw = (struct reg_window32 __user *)			(regs->u_regs[14] & 0x00000000ffffffffUL);		err |= __put_user(signr, &rw->ins[0]);		err |= __put_user((u64)si, &rw->ins[1]);		err |= __put_user((u64)uc, &rw->ins[2]);		err |= __put_user((u64)sfp, &rw->ins[6]);	/* frame pointer */		if (err)			goto sigsegv;		regs->u_regs[UREG_I0] = signr;		regs->u_regs[UREG_I1] = (u32)(u64) si;		regs->u_regs[UREG_I2] = (u32)(u64) uc;	}	return;sigsegv:	force_sigsegv(signr, current);}asmlinkage intsvr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs){	svr4_gregset_t  __user *gr;	svr4_mcontext_t __user *mc;	svr4_sigset_t setv;	int i, err;	u32 psr;	synchronize_user_stack();	save_and_clear_fpu();		if (get_thread_wsaved())		do_exit(SIGSEGV);	err = clear_user(uc, sizeof(*uc));	/* Setup convenience variables */	mc = &uc->mcontext;	gr = &mc->greg;	setv.sigbits[0] = current->blocked.sig[0];	setv.sigbits[1] = (current->blocked.sig[0] >> 32);	if (_NSIG_WORDS >= 2) {		setv.sigbits[2] = current->blocked.sig[1];		setv.sigbits[3] = (current->blocked.sig[1] >> 32);		err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t));	} else		err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned));	/* Store registers */	if (test_thread_flag(TIF_32BIT)) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	err |= __put_user(regs->tpc, &uc->mcontext.greg[SVR4_PC]);	err |= __put_user(regs->tnpc, &uc->mcontext.greg[SVR4_NPC]);	psr = tstate_to_psr(regs->tstate) & ~PSR_EF;		   	if (current_thread_info()->fpsaved[0] & FPRS_FEF)		psr |= PSR_EF;	err |= __put_user(psr, &uc->mcontext.greg[SVR4_PSR]);	err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]);		/* Copy g[1..7] and o[0..7] registers */	for (i = 0; i < 7; i++)		err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);	for (i = 0; i < 8; i++)		err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);	/* Setup sigaltstack */	err |= __put_user(current->sas_ss_sp, &uc->stack.sp);	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags);	err |= __put_user(current->sas_ss_size, &uc->stack.size);	/* The register file is not saved	 * we have already stuffed all of it with sync_user_stack	 */	return (err ? -EFAULT : 0);}/* Set the context for a svr4 application, this is Solaris way to sigreturn */asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs){	svr4_gregset_t  __user *gr;	mm_segment_t old_fs;	u32 pc, npc, psr, u_ss_sp;	sigset_t set;	svr4_sigset_t setv;	int i, err;	stack_t st;		/* Fixme: restore windows, or is this already taken care of in	 * svr4_setup_frame when sync_user_windows is done?	 */	flush_user_windows();		if (get_thread_wsaved())		goto sigsegv;	if (((unsigned long) c) & 3){		printk("Unaligned structure passed\n");		goto sigsegv;	}	if (!__access_ok(c, sizeof(*c))) {		/* Miguel, add nice debugging msg _here_. ;-) */		goto sigsegv;	}	/* Check for valid PC and nPC */	gr = &c->mcontext.greg;	err = __get_user(pc, &((*gr)[SVR4_PC]));	err |= __get_user(npc, &((*gr)[SVR4_NPC]));	if ((pc | npc) & 3)		goto sigsegv;		/* Retrieve information from passed ucontext */	/* note that nPC is ored a 1, this is used to inform entry.S */	/* that we don't want it to mess with our PC and nPC */		err |= copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t));	set.sig[0] = setv.sigbits[0] | (((long)setv.sigbits[1]) << 32);	if (_NSIG_WORDS >= 2)		set.sig[1] = setv.sigbits[2] | (((long)setv.sigbits[3]) << 32);		err |= __get_user(u_ss_sp, &c->stack.sp);	st.ss_sp = compat_ptr(u_ss_sp);	err |= __get_user(st.ss_flags, &c->stack.flags);	err |= __get_user(st.ss_size, &c->stack.size);	if (err)		goto sigsegv;			/* It is more difficult to avoid calling this function than to	   call it and ignore errors.  */	old_fs = get_fs();	set_fs(KERNEL_DS);	do_sigaltstack((stack_t __user *) &st, NULL, regs->u_regs[UREG_I6]);	set_fs(old_fs);		sigdelsetmask(&set, ~_BLOCKABLE);	spin_lock_irq(&current->sighand->siglock);	current->blocked = set;	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);	regs->tpc = pc;	regs->tnpc = npc | 1;	if (test_thread_flag(TIF_32BIT)) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	err |= __get_user(regs->y, &((*gr)[SVR4_Y]));	err |= __get_user(psr, &((*gr)[SVR4_PSR]));	regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);	regs->tstate |= psr_to_tstate_icc(psr);	/* Restore g[1..7] and o[0..7] registers */	for (i = 0; i < 7; i++)		err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i);	for (i = 0; i < 8; i++)		err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i);	if (err)		goto sigsegv;	return -EINTR;sigsegv:	return -EFAULT;}static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,			     unsigned long signr, sigset_t *oldset,			     siginfo_t *info){	struct rt_signal_frame32 __user *sf;	int sigframe_size;	u32 psr;	int i, err;	compat_sigset_t seta;	/* 1. Make sure everything is clean */	synchronize_user_stack();	save_and_clear_fpu();		sigframe_size = RT_ALIGNEDSZ;	if (!(current_thread_info()->fpsaved[0] & FPRS_FEF))		sigframe_size -= sizeof(__siginfo_fpu_t);	sf = (struct rt_signal_frame32 __user *)		get_sigframe(&ka->sa, regs, sigframe_size);		if (invalid_frame_pointer(sf, sigframe_size))		goto sigill;	if (get_thread_wsaved() != 0)		goto sigill;	/* 2. Save the current process state */	if (test_thread_flag(TIF_32BIT)) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	err  = put_user(regs->tpc, &sf->regs.pc);	err |= __put_user(regs->tnpc, &sf->regs.npc);	err |= __put_user(regs->y, &sf->regs.y);	psr = tstate_to_psr(regs->tstate);	if (current_thread_info()->fpsaved[0] & FPRS_FEF)		psr |= PSR_EF;	err |= __put_user(psr, &sf->regs.psr);	for (i = 0; i < 16; i++)		err |= __put_user(regs->u_regs[i], &sf->regs.u_regs[i]);	err |= __put_user(sizeof(siginfo_extra_v8plus_t), &sf->extra_size);	err |= __put_user(SIGINFO_EXTRA_V8PLUS_MAGIC, &sf->v8plus.g_upper[0]);	for (i = 1; i < 16; i++)		err |= __put_user(((u32 *)regs->u_regs)[2*i],				  &sf->v8plus.g_upper[i]);	err |= __put_user((regs->tstate & TSTATE_ASI) >> 24UL,			  &sf->v8plus.asi);	if (psr & PSR_EF) {		err |= save_fpu_state32(regs, &sf->fpu_state);		err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save);	} else {		err |= __put_user(0, &sf->fpu_save);	}	/* Update the siginfo structure.  */	err |= copy_siginfo_to_user32(&sf->info, info);		/* Setup sigaltstack */	err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp);	err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags);	err |= __put_user(current->sas_ss_size, &sf->stack.ss_size);	switch (_NSIG_WORDS) {	case 4: seta.sig[7] = (oldset->sig[3] >> 32);		seta.sig[6] = oldset->sig[3];	case 3: seta.sig[5] = (oldset->sig[2] >> 32);		seta.sig[4] = oldset->sig[2];	case 2: seta.sig[3] = (oldset->sig[1] >> 32);		seta.sig[2] = oldset->sig[1];	case 1: seta.sig[1] = (oldset->sig[0] >> 32);		seta.sig[0] = oldset->sig[0];	}	err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t));	err |= copy_in_user((u32 __user *)sf,			    (u32 __user *)(regs->u_regs[UREG_FP]),			    sizeof(struct reg_window32));	if (err)		goto sigsegv;		/* 3. signal handler back-trampoline and parameters */	regs->u_regs[UREG_FP] = (unsigned long) sf;	regs->u_regs[UREG_I0] = signr;	regs->u_regs[UREG_I1] = (unsigned long) &sf->info;	regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;	/* 4. signal handler */	regs->tpc = (unsigned long) ka->sa.sa_handler;	regs->tnpc = (regs->tpc + 4);	if (test_thread_flag(TIF_32BIT)) {		regs->tpc &= 0xffffffff;		regs->tnpc &= 0xffffffff;	}	/* 5. return to kernel instructions */	if (ka->ka_restorer)		regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;	else {		/* Flush instruction space. */		unsigned long address = ((unsigned long)&(sf->insns[0]));		pgd_t *pgdp = pgd_offset(current->mm, address);		pud_t *pudp = pud_offset(pgdp, address);		pmd_t *pmdp = pmd_offset(pudp, address);		pte_t *ptep;		regs->u_regs[UREG_I7] = (unsigned long) (&(sf->insns[0]) - 2);			/* mov __NR_rt_sigreturn, %g1 */		err |= __put_user(0x82102065, &sf->insns[0]);		/* t 0x10 */		err |= __put_user(0x91d02010, &sf->insns[1]);		if (err)			goto sigsegv;		preempt_disable();		ptep = pte_offset_map(pmdp, address);		if (pte_present(*ptep)) {			unsigned long page = (unsigned long)				page_address(pte_page(*ptep));			wmb();			__asm__ __volatile__("flush	%0 + %1"					     : /* no outputs */					     : "r" (page),					       "r" (address & (PAGE_SIZE - 1))					     : "memory");		}		pte_unmap(ptep);		preempt_enable();	}	return;sigill:	do_exit(SIGILL);sigsegv:	force_sigsegv(signr, current);}static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,				   siginfo_t *info,				   sigset_t *oldset, struct pt_regs *regs,				   int svr4_signal){	if (svr4_signal)		setup_svr4_frame32(&ka->sa, regs->tpc, regs->tnpc,				   regs, signr, oldset);	else {		if (ka->sa.sa_flags & SA_SIGINFO)			setup_rt_frame32(ka, regs, signr, oldset, info);		else if (test_thread_flag(TIF_NEWSIGNALS))			new_setup_frame32(ka, regs, signr, oldset);		else			setup_frame32(&ka->sa, regs, signr, oldset, info);	}	spin_lock_irq(&current->sighand->siglock);	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);	if (!(ka->sa.sa_flags & SA_NOMASK))		sigaddset(&current->blocked,signr);	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);}static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,				     struct sigaction *sa){	switch (regs->u_regs[UREG_I0]) {	case ERESTART_RESTARTBLOCK:	case ERESTARTNOHAND:	no_system_call_restart:		regs->u_regs[UREG_I0] = EINTR;		regs->tstate |= TSTATE_ICARRY;		break;	case ERESTARTSYS:		if (!(sa->sa_flags & SA_RESTART))			goto no_system_call_restart;		/* fallthrough */	case ERESTARTNOINTR:		regs->u_regs[UREG_I0] = orig_i0;		regs->tpc -= 4;		regs->tnpc -= 4;	}}/* 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. */int do_signal32(sigset_t *oldset, struct pt_regs * regs,		unsigned long orig_i0, int restart_syscall){	siginfo_t info;	struct signal_deliver_cookie cookie;	struct k_sigaction ka;	int signr;	int svr4_signal = current->personality == PER_SVR4;		cookie.restart_syscall = restart_syscall;	cookie.orig_i0 = orig_i0;	signr = get_signal_to_deliver(&info, &ka, regs, &cookie);	if (signr > 0) {		if (cookie.restart_syscall)			syscall_restart32(orig_i0, regs, &ka.sa);		handle_signal32(signr, &ka, &info, oldset,				regs, svr4_signal);		return 1;	}	if (cookie.restart_syscall &&	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||	     regs->u_regs[UREG_I0] == ERESTARTSYS ||	     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {		/* replay the system call when we are done */		regs->u_regs[UREG_I0] = cookie.orig_i0;		regs->tpc -= 4;		regs->tnpc -= 4;	}	if (cookie.restart_syscall &&	    regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {		regs->u_regs[UREG_G1] = __NR_restart_syscall;		regs->tpc -= 4;		regs->tnpc -= 4;	}	return 0;}struct sigstack32 {	u32 the_stack;	int cur_status;};asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp){	struct sigstack32 __user *ssptr =		(struct sigstack32 __user *)((unsigned long)(u_ssptr));	struct sigstack32 __user *ossptr =		(struct sigstack32 __user *)((unsigned long)(u_ossptr));	int ret = -EFAULT;	/* First see if old state is wanted. */	if (ossptr) {		if (put_user(current->sas_ss_sp + current->sas_ss_size,			     &ossptr->the_stack) ||		    __put_user(on_sig_stack(sp), &ossptr->cur_status))			goto out;	}		/* Now see if we want to update the new state. */	if (ssptr) {		u32 ss_sp;		if (get_user(ss_sp, &ssptr->the_stack))			goto out;		/* If the current stack was set with sigaltstack, don't		 * swap stacks while we are on it.		 */		ret = -EPERM;		if (current->sas_ss_sp && on_sig_stack(sp))			goto out;					/* Since we don't know the extent of the stack, and we don't		 * track onstack-ness, but rather calculate it, we must		 * presume a size.  Ho hum this interface is lossy.		 */		current->sas_ss_sp = (unsigned long)ss_sp - SIGSTKSZ;		current->sas_ss_size = SIGSTKSZ;	}		ret = 0;out:	return ret;}asmlinkage long do_sys32_sigaltstack(u32 ussa, u32 uossa, unsigned long sp){	stack_t uss, uoss;	u32 u_ss_sp = 0;	int ret;	mm_segment_t old_fs;	stack_t32 __user *uss32 = compat_ptr(ussa);	stack_t32 __user *uoss32 = compat_ptr(uossa);		if (ussa && (get_user(u_ss_sp, &uss32->ss_sp) ||		    __get_user(uss.ss_flags, &uss32->ss_flags) ||		    __get_user(uss.ss_size, &uss32->ss_size)))		return -EFAULT;	uss.ss_sp = compat_ptr(u_ss_sp);	old_fs = get_fs();	set_fs(KERNEL_DS);	ret = do_sigaltstack(ussa ? (stack_t __user *) &uss : NULL,			     uossa ? (stack_t __user *) &uoss : NULL, sp);	set_fs(old_fs);	if (!ret && uossa && (put_user(ptr_to_compat(uoss.ss_sp), &uoss32->ss_sp) ||		    __put_user(uoss.ss_flags, &uoss32->ss_flags) ||		    __put_user(uoss.ss_size, &uoss32->ss_size)))		return -EFAULT;	return ret;}

⌨️ 快捷键说明

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