📄 compat_signal.c
字号:
{ stack_t kss, koss; unsigned long ss_sp; int ret, err = 0; mm_segment_t old_fs = get_fs(); if (uss) { if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) return -EFAULT; err |= __get_user(ss_sp, &uss->ss_sp); err |= __get_user(kss.ss_size, &uss->ss_size); err |= __get_user(kss.ss_flags, &uss->ss_flags); if (err) return -EFAULT; kss.ss_sp = (void __user *) ss_sp; } set_fs (KERNEL_DS); ret = do_sigaltstack((stack_t __user *) (uss ? &kss : NULL), (stack_t __user *) (uoss ? &koss : NULL), regs->gprs[15]); set_fs (old_fs); if (!ret && uoss) { if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) return -EFAULT; ss_sp = (unsigned long) koss.ss_sp; err |= __put_user(ss_sp, &uoss->ss_sp); err |= __put_user(koss.ss_size, &uoss->ss_size); err |= __put_user(koss.ss_flags, &uoss->ss_flags); if (err) return -EFAULT; } return ret;}static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs){ _s390_regs_common32 regs32; int err, i; regs32.psw.mask = PSW32_MASK_MERGE(PSW32_USER_BITS, (__u32)(regs->psw.mask >> 32)); regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr; for (i = 0; i < NUM_GPRS; i++) regs32.gprs[i] = (__u32) regs->gprs[i]; save_access_regs(current->thread.acrs); memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs)); err = __copy_to_user(&sregs->regs, ®s32, sizeof(regs32)); if (err) return err; save_fp_regs(¤t->thread.fp_regs); /* s390_fp_regs and _s390_fp_regs32 are the same ! */ return __copy_to_user(&sregs->fpregs, ¤t->thread.fp_regs, sizeof(_s390_fp_regs32));}static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs){ _s390_regs_common32 regs32; int err, i; /* Alwys make any pending restarted system call return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; err = __copy_from_user(®s32, &sregs->regs, sizeof(regs32)); if (err) return err; regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask, (__u64)regs32.psw.mask << 32); regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = (__u64) regs32.gprs[i]; memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs)); restore_access_regs(current->thread.acrs); err = __copy_from_user(¤t->thread.fp_regs, &sregs->fpregs, sizeof(_s390_fp_regs32)); current->thread.fp_regs.fpc &= FPC_VALID_MASK; if (err) return err; restore_fp_regs(¤t->thread.fp_regs); regs->trap = -1; /* disable syscall checks */ return 0;}asmlinkage long sys32_sigreturn(struct pt_regs *regs){ sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; sigset_t set; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32)) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); if (restore_sigregs32(regs, &frame->sregs)) goto badframe; return regs->gprs[2];badframe: force_sig(SIGSEGV, current); return 0;}asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs){ rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; sigset_t set; stack_t st; __u32 ss_sp; int err; mm_segment_t old_fs = get_fs(); 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_sigregs32(regs, &frame->uc.uc_mcontext)) goto badframe; err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp); st.ss_sp = compat_ptr(ss_sp); err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size); err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags); if (err) goto badframe; /* It is more difficult to avoid calling this function than to call it and ignore errors. */ set_fs (KERNEL_DS); do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]); set_fs (old_fs); return regs->gprs[2];badframe: force_sig(SIGSEGV, current); return 0;} /* * Set up a signal frame. *//* * 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 sp; /* Default to using normal stack */ sp = (unsigned long) A(regs->gprs[15]); /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (! on_sig_stack(sp)) sp = current->sas_ss_sp + current->sas_ss_size; } /* This is the legacy signal stack switching. */ else if (!user_mode(regs) && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) { sp = (unsigned long) ka->sa.sa_restorer; } return (void __user *)((sp - frame_size) & -8ul);}static inline int map_signal(int sig){ if (current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32) return current_thread_info()->exec_domain->signal_invmap[sig]; else return sig;}static void setup_frame32(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs * regs){ sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32)); if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32))) goto give_sigsegv; if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32)) goto give_sigsegv; if (save_sigregs32(regs, &frame->sregs)) goto give_sigsegv; if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs)) goto give_sigsegv; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { regs->gprs[14] = (__u64) ka->sa.sa_restorer; } else { regs->gprs[14] = (__u64) frame->retcode; if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, (u16 __user *)(frame->retcode))) goto give_sigsegv; } /* Set up backchain. */ if (__put_user(regs->gprs[15], (unsigned int __user *) frame)) goto give_sigsegv; /* Set up registers for signal handler */ regs->gprs[15] = (__u64) frame; regs->psw.addr = (__u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); regs->gprs[3] = (__u64) &frame->sc; /* We forgot to include these in the sigcontext. To avoid breaking binary compatibility, they are passed as args. */ regs->gprs[4] = current->thread.trap_no; regs->gprs[5] = current->thread.prot_addr; /* Place signal number on stack to allow backtrace from handler. */ if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) goto give_sigsegv; return;give_sigsegv: force_sigsegv(sig, current);}static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs){ int err = 0; rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32)); if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32))) goto give_sigsegv; if (copy_siginfo_to_user32(&frame->info, info)) 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->gprs[15]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= save_sigregs32(regs, &frame->uc.uc_mcontext); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { regs->gprs[14] = (__u64) ka->sa.sa_restorer; } else { regs->gprs[14] = (__u64) frame->retcode; err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, (u16 __user *)(frame->retcode)); } /* Set up backchain. */ if (__put_user(regs->gprs[15], (unsigned int __user *) frame)) goto give_sigsegv; /* Set up registers for signal handler */ regs->gprs[15] = (__u64) frame; regs->psw.addr = (__u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); regs->gprs[3] = (__u64) &frame->info; regs->gprs[4] = (__u64) &frame->uc; return;give_sigsegv: force_sigsegv(sig, current);}/* * OK, we're invoking a handler */ voidhandle_signal32(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs * regs){ /* Set up the stack frame */ if (ka->sa.sa_flags & SA_SIGINFO) setup_rt_frame32(sig, ka, info, oldset, regs); else setup_frame32(sig, ka, oldset, regs); spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -