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

📄 signal_32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  Copyright (C) 1991, 1992  Linus Torvalds * *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes */#include <linux/sched.h>#include <linux/mm.h>#include <linux/smp.h>#include <linux/kernel.h>#include <linux/signal.h>#include <linux/errno.h>#include <linux/wait.h>#include <linux/unistd.h>#include <linux/stddef.h>#include <linux/personality.h>#include <linux/suspend.h>#include <linux/ptrace.h>#include <linux/elf.h>#include <linux/binfmts.h>#include <asm/processor.h>#include <asm/ucontext.h>#include <asm/uaccess.h>#include <asm/i387.h>#include "sigframe_32.h"#define DEBUG_SIG 0#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))/* * Atomically swap in the new signal mask, and wait for a signal. */asmlinkage intsys_sigsuspend(int history0, int history1, old_sigset_t mask){	mask &= _BLOCKABLE;	spin_lock_irq(&current->sighand->siglock);	current->saved_sigmask = current->blocked;	siginitset(&current->blocked, mask);	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);	current->state = TASK_INTERRUPTIBLE;	schedule();	set_thread_flag(TIF_RESTORE_SIGMASK);	return -ERESTARTNOHAND;}asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,	      struct old_sigaction __user *oact){	struct k_sigaction new_ka, old_ka;	int ret;	if (act) {		old_sigset_t mask;		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))			return -EFAULT;		__get_user(new_ka.sa.sa_flags, &act->sa_flags);		__get_user(mask, &act->sa_mask);		siginitset(&new_ka.sa.sa_mask, mask);	}	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))			return -EFAULT;		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);	}	return ret;}asmlinkage intsys_sigaltstack(unsigned long ebx){	/* This is needed to make gcc realize it doesn't own the "struct pt_regs" */	struct pt_regs *regs = (struct pt_regs *)&ebx;	const stack_t __user *uss = (const stack_t __user *)ebx;	stack_t __user *uoss = (stack_t __user *)regs->ecx;	return do_sigaltstack(uss, uoss, regs->esp);}/* * Do a signal return; undo the signal stack. */static intrestore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax){	unsigned int err = 0;	/* Always make any pending restarted system calls return -EINTR */	current_thread_info()->restart_block.fn = do_no_restart_syscall;#define COPY(x)		err |= __get_user(regs->x, &sc->x)#define COPY_SEG(seg)							\	{ unsigned short tmp;						\	  err |= __get_user(tmp, &sc->seg);				\	  regs->x##seg = tmp; }#define COPY_SEG_STRICT(seg)						\	{ unsigned short tmp;						\	  err |= __get_user(tmp, &sc->seg);				\	  regs->x##seg = tmp|3; }#define GET_SEG(seg)							\	{ unsigned short tmp;						\	  err |= __get_user(tmp, &sc->seg);				\	  loadsegment(seg,tmp); }#define	FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_RF |		 \			 X86_EFLAGS_OF | X86_EFLAGS_DF |		 \			 X86_EFLAGS_TF | X86_EFLAGS_SF | X86_EFLAGS_ZF | \			 X86_EFLAGS_AF | X86_EFLAGS_PF | X86_EFLAGS_CF)	GET_SEG(gs);	COPY_SEG(fs);	COPY_SEG(es);	COPY_SEG(ds);	COPY(edi);	COPY(esi);	COPY(ebp);	COPY(esp);	COPY(ebx);	COPY(edx);	COPY(ecx);	COPY(eip);	COPY_SEG_STRICT(cs);	COPY_SEG_STRICT(ss);		{		unsigned int tmpflags;		err |= __get_user(tmpflags, &sc->eflags);		regs->eflags = (regs->eflags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);		regs->orig_eax = -1;		/* disable syscall checks */	}	{		struct _fpstate __user * buf;		err |= __get_user(buf, &sc->fpstate);		if (buf) {			if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))				goto badframe;			err |= restore_i387(buf);		} else {			struct task_struct *me = current;			if (used_math()) {				clear_fpu(me);				clear_used_math();			}		}	}	err |= __get_user(*peax, &sc->eax);	return err;badframe:	return 1;}asmlinkage int sys_sigreturn(unsigned long __unused){	struct pt_regs *regs = (struct pt_regs *) &__unused;	struct sigframe __user *frame = (struct sigframe __user *)(regs->esp - 8);	sigset_t set;	int eax;	if (!access_ok(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, &eax))		goto badframe;	return eax;badframe:	if (show_unhandled_signals && printk_ratelimit())		printk("%s%s[%d] bad frame in sigreturn frame:%p eip:%lx"		       " esp:%lx oeax:%lx\n",		    task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,		    current->comm, task_pid_nr(current), frame, regs->eip,		    regs->esp, regs->orig_eax);	force_sig(SIGSEGV, current);	return 0;}	asmlinkage int sys_rt_sigreturn(unsigned long __unused){	struct pt_regs *regs = (struct pt_regs *) &__unused;	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(regs->esp - 4);	sigset_t set;	int eax;	if (!access_ok(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, &eax))		goto badframe;	if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->esp) == -EFAULT)		goto badframe;	return eax;badframe:	force_sig(SIGSEGV, current);	return 0;}	/* * Set up a signal frame. */static intsetup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,		 struct pt_regs *regs, unsigned long mask){	int tmp, err = 0;	err |= __put_user(regs->xfs, (unsigned int __user *)&sc->fs);	savesegment(gs, tmp);	err |= __put_user(tmp, (unsigned int __user *)&sc->gs);	err |= __put_user(regs->xes, (unsigned int __user *)&sc->es);	err |= __put_user(regs->xds, (unsigned int __user *)&sc->ds);	err |= __put_user(regs->edi, &sc->edi);	err |= __put_user(regs->esi, &sc->esi);	err |= __put_user(regs->ebp, &sc->ebp);	err |= __put_user(regs->esp, &sc->esp);	err |= __put_user(regs->ebx, &sc->ebx);	err |= __put_user(regs->edx, &sc->edx);	err |= __put_user(regs->ecx, &sc->ecx);	err |= __put_user(regs->eax, &sc->eax);	err |= __put_user(current->thread.trap_no, &sc->trapno);	err |= __put_user(current->thread.error_code, &sc->err);	err |= __put_user(regs->eip, &sc->eip);	err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs);	err |= __put_user(regs->eflags, &sc->eflags);	err |= __put_user(regs->esp, &sc->esp_at_signal);	err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss);	tmp = save_i387(fpstate);	if (tmp < 0)	  err = 1;	else	  err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);	/* non-iBCS2 extensions.. */	err |= __put_user(mask, &sc->oldmask);	err |= __put_user(current->thread.cr2, &sc->cr2);	return err;}/* * Determine which stack to use.. */static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size){	unsigned long esp;	/* Default to using normal stack */	esp = regs->esp;	/* This is the X/Open sanctioned signal stack switching.  */	if (ka->sa.sa_flags & SA_ONSTACK) {		if (sas_ss_flags(esp) == 0)			esp = current->sas_ss_sp + current->sas_ss_size;	}	/* This is the legacy signal stack switching. */	else if ((regs->xss & 0xffff) != __USER_DS &&		 !(ka->sa.sa_flags & SA_RESTORER) &&		 ka->sa.sa_restorer) {		esp = (unsigned long) ka->sa.sa_restorer;	}	esp -= frame_size;	/* Align the stack pointer according to the i386 ABI,	 * i.e. so that on function entry ((sp + 4) & 15) == 0. */	esp = ((esp + 4) & -16ul) - 4;	return (void __user *) esp;}/* These symbols are defined with the addresses in the vsyscall page.   See vsyscall-sigreturn.S.  */extern void __user __kernel_sigreturn;extern void __user __kernel_rt_sigreturn;static int setup_frame(int sig, struct k_sigaction *ka,		       sigset_t *set, struct pt_regs * regs){	void __user *restorer;	struct sigframe __user *frame;	int err = 0;	int usig;	frame = get_sigframe(ka, regs, sizeof(*frame));

⌨️ 快捷键说明

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