📄 signal32.c
字号:
if (err) return -EFAULT; } set_fs(KERNEL_DS); ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL, uoss ? (stack_t __user *)&koss : NULL, usp); set_fs(old_fs); if (!ret && uoss) { if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) return -EFAULT; sp = (int) (unsigned long) koss.ss_sp; err |= __put_user(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;}int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from){ int err; if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; /* If you change siginfo_t structure, please be sure this code is fixed accordingly. It should never copy any pad contained in the structure to avoid security leaks, but must copy the generic 3 ints plus the relevant union member. This routine must convert siginfo from 64bit to 32bit as well at the same time. */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); err |= __put_user((short)from->si_code, &to->si_code); if (from->si_code < 0) err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); else { switch (from->si_code >> 16) { case __SI_TIMER >> 16: err |= __put_user(from->si_tid, &to->si_tid); err |= __put_user(from->si_overrun, &to->si_overrun); err |= __put_user(from->si_int, &to->si_int); break; case __SI_CHLD >> 16: err |= __put_user(from->si_utime, &to->si_utime); err |= __put_user(from->si_stime, &to->si_stime); err |= __put_user(from->si_status, &to->si_status); default: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); break; case __SI_FAULT >> 16: err |= __put_user((unsigned long)from->si_addr, &to->si_addr); break; case __SI_POLL >> 16: err |= __put_user(from->si_band, &to->si_band); err |= __put_user(from->si_fd, &to->si_fd); break; case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ case __SI_MESGQ >> 16: err |= __put_user(from->si_pid, &to->si_pid); err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_int, &to->si_int); break; } } return err;}asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs){ struct sigframe32 __user *frame; sigset_t blocked; int sig; frame = (struct sigframe32 __user *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask)) goto badframe; sigdelsetmask(&blocked, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = blocked; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); sig = restore_sigcontext32(®s, &frame->sf_sc); if (sig < 0) goto badframe; else if (sig) force_sig(sig, current); /* * Don't let your children do this ... */ __asm__ __volatile__( "move\t$29, %0\n\t" "j\tsyscall_exit" :/* no outputs */ :"r" (®s)); /* Unreached */badframe: force_sig(SIGSEGV, current);}asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs){ struct rt_sigframe32 __user *frame; mm_segment_t old_fs; sigset_t set; stack_t st; s32 sp; int sig; frame = (struct rt_sigframe32 __user *) regs.regs[29]; if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext); if (sig < 0) goto badframe; else if (sig) force_sig(sig, current); /* The ucontext contains a stack32_t, so we must convert! */ if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp)) goto badframe; st.ss_sp = (void __user *)(long) sp; if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size)) goto badframe; if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags)) goto badframe; /* 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.regs[29]); set_fs(old_fs); /* * Don't let your children do this ... */ __asm__ __volatile__( "move\t$29, %0\n\t" "j\tsyscall_exit" :/* no outputs */ :"r" (®s)); /* Unreached */badframe: force_sig(SIGSEGV, current);}static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set){ struct sigframe32 __user *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn); err |= setup_sigcontext32(regs, &frame->sf_sc); err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); if (err) goto give_sigsegv; /* * Arguments to signal handler: * * a0 = signal number * a1 = 0 (should be cause) * a2 = pointer to struct sigcontext * * $25 and c0_epc point to the signal handler, $29 points to the * struct sigframe. */ regs->regs[ 4] = signr; regs->regs[ 5] = 0; regs->regs[ 6] = (unsigned long) &frame->sf_sc; regs->regs[29] = (unsigned long) frame; regs->regs[31] = (unsigned long) frame->sf_code; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", current->comm, current->pid, frame, regs->cp0_epc, regs->regs[31]); return 0;give_sigsegv: force_sigsegv(signr, current); return -EFAULT;}static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info){ struct rt_sigframe32 __user *frame; int err = 0; s32 sp; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn); /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ err |= copy_siginfo_to_user32(&frame->rs_info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_link); sp = (int) (long) current->sas_ss_sp; err |= __put_user(sp, &frame->rs_uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->regs[29]), &frame->rs_uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->rs_uc.uc_stack.ss_size); err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext); err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); if (err) goto give_sigsegv; /* * Arguments to signal handler: * * a0 = signal number * a1 = 0 (should be cause) * a2 = pointer to ucontext * * $25 and c0_epc point to the signal handler, $29 points to * the struct rt_sigframe32. */ regs->regs[ 4] = signr; regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[29] = (unsigned long) frame; regs->regs[31] = (unsigned long) frame->rs_code; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", current->comm, current->pid, frame, regs->cp0_epc, regs->regs[31]); return 0;give_sigsegv: force_sigsegv(signr, current); return -EFAULT;}/* * o32 compatibility on 64-bit kernels, without DSP ASE */struct mips_abi mips_abi_32 = { .setup_frame = setup_frame_32, .setup_rt_frame = setup_rt_frame_32, .restart = __NR_O32_restart_syscall};asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact, unsigned int sigsetsize){ struct k_sigaction new_sa, old_sa; int ret = -EINVAL; /* XXX: Don't preclude handling different sized sigset_t's. */ if (sigsetsize != sizeof(sigset_t)) goto out; if (act) { s32 handler; int err = 0; if (!access_ok(VERIFY_READ, act, sizeof(*act))) return -EFAULT; err |= __get_user(handler, &act->sa_handler); new_sa.sa.sa_handler = (void __user *)(s64)handler; err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags); err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask); if (err) return -EFAULT; } ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL); if (!ret && oact) { int err = 0; if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) return -EFAULT; err |= __put_user((u32)(u64)old_sa.sa.sa_handler, &oact->sa_handler); err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags); err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask); if (err) return -EFAULT; }out: return ret;}asmlinkage int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, unsigned int sigsetsize){ sigset_t old_set, new_set; int ret; mm_segment_t old_fs = get_fs(); if (set && get_sigset(&new_set, set)) return -EFAULT; set_fs(KERNEL_DS); ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL, oset ? (sigset_t __user *)&old_set : NULL, sigsetsize); set_fs(old_fs); if (!ret && oset && put_sigset(&old_set, oset)) return -EFAULT; return ret;}asmlinkage int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize){ int ret; sigset_t set; mm_segment_t old_fs = get_fs(); set_fs(KERNEL_DS); ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize); set_fs(old_fs); if (!ret && put_sigset(&set, uset)) return -EFAULT; return ret;}asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo){ siginfo_t info; int ret; mm_segment_t old_fs = get_fs(); if (copy_from_user(&info, uinfo, 3*sizeof(int)) || copy_from_user(info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) return -EFAULT; set_fs(KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info); set_fs(old_fs); return ret;}asmlinkage longsys32_waitid(int which, compat_pid_t pid, compat_siginfo_t __user *uinfo, int options, struct compat_rusage __user *uru){ siginfo_t info; struct rusage ru; long ret; mm_segment_t old_fs = get_fs(); info.si_signo = 0; set_fs(KERNEL_DS); ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options, uru ? (struct rusage __user *) &ru : NULL); set_fs(old_fs); if (ret < 0 || info.si_signo == 0) return ret; if (uru && (ret = put_compat_rusage(&ru, uru))) return ret; BUG_ON(info.si_code & __SI_MASK); info.si_code |= __SI_CHLD; return copy_siginfo_to_user32(uinfo, &info);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -