📄 ia32_signal.c
字号:
struct pt_regs tregs; frame = (struct rt_sigframe __user *)(regs->rsp - 4); 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 (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &eax)) goto badframe; tregs = *regs; if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT) goto badframe; return eax;badframe: signal_fault(regs,frame,"32bit rt sigreturn"); return 0;} /* * Set up a signal frame. */static intia32_setup_sigcontext(struct sigcontext_ia32 __user *sc, struct _fpstate_ia32 __user *fpstate, struct pt_regs *regs, unsigned int mask){ int tmp, err = 0; tmp = 0; __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp)); err |= __put_user(tmp, (unsigned int __user *)&sc->gs); __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp)); err |= __put_user(tmp, (unsigned int __user *)&sc->fs); __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp)); err |= __put_user(tmp, (unsigned int __user *)&sc->ds); __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp)); err |= __put_user(tmp, (unsigned int __user *)&sc->es); err |= __put_user((u32)regs->rdi, &sc->edi); err |= __put_user((u32)regs->rsi, &sc->esi); err |= __put_user((u32)regs->rbp, &sc->ebp); err |= __put_user((u32)regs->rsp, &sc->esp); err |= __put_user((u32)regs->rbx, &sc->ebx); err |= __put_user((u32)regs->rdx, &sc->edx); err |= __put_user((u32)regs->rcx, &sc->ecx); err |= __put_user((u32)regs->rax, &sc->eax); err |= __put_user((u32)regs->cs, &sc->cs); err |= __put_user((u32)regs->ss, &sc->ss); err |= __put_user(current->thread.trap_no, &sc->trapno); err |= __put_user(current->thread.error_code, &sc->err); err |= __put_user((u32)regs->rip, &sc->eip); err |= __put_user((u32)regs->eflags, &sc->eflags); err |= __put_user((u32)regs->rsp, &sc->esp_at_signal); tmp = save_i387_ia32(current, fpstate, regs, 0); if (tmp < 0) err = -EFAULT; else { clear_used_math(); stts(); err |= __put_user(ptr_to_compat(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 void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size){ unsigned long rsp; /* Default to using normal stack */ rsp = regs->rsp; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(rsp) == 0) rsp = current->sas_ss_sp + current->sas_ss_size; } /* This is the legacy signal stack switching. */ else if ((regs->ss & 0xffff) != __USER_DS && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) { rsp = (unsigned long) ka->sa.sa_restorer; } rsp -= frame_size; /* Align the stack pointer according to the i386 ABI, * i.e. so that on function entry ((sp + 4) & 15) == 0. */ rsp = ((rsp + 4) & -16ul) - 4; return (void __user *) rsp;}int ia32_setup_frame(int sig, struct k_sigaction *ka, compat_sigset_t *set, struct pt_regs * regs){ struct sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= __put_user(sig, &frame->sig); if (err) goto give_sigsegv; err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]); if (err) goto give_sigsegv; if (_COMPAT_NSIG_WORDS > 1) { err |= __copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask)); } if (err) goto give_sigsegv; /* Return stub is in 32bit vsyscall page */ { void __user *restorer; if (current->binfmt->hasvdso) restorer = VSYSCALL32_SIGRETURN; else restorer = (void *)&frame->retcode; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); } /* These are actually not used anymore, but left because some gdb versions depend on them as a marker. */ { /* copy_to_user optimizes that into a single 8 byte store */ static const struct { u16 poplmovl; u32 val; u16 int80; u16 pad; } __attribute__((packed)) code = { 0xb858, /* popl %eax ; movl $...,%eax */ __NR_ia32_sigreturn, 0x80cd, /* int $0x80 */ 0, }; err |= __copy_to_user(frame->retcode, &code, 8); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->rsp = (unsigned long) frame; regs->rip = (unsigned long) ka->sa.sa_handler; /* Make -mregparm=3 work */ regs->rax = sig; regs->rdx = 0; regs->rcx = 0; asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); regs->cs = __USER32_CS; regs->ss = __USER32_DS; set_fs(USER_DS); regs->eflags &= ~TF_MASK; if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP);#if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n", current->comm, current->pid, frame, regs->rip, frame->pretcode);#endif return 0;give_sigsegv: force_sigsegv(sig, current); return -EFAULT;}int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, compat_sigset_t *set, struct pt_regs * regs){ struct rt_sigframe __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; { struct exec_domain *ed = current_thread_info()->exec_domain; err |= __put_user((ed && ed->signal_invmap && sig < 32 ? ed->signal_invmap[sig] : sig), &frame->sig); } err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo); err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc); err |= copy_siginfo_to_user32(&frame->info, info); if (err) goto give_sigsegv; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->rsp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; { void __user *restorer = VSYSCALL32_RTSIGRETURN; if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; err |= __put_user(ptr_to_compat(restorer), &frame->pretcode); } /* This is movl $,%eax ; int $0x80 */ /* Not actually used anymore, but left because some gdb versions need it. */ { /* __copy_to_user optimizes that into a single 8 byte store */ static const struct { u8 movl; u32 val; u16 int80; u16 pad; u8 pad2; } __attribute__((packed)) code = { 0xb8, __NR_ia32_rt_sigreturn, 0x80cd, 0, }; err |= __copy_to_user(frame->retcode, &code, 8); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->rsp = (unsigned long) frame; regs->rip = (unsigned long) ka->sa.sa_handler; /* Make -mregparm=3 work */ regs->rax = sig; regs->rdx = (unsigned long) &frame->info; regs->rcx = (unsigned long) &frame->uc; /* Make -mregparm=3 work */ regs->rax = sig; regs->rdx = (unsigned long) &frame->info; regs->rcx = (unsigned long) &frame->uc; asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); regs->cs = __USER32_CS; regs->ss = __USER32_DS; set_fs(USER_DS); regs->eflags &= ~TF_MASK; if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP);#if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n", current->comm, current->pid, frame, regs->rip, frame->pretcode);#endif return 0;give_sigsegv: force_sigsegv(sig, current); return -EFAULT;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -