📄 signal_32.c
字号:
/* * 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(¤t->sighand->siglock); current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->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(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->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(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->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 + -