int compat_mc_getsockopt(struct sock *sock, int level, int optname, char __user *optval, int __user *optlen, int (*getsockopt)(struct sock *,int,int,char __user *,int __user *)) { struct compat_group_filter __user *gf32 = (void *)optval; struct group_filter __user *kgf; int __user *koptlen; u32 interface, fmode, numsrc; int klen, ulen, err; if (optname != MCAST_MSFILTER) return getsockopt(sock, level, optname, optval, optlen); koptlen = compat_alloc_user_space(sizeof(*koptlen)); if (!access_ok(VERIFY_READ, optlen, sizeof(*optlen)) || __get_user(ulen, optlen)) return -EFAULT; /* adjust len for pad */ klen = ulen + sizeof(*kgf) - sizeof(*gf32); if (klen < GROUP_FILTER_SIZE(0)) return -EINVAL; if (!access_ok(VERIFY_WRITE, koptlen, sizeof(*koptlen)) || __put_user(klen, koptlen)) return -EFAULT; /* have to allow space for previous compat_alloc_user_space, too */ kgf = compat_alloc_user_space(klen+sizeof(*optlen)); if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) || __get_user(interface, &gf32->gf_interface) || __get_user(fmode, &gf32->gf_fmode) || __get_user(numsrc, &gf32->gf_numsrc) || __put_user(interface, &kgf->gf_interface) || __put_user(fmode, &kgf->gf_fmode) || __put_user(numsrc, &kgf->gf_numsrc) || copy_in_user(&kgf->gf_group,&gf32->gf_group,sizeof(kgf->gf_group))) return -EFAULT; err = getsockopt(sock, level, optname, (char __user *)kgf, koptlen); if (err) return err; if (!access_ok(VERIFY_READ, koptlen, sizeof(*koptlen)) || __get_user(klen, koptlen)) return -EFAULT; ulen = klen - (sizeof(*kgf)-sizeof(*gf32)); if (!access_ok(VERIFY_WRITE, optlen, sizeof(*optlen)) || __put_user(ulen, optlen)) return -EFAULT; if (!access_ok(VERIFY_READ, kgf, klen) || !access_ok(VERIFY_WRITE, gf32, ulen) || __get_user(interface, &kgf->gf_interface) || __get_user(fmode, &kgf->gf_fmode) || __get_user(numsrc, &kgf->gf_numsrc) || __put_user(interface, &gf32->gf_interface) || __put_user(fmode, &gf32->gf_fmode) || __put_user(numsrc, &gf32->gf_numsrc)) return -EFAULT; if (numsrc) { int copylen; klen -= GROUP_FILTER_SIZE(0); copylen = numsrc * sizeof(gf32->gf_slist[0]); if (copylen > klen) copylen = klen; if (copy_in_user(gf32->gf_slist, kgf->gf_slist, copylen)) return -EFAULT; } return err; }
/* Copy 32-bit cmd structure to native cmd structure. */ static int get_compat_cmd(struct comedi_cmd __user *cmd, struct comedi32_cmd_struct __user *cmd32) { int err; union { unsigned int uint; compat_uptr_t uptr; } temp; /* Copy cmd structure. */ if (!access_ok(VERIFY_READ, cmd32, sizeof(*cmd32)) || !access_ok(VERIFY_WRITE, cmd, sizeof(*cmd))) return -EFAULT; err = 0; err |= __get_user(temp.uint, &cmd32->subdev); err |= __put_user(temp.uint, &cmd->subdev); err |= __get_user(temp.uint, &cmd32->flags); err |= __put_user(temp.uint, &cmd->flags); err |= __get_user(temp.uint, &cmd32->start_src); err |= __put_user(temp.uint, &cmd->start_src); err |= __get_user(temp.uint, &cmd32->start_arg); err |= __put_user(temp.uint, &cmd->start_arg); err |= __get_user(temp.uint, &cmd32->scan_begin_src); err |= __put_user(temp.uint, &cmd->scan_begin_src); err |= __get_user(temp.uint, &cmd32->scan_begin_arg); err |= __put_user(temp.uint, &cmd->scan_begin_arg); err |= __get_user(temp.uint, &cmd32->convert_src); err |= __put_user(temp.uint, &cmd->convert_src); err |= __get_user(temp.uint, &cmd32->convert_arg); err |= __put_user(temp.uint, &cmd->convert_arg); err |= __get_user(temp.uint, &cmd32->scan_end_src); err |= __put_user(temp.uint, &cmd->scan_end_src); err |= __get_user(temp.uint, &cmd32->scan_end_arg); err |= __put_user(temp.uint, &cmd->scan_end_arg); err |= __get_user(temp.uint, &cmd32->stop_src); err |= __put_user(temp.uint, &cmd->stop_src); err |= __get_user(temp.uint, &cmd32->stop_arg); err |= __put_user(temp.uint, &cmd->stop_arg); err |= __get_user(temp.uptr, &cmd32->chanlist); err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist); err |= __get_user(temp.uint, &cmd32->chanlist_len); err |= __put_user(temp.uint, &cmd->chanlist_len); err |= __get_user(temp.uptr, &cmd32->data); err |= __put_user(compat_ptr(temp.uptr), &cmd->data); err |= __get_user(temp.uint, &cmd32->data_len); err |= __put_user(temp.uint, &cmd->data_len); return err ? -EFAULT : 0; }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; int signal; frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; signal = current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->regs[15]); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; #ifdef CONFIG_VSYSCALL } else if (likely(current->mm->context.vdso)) { regs->pr = VDSO_SYM(&__kernel_rt_sigreturn); #endif } else { /* Generate return code (system call to rt_sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); err |= __put_user(OR_R0_R0, &frame->retcode[5]); err |= __put_user(OR_R0_R0, &frame->retcode[6]); err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]); regs->pr = (unsigned long) frame->retcode; flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode)); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->regs[15] = (unsigned long) frame; regs->regs[4] = signal; /* Arg for signal handler */ regs->regs[5] = (unsigned long) &frame->info; regs->regs[6] = (unsigned long) &frame->uc; if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *)ka->sa.sa_handler; err |= __get_user(regs->pc, &funcptr->text); err |= __get_user(regs->regs[12], &funcptr->GOT); } else regs->pc = (unsigned long)ka->sa.sa_handler; if (err) goto give_sigsegv; set_fs(USER_DS); pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
static void setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) { struct sigframe *frame; int err = 0; int signal; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; signal = current->exec_domain && current->exec_domain->signal_invmap && sig < 32 ? current->exec_domain->signal_invmap[sig] : sig; err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); if (_NSIG_WORDS > 1) { err |= __copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask)); } /* Set up to return from userspace. If provided, use a stub already in userspace. */ /* minus 8 is offset to cater for "rtsd r15,8" offset */ if (ka->sa.sa_flags & SA_RESTORER) { regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer-8; } else { /* Note, these encodings are _big endian_! */ /* addi r12, r0, __NR_sigreturn */ err |= __put_user(0x31800000 | __NR_sigreturn , frame->tramp + 0); /* brki r14, 0x8 */ err |= __put_user(0xb9cc0008, frame->tramp + 1); regs->gpr[GPR_LP] = (unsigned long)frame->tramp-8; flush_cache_sigtramp (regs->gpr[GPR_LP]); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->gpr[GPR_SP] = (unsigned long) frame; regs->gpr[GPR_ARG0] = signal; /* Arg for signal handler */ /* Offset of 4 to handle microblaze rtbd r14, 4 */ regs->pc = (unsigned long) ka->sa.sa_handler-4; set_fs(USER_DS); #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%08lx ra=%08lx\n", current->comm, current->pid, frame, regs->pc, ); #endif return; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); }
static int compat_r128_init(struct file *file, unsigned int cmd, unsigned long arg) { drm_r128_init32_t init32; drm_r128_init_t __user *init; if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) return -EFAULT; init = compat_alloc_user_space(sizeof(*init)); if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) || __put_user(init32.func, &init->func) || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) || __put_user(init32.is_pci, &init->is_pci) || __put_user(init32.cce_mode, &init->cce_mode) || __put_user(init32.cce_secure, &init->cce_secure) || __put_user(init32.ring_size, &init->ring_size) || __put_user(init32.usec_timeout, &init->usec_timeout) || __put_user(init32.fb_bpp, &init->fb_bpp) || __put_user(init32.front_offset, &init->front_offset) || __put_user(init32.front_pitch, &init->front_pitch) || __put_user(init32.back_offset, &init->back_offset) || __put_user(init32.back_pitch, &init->back_pitch) || __put_user(init32.depth_bpp, &init->depth_bpp) || __put_user(init32.depth_offset, &init->depth_offset) || __put_user(init32.depth_pitch, &init->depth_pitch) || __put_user(init32.span_offset, &init->span_offset) || __put_user(init32.fb_offset, &init->fb_offset) || __put_user(init32.mmio_offset, &init->mmio_offset) || __put_user(init32.ring_offset, &init->ring_offset) || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset) || __put_user(init32.buffers_offset, &init->buffers_offset) || __put_user(init32.agp_textures_offset, &init->agp_textures_offset)) return -EFAULT; return drm_ioctl(file, DRM_IOCTL_R128_INIT, (unsigned long)init); }
int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { compat_ulong_t __user *datap = compat_ptr(data); compat_ulong_t word; siginfo_t siginfo; int ret; switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: ret = access_process_vm(child, addr, &word, sizeof(word), 0); if (ret != sizeof(word)) ret = -EIO; else ret = put_user(word, datap); break; case PTRACE_POKETEXT: case PTRACE_POKEDATA: ret = access_process_vm(child, addr, &data, sizeof(data), 1); ret = (ret != sizeof(data) ? -EIO : 0); break; case PTRACE_GETEVENTMSG: ret = put_user((compat_ulong_t) child->ptrace_message, datap); break; case PTRACE_GETSIGINFO: ret = ptrace_getsiginfo(child, &siginfo); if (!ret) ret = copy_siginfo_to_user32( (struct compat_siginfo __user *) datap, &siginfo); break; case PTRACE_SETSIGINFO: memset(&siginfo, 0, sizeof siginfo); if (copy_siginfo_from_user32( &siginfo, (struct compat_siginfo __user *) datap)) ret = -EFAULT; else ret = ptrace_setsiginfo(child, &siginfo); break; #ifdef CONFIG_HAVE_ARCH_TRACEHOOK case PTRACE_GETREGSET: case PTRACE_SETREGSET: { struct iovec kiov; struct compat_iovec __user *uiov = (struct compat_iovec __user *) datap; compat_uptr_t ptr; compat_size_t len; if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov))) return -EFAULT; if (__get_user(ptr, &uiov->iov_base) || __get_user(len, &uiov->iov_len)) return -EFAULT; kiov.iov_base = compat_ptr(ptr); kiov.iov_len = len; ret = ptrace_regset(child, request, addr, &kiov); if (!ret) ret = __put_user(kiov.iov_len, &uiov->iov_len); break; } #endif default: ret = ptrace_request(child, request, addr, data); } return ret; }
int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { int err = 0, tmp; int retval = 0; /* * extract the type and number bitfields, and don't decode * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok() */ if (_IOC_TYPE(cmd) != SCULL_IOC_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > SCULL_IOC_MAXNR) return -ENOTTY; /* * the direction is a bitmask, and VERIFY_WRITE catches R/W * transfers. `Type' is user-oriented, while * access_ok is kernel-oriented, so the concept of "read" and * "write" is reversed */ if (_IOC_DIR(cmd) & _IOC_READ) err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); else if (_IOC_DIR(cmd) & _IOC_WRITE) err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); if (err) return -EFAULT; switch(cmd) { case SCULL_IOCRESET: scull_quantum = SCULL_QUANTUM; scull_qset = SCULL_QSET; break; case SCULL_IOCSQUANTUM: /* Set: arg points to the value */ if (! capable (CAP_SYS_ADMIN)) return -EPERM; retval = __get_user(scull_quantum, (int __user *)arg); break; case SCULL_IOCTQUANTUM: /* Tell: arg is the value */ if (! capable (CAP_SYS_ADMIN)) return -EPERM; scull_quantum = arg; break; case SCULL_IOCGQUANTUM: /* Get: arg is pointer to result */ retval = __put_user(scull_quantum, (int __user *)arg); break; case SCULL_IOCQQUANTUM: /* Query: return it (it's positive) */ return scull_quantum; case SCULL_IOCXQUANTUM: /* eXchange: use arg as pointer */ if (! capable (CAP_SYS_ADMIN)) return -EPERM; tmp = scull_quantum; retval = __get_user(scull_quantum, (int __user *)arg); if (retval == 0) retval = __put_user(tmp, (int __user *)arg); break; case SCULL_IOCHQUANTUM: /* sHift: like Tell + Query */ if (! capable (CAP_SYS_ADMIN)) return -EPERM; tmp = scull_quantum; scull_quantum = arg; return tmp; case SCULL_IOCSQSET: if (! capable (CAP_SYS_ADMIN)) return -EPERM; retval = __get_user(scull_qset, (int __user *)arg); break; case SCULL_IOCTQSET: if (! capable (CAP_SYS_ADMIN)) return -EPERM; scull_qset = arg; break; case SCULL_IOCGQSET: retval = __put_user(scull_qset, (int __user *)arg); break; case SCULL_IOCQQSET: return scull_qset; case SCULL_IOCXQSET: if (! capable (CAP_SYS_ADMIN)) return -EPERM; tmp = scull_qset; retval = __get_user(scull_qset, (int __user *)arg); if (retval == 0) retval = put_user(tmp, (int __user *)arg); break; case SCULL_IOCHQSET: if (! capable (CAP_SYS_ADMIN)) return -EPERM; tmp = scull_qset; scull_qset = arg; return tmp; /* * The following two change the buffer size for scullpipe. * The scullpipe device uses this same ioctl method, just to * write less code. Actually, it's the same driver, isn't it? */ case SCULL_P_IOCTSIZE: scull_p_buffer = arg; break; case SCULL_P_IOCQSIZE: return scull_p_buffer; default: /* redundant, as cmd was checked against MAXNR */ return -ENOTTY; } return retval; }
static inline void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset, siginfo_t *info) { struct rt_signal_frame *sf; int sigframe_size, err; /* 1. Make sure everything is clean */ synchronize_user_stack(); save_and_clear_fpu(); sigframe_size = RT_ALIGNEDSZ; if (!(current->thread.fpsaved[0] & FPRS_FEF)) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct rt_signal_frame *)get_sigframe(ka, regs, sigframe_size); if (invalid_frame_pointer (sf, sigframe_size)) goto sigill; if (current->thread.w_saved != 0) { #ifdef DEBUG_SIGNALS printk ("%s[%d]: Invalid user stack frame for " "signal delivery.\n", current->comm, current->pid); #endif goto sigill; } /* 2. Save the current process state */ err = copy_to_user(&sf->regs, regs, sizeof (*regs)); if (current->thread.fpsaved[0] & FPRS_FEF) { err |= save_fpu_state(regs, &sf->fpu_state); err |= __put_user((u64)&sf->fpu_state, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } /* Setup sigaltstack */ err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); err |= copy_in_user((u64 *)sf, (u64 *)(regs->u_regs[UREG_FP]+STACK_BIAS), sizeof(struct reg_window)); if (info) err |= copy_siginfo_to_user(&sf->info, info); else { err |= __put_user(signo, &sf->info.si_signo); err |= __put_user(SI_NOINFO, &sf->info.si_code); } if (err) goto sigsegv; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS; regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; /* The sigcontext is passed in this way because of how it * is defined in GLIBC's /usr/include/bits/sigcontext.h * for sparc64. It includes the 128 bytes of siginfo_t. */ regs->u_regs[UREG_I2] = (unsigned long) &sf->info; /* 5. signal handler */ regs->tpc = (unsigned long) ka->sa.sa_handler; regs->tnpc = (regs->tpc + 4); if ((current->thread.flags & SPARC_FLAG_32BIT) != 0) { regs->tpc &= 0xffffffff; regs->tnpc &= 0xffffffff; } /* 4. return to kernel instructions */ regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; return; sigill: do_exit(SIGILL); sigsegv: do_exit(SIGSEGV); }
/* {set, get}context() needed for 64-bit SparcLinux userland. */ asmlinkage void sparc64_set_context(struct pt_regs *regs) { struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0]; struct thread_struct *tp = ¤t->thread; mc_gregset_t *grp; unsigned long pc, npc, tstate; unsigned long fp, i7; unsigned char fenab; int err; flush_user_windows(); if(tp->w_saved || (((unsigned long)ucp) & (sizeof(unsigned long)-1)) || (!__access_ok((unsigned long)ucp, sizeof(*ucp)))) goto do_sigsegv; grp = &ucp->uc_mcontext.mc_gregs; err = __get_user(pc, &((*grp)[MC_PC])); err |= __get_user(npc, &((*grp)[MC_NPC])); if(err || ((pc | npc) & 3)) goto do_sigsegv; if(regs->u_regs[UREG_I1]) { sigset_t set; if (_NSIG_WORDS == 1) { if (__get_user(set.sig[0], &ucp->uc_sigmask.sig[0])) goto do_sigsegv; } else { if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t))) goto do_sigsegv; } sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); current->blocked = set; recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); } if ((tp->flags & SPARC_FLAG_32BIT) != 0) { pc &= 0xffffffff; npc &= 0xffffffff; } regs->tpc = pc; regs->tnpc = npc; err |= __get_user(regs->y, &((*grp)[MC_Y])); err |= __get_user(tstate, &((*grp)[MC_TSTATE])); regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC); regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC)); err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1])); err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2])); err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3])); err |= __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4])); err |= __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5])); err |= __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6])); err |= __get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7])); err |= __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0])); err |= __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1])); err |= __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2])); err |= __get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3])); err |= __get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4])); err |= __get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5])); err |= __get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6])); err |= __get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7])); err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp)); err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7)); err |= __put_user(fp, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); err |= __put_user(i7, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7]))); err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab)); if(fenab) { unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs); unsigned long fprs; fprs_write(0); err |= __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs)); if (fprs & FPRS_DL) err |= copy_from_user(fpregs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs), (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) err |= copy_from_user(fpregs+16, ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16, (sizeof(unsigned int) * 32)); err |= __get_user(current->thread.xfsr[0], &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr)); err |= __get_user(current->thread.gsr[0], &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr)); regs->tstate &= ~TSTATE_PEF; } if (err) goto do_sigsegv; return; do_sigsegv: do_exit(SIGSEGV); }
static int setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { struct sigframe __user *frame; int err = 0, sig = ksig->sig; frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); if (_NSIG_WORDS > 1) err |= __copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ksig->ka.sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ksig->ka.sa.sa_restorer; #ifdef CONFIG_VSYSCALL } else if (likely(current->mm->context.vdso)) { regs->pr = VDSO_SYM(&__kernel_sigreturn); #endif } else { /* Generate return code (system call to sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); err |= __put_user(TRAP_NOARG, &frame->retcode[1]); err |= __put_user(OR_R0_R0, &frame->retcode[2]); err |= __put_user(OR_R0_R0, &frame->retcode[3]); err |= __put_user(OR_R0_R0, &frame->retcode[4]); err |= __put_user(OR_R0_R0, &frame->retcode[5]); err |= __put_user(OR_R0_R0, &frame->retcode[6]); err |= __put_user((__NR_sigreturn), &frame->retcode[7]); regs->pr = (unsigned long) frame->retcode; flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode)); } if (err) return -EFAULT; /* Set up registers for signal handler */ regs->regs[15] = (unsigned long) frame; regs->regs[4] = sig; /* Arg for signal handler */ regs->regs[5] = 0; regs->regs[6] = (unsigned long) &frame->sc; if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler; err |= __get_user(regs->pc, &funcptr->text); err |= __get_user(regs->regs[12], &funcptr->GOT); } else regs->pc = (unsigned long)ksig->ka.sa.sa_handler; if (err) return -EFAULT; pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); return 0; }
asmlinkage void sparc64_get_context(struct pt_regs *regs) { struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0]; struct thread_struct *tp = ¤t->thread; mc_gregset_t *grp; mcontext_t *mcp; unsigned long fp, i7; unsigned char fenab; int err; synchronize_user_stack(); if(tp->w_saved || clear_user(ucp, sizeof(*ucp))) goto do_sigsegv; #if 1 fenab = 0; /* IMO get_context is like any other system call, thus modifies FPU state -jj */ #else fenab = (current->thread.fpsaved[0] & FPRS_FEF); #endif mcp = &ucp->uc_mcontext; grp = &mcp->mc_gregs; /* Skip over the trap instruction, first. */ if ((tp->flags & SPARC_FLAG_32BIT) != 0) { regs->tpc = (regs->tnpc & 0xffffffff); regs->tnpc = (regs->tnpc + 4) & 0xffffffff; } else { regs->tpc = regs->tnpc; regs->tnpc += 4; } err = 0; if (_NSIG_WORDS == 1) err |= __put_user(current->blocked.sig[0], (unsigned long *)&ucp->uc_sigmask); else err |= __copy_to_user(&ucp->uc_sigmask, ¤t->blocked, sizeof(sigset_t)); err |= __put_user(regs->tstate, &((*grp)[MC_TSTATE])); err |= __put_user(regs->tpc, &((*grp)[MC_PC])); err |= __put_user(regs->tnpc, &((*grp)[MC_NPC])); err |= __put_user(regs->y, &((*grp)[MC_Y])); err |= __put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1])); err |= __put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2])); err |= __put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3])); err |= __put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4])); err |= __put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5])); err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6])); err |= __put_user(regs->u_regs[UREG_G7], &((*grp)[MC_G7])); err |= __put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0])); err |= __put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1])); err |= __put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2])); err |= __put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3])); err |= __put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4])); err |= __put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5])); err |= __put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6])); err |= __put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7])); err |= __get_user(fp, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); err |= __get_user(i7, (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7]))); err |= __put_user(fp, &(mcp->mc_fp)); err |= __put_user(i7, &(mcp->mc_i7)); err |= __put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab)); if(fenab) { unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs); unsigned long fprs; fprs = current->thread.fpsaved[0]; if (fprs & FPRS_DL) err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs, (sizeof(unsigned int) * 32)); if (fprs & FPRS_DU) err |= copy_to_user( ((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16, (sizeof(unsigned int) * 32)); err |= __put_user(current->thread.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr)); err |= __put_user(current->thread.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr)); err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs)); } if (err) goto do_sigsegv; return; do_sigsegv: do_exit(SIGSEGV); }
int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts) { return (!access_ok(VERIFY_WRITE, cts, sizeof(*cts)) || __put_user(ts->tv_sec, &cts->tv_sec) || __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0; }
int put_compat_rusage(const struct rusage *r, struct compat_rusage __user *ru) { if (!access_ok(VERIFY_WRITE, ru, sizeof(*ru)) || __put_user(r->ru_utime.tv_sec, &ru->ru_utime.tv_sec) || __put_user(r->ru_utime.tv_usec, &ru->ru_utime.tv_usec) || __put_user(r->ru_stime.tv_sec, &ru->ru_stime.tv_sec) || __put_user(r->ru_stime.tv_usec, &ru->ru_stime.tv_usec) || __put_user(r->ru_maxrss, &ru->ru_maxrss) || __put_user(r->ru_ixrss, &ru->ru_ixrss) || __put_user(r->ru_idrss, &ru->ru_idrss) || __put_user(r->ru_isrss, &ru->ru_isrss) || __put_user(r->ru_minflt, &ru->ru_minflt) || __put_user(r->ru_majflt, &ru->ru_majflt) || __put_user(r->ru_nswap, &ru->ru_nswap) || __put_user(r->ru_inblock, &ru->ru_inblock) || __put_user(r->ru_oublock, &ru->ru_oublock) || __put_user(r->ru_msgsnd, &ru->ru_msgsnd) || __put_user(r->ru_msgrcv, &ru->ru_msgrcv) || __put_user(r->ru_nsignals, &ru->ru_nsignals) || __put_user(r->ru_nvcsw, &ru->ru_nvcsw) || __put_user(r->ru_nivcsw, &ru->ru_nivcsw)) return -EFAULT; return 0; }
static int compat_mga_init(struct file *file, unsigned int cmd, unsigned long arg) { drm_mga_init32_t init32; drm_mga_init_t __user *init; int err = 0, i; if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) return -EFAULT; init = compat_alloc_user_space(sizeof(*init)); if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) || __put_user(init32.func, &init->func) || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) || __put_user(init32.chipset, &init->chipset) || __put_user(init32.sgram, &init->sgram) || __put_user(init32.maccess, &init->maccess) || __put_user(init32.fb_cpp, &init->fb_cpp) || __put_user(init32.front_offset, &init->front_offset) || __put_user(init32.front_pitch, &init->front_pitch) || __put_user(init32.back_offset, &init->back_offset) || __put_user(init32.back_pitch, &init->back_pitch) || __put_user(init32.depth_cpp, &init->depth_cpp) || __put_user(init32.depth_offset, &init->depth_offset) || __put_user(init32.depth_pitch, &init->depth_pitch) || __put_user(init32.fb_offset, &init->fb_offset) || __put_user(init32.mmio_offset, &init->mmio_offset) || __put_user(init32.status_offset, &init->status_offset) || __put_user(init32.warp_offset, &init->warp_offset) || __put_user(init32.primary_offset, &init->primary_offset) || __put_user(init32.buffers_offset, &init->buffers_offset)) return -EFAULT; for (i=0; i<MGA_NR_TEX_HEAPS; i++) { err |= __put_user(init32.texture_offset[i], &init->texture_offset[i]); err |= __put_user(init32.texture_size[i], &init->texture_size[i]); } if (err) return -EFAULT; return drm_ioctl(file->f_dentry->d_inode, file, DRM_IOCTL_MGA_INIT, (unsigned long) init); }
/* * Copied from copy_siginfo_to_user() in kernel/signal.c */ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, siginfo_t const *kinfo) { long err; BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128); /* * Unused members should be zero ... */ err = __clear_user(uinfo, sizeof(*uinfo)); /* * If you change siginfo_t structure, please be sure * this code is fixed accordingly. */ err |= __put_user(kinfo->si_signo, &uinfo->ssi_signo); err |= __put_user(kinfo->si_errno, &uinfo->ssi_errno); err |= __put_user((short) kinfo->si_code, &uinfo->ssi_code); switch (kinfo->si_code & __SI_MASK) { case __SI_KILL: err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); break; case __SI_TIMER: err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid); err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun); err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); err |= __put_user(kinfo->si_int, &uinfo->ssi_int); break; case __SI_POLL: err |= __put_user(kinfo->si_band, &uinfo->ssi_band); err |= __put_user(kinfo->si_fd, &uinfo->ssi_fd); break; case __SI_FAULT: err |= __put_user((long) kinfo->si_addr, &uinfo->ssi_addr); #ifdef __ARCH_SI_TRAPNO err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno); #endif break; case __SI_CHLD: err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); err |= __put_user(kinfo->si_status, &uinfo->ssi_status); err |= __put_user(kinfo->si_utime, &uinfo->ssi_utime); err |= __put_user(kinfo->si_stime, &uinfo->ssi_stime); break; case __SI_RT: /* This is not generated by the kernel as of now. */ case __SI_MESGQ: /* But this is */ err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); err |= __put_user(kinfo->si_int, &uinfo->ssi_int); break; default: /* * This case catches also the signals queued by sigqueue(). */ err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid); err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid); err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr); err |= __put_user(kinfo->si_int, &uinfo->ssi_int); break; } return err ? -EFAULT: sizeof(*uinfo); }
int copy_siginfo_to_user (siginfo_t *to, siginfo_t *from) { if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t))) return -EFAULT; if (from->si_code < 0) { if (__copy_to_user(to, from, sizeof(siginfo_t))) return -EFAULT; return 0; } else { int err; /* * 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. */ 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); switch (from->si_code >> 16) { case __SI_FAULT >> 16: err |= __put_user(from->si_flags, &to->si_flags); err |= __put_user(from->si_isr, &to->si_isr); case __SI_POLL >> 16: err |= __put_user(from->si_addr, &to->si_addr); err |= __put_user(from->si_imm, &to->si_imm); 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); case __SI_PROF >> 16: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_pid, &to->si_pid); if (from->si_code == PROF_OVFL) { err |= __put_user(from->si_pfm_ovfl[0], &to->si_pfm_ovfl[0]); err |= __put_user(from->si_pfm_ovfl[1], &to->si_pfm_ovfl[1]); err |= __put_user(from->si_pfm_ovfl[2], &to->si_pfm_ovfl[2]); err |= __put_user(from->si_pfm_ovfl[3], &to->si_pfm_ovfl[3]); } break; default: err |= __put_user(from->si_uid, &to->si_uid); err |= __put_user(from->si_pid, &to->si_pid); break; /* case __SI_RT: This is not generated by the kernel as of now. */ } return err; } }
int ptrace_request(struct task_struct *child, long request, unsigned long addr, unsigned long data) { int ret = -EIO; siginfo_t siginfo; void __user *datavp = (__force void __user *) data; unsigned long __user *datalp = datavp; switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: return generic_ptrace_peekdata(child, addr, data); case PTRACE_POKETEXT: case PTRACE_POKEDATA: return generic_ptrace_pokedata(child, addr, data); #ifdef PTRACE_OLDSETOPTIONS case PTRACE_OLDSETOPTIONS: #endif case PTRACE_SETOPTIONS: ret = ptrace_setoptions(child, data); break; case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, datalp); break; case PTRACE_GETSIGINFO: ret = ptrace_getsiginfo(child, &siginfo); if (!ret) ret = copy_siginfo_to_user(datavp, &siginfo); break; case PTRACE_SETSIGINFO: if (copy_from_user(&siginfo, datavp, sizeof siginfo)) ret = -EFAULT; else ret = ptrace_setsiginfo(child, &siginfo); break; case PTRACE_DETACH: /* detach a process that was attached. */ ret = ptrace_detach(child, data); break; #ifdef CONFIG_BINFMT_ELF_FDPIC case PTRACE_GETFDPIC: { struct mm_struct *mm = get_task_mm(child); unsigned long tmp = 0; ret = -ESRCH; if (!mm) break; switch (addr) { case PTRACE_GETFDPIC_EXEC: tmp = mm->context.exec_fdpic_loadmap; break; case PTRACE_GETFDPIC_INTERP: tmp = mm->context.interp_fdpic_loadmap; break; default: break; } mmput(mm); ret = put_user(tmp, datalp); break; } #endif #ifdef PTRACE_SINGLESTEP case PTRACE_SINGLESTEP: #endif #ifdef PTRACE_SINGLEBLOCK case PTRACE_SINGLEBLOCK: #endif #ifdef PTRACE_SYSEMU case PTRACE_SYSEMU: case PTRACE_SYSEMU_SINGLESTEP: #endif case PTRACE_SYSCALL: case PTRACE_CONT: return ptrace_resume(child, request, data); case PTRACE_KILL: if (child->exit_state) /* already dead */ return 0; return ptrace_resume(child, request, SIGKILL); #ifdef CONFIG_HAVE_ARCH_TRACEHOOK case PTRACE_GETREGSET: case PTRACE_SETREGSET: { struct iovec kiov; struct iovec __user *uiov = datavp; if (!access_ok(VERIFY_WRITE, uiov, sizeof(*uiov))) return -EFAULT; if (__get_user(kiov.iov_base, &uiov->iov_base) || __get_user(kiov.iov_len, &uiov->iov_len)) return -EFAULT; ret = ptrace_regset(child, request, addr, &kiov); if (!ret) ret = __put_user(kiov.iov_len, &uiov->iov_len); break; } #endif default: break; } return ret; }
/* * This does just the minimum required setup of sigcontext. * Specifically, it only installs data that is either not knowable at * the user-level or that gets modified before execution in the * trampoline starts. Everything else is done at the user-level. */ static long setup_sigcontext (struct sigcontext *sc, sigset_t *mask, struct sigscratch *scr) { unsigned long flags = 0, ifs, cfm, nat; long err; ifs = scr->pt.cr_ifs; if (on_sig_stack((unsigned long) sc)) flags |= IA64_SC_FLAG_ONSTACK; if ((ifs & (1UL << 63)) == 0) { /* if cr_ifs isn't valid, we got here through a syscall */ flags |= IA64_SC_FLAG_IN_SYSCALL; cfm = scr->ar_pfs & ((1UL << 38) - 1); } else cfm = ifs & ((1UL << 38) - 1); ia64_flush_fph(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { flags |= IA64_SC_FLAG_FPH_VALID; __copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16); } /* * Note: sw->ar_unat is UNDEFINED unless the process is being * PTRACED. However, this is OK because the NaT bits of the * preserved registers (r4-r7) are never being looked at by * the signal handler (registers r4-r7 are used instead). */ nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat); err = __put_user(flags, &sc->sc_flags); err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); err |= __put_user(cfm, &sc->sc_cfm); err |= __put_user(scr->pt.cr_ipsr & IA64_PSR_UM, &sc->sc_um); err |= __put_user(scr->pt.ar_rsc, &sc->sc_ar_rsc); err |= __put_user(scr->pt.ar_ccv, &sc->sc_ar_ccv); err |= __put_user(scr->pt.ar_unat, &sc->sc_ar_unat); /* ar.unat */ err |= __put_user(scr->pt.ar_fpsr, &sc->sc_ar_fpsr); /* ar.fpsr */ err |= __put_user(scr->pt.ar_pfs, &sc->sc_ar_pfs); err |= __put_user(scr->pt.pr, &sc->sc_pr); /* predicates */ err |= __put_user(scr->pt.b0, &sc->sc_br[0]); /* b0 (rp) */ err |= __put_user(scr->pt.b6, &sc->sc_br[6]); /* b6 */ err |= __put_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */ err |= __copy_to_user(&sc->sc_gr[1], &scr->pt.r1, 3*8); /* r1-r3 */ err |= __copy_to_user(&sc->sc_gr[8], &scr->pt.r8, 4*8); /* r8-r11 */ err |= __copy_to_user(&sc->sc_gr[12], &scr->pt.r12, 4*8); /* r12-r15 */ err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8); /* r16-r31 */ err |= __put_user(scr->pt.cr_iip + ia64_psr(&scr->pt)->ri, &sc->sc_ip); return err; }
static inline long put_tv32(struct compat_timeval __user *o, struct timeval *i) { return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) || (__put_user(i->tv_sec, &o->tv_sec) | __put_user(i->tv_usec, &o->tv_usec))); }
static long setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct sigscratch *scr) { extern char ia64_sigtramp[], __start_gate_section[]; unsigned long tramp_addr, new_rbs = 0; struct sigframe *frame; struct siginfo si; long err; frame = (void *) scr->pt.r12; tramp_addr = GATE_ADDR + (ia64_sigtramp - __start_gate_section); if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) { frame = (void *) ((current->sas_ss_sp + current->sas_ss_size) & ~(STACK_ALIGN - 1)); /* * We need to check for the register stack being on the signal stack * separately, because it's switched separately (memory stack is switched * in the kernel, register stack is switched in the signal trampoline). */ if (!rbs_on_sig_stack(scr->pt.ar_bspstore)) new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); } frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err = __put_user(sig, &frame->arg0); err |= __put_user(&frame->info, &frame->arg1); err |= __put_user(&frame->sc, &frame->arg2); err |= __put_user(new_rbs, &frame->sc.sc_rbs_base); err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */ err |= __put_user(ka->sa.sa_handler, &frame->handler); err |= copy_siginfo_to_user(&frame->info, info); err |= __put_user(current->sas_ss_sp, &frame->sc.sc_stack.ss_sp); err |= __put_user(current->sas_ss_size, &frame->sc.sc_stack.ss_size); err |= __put_user(sas_ss_flags(scr->pt.r12), &frame->sc.sc_stack.ss_flags); err |= setup_sigcontext(&frame->sc, set, scr); if (err) goto give_sigsegv; scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ scr->pt.cr_iip = tramp_addr; ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */ /* * Force the interruption function mask to zero. This has no effect when a * system-call got interrupted by a signal (since, in that case, scr->pt_cr_ifs is * ignored), but it has the desirable effect of making it possible to deliver a * signal with an incomplete register frame (which happens when a mandatory RSE * load faults). Furthermore, it has no negative effect on the getting the user's * dirty partition preserved, because that's governed by scr->pt.loadrs. */ scr->pt.cr_ifs = (1UL << 63); /* * Note: this affects only the NaT bits of the scratch regs (the ones saved in * pt_regs), which is exactly what we want. */ scr->scratch_unat = 0; /* ensure NaT bits of r12 is clear */ #if DEBUG_SIG printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%lx\n", current->comm, current->pid, sig, scr->pt.r12, scr->pt.cr_iip, scr->pt.r3); #endif return 1; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; si.si_signo = SIGSEGV; si.si_errno = 0; si.si_code = SI_KERNEL; si.si_pid = current->pid; si.si_uid = current->uid; si.si_addr = frame; force_sig_info(SIGSEGV, &si, current); return 0; }
int setup_signal_stack_si(unsigned long stack_top, int sig, struct k_sigaction *ka, struct pt_regs * regs, siginfo_t *info, sigset_t *set) { struct rt_sigframe __user *frame; struct _fpstate __user *fp = NULL; int err = 0; struct task_struct *me = current; frame = (struct rt_sigframe __user *) round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8; frame -= 128; if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto out; #if 0 /* XXX */ if (save_i387(fp) < 0) err |= -1; #endif if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto out; if (ka->sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, info); if (err) goto out; } /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)), &frame->uc.uc_stack.ss_flags); err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]); err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); if (sizeof(*set) == 16) { __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); } else err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ /* x86-64 should always use SA_RESTORER. */ if (ka->sa.sa_flags & SA_RESTORER) err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); else /* could use a vstub here */ goto out; if (err) goto out; /* Set up registers for signal handler */ { struct exec_domain *ed = current_thread_info()->exec_domain; if (unlikely(ed && ed->signal_invmap && sig < 32)) sig = ed->signal_invmap[sig]; } PT_REGS_RDI(regs) = sig; /* In case the signal handler was declared without prototypes */ PT_REGS_RAX(regs) = 0; /* This also works for non SA_SIGINFO handlers because they expect the next argument after the signal number on the stack. */ PT_REGS_RSI(regs) = (unsigned long) &frame->info; PT_REGS_RDX(regs) = (unsigned long) &frame->uc; PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler; PT_REGS_RSP(regs) = (unsigned long) frame; out: return(err); }
static int setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set) { int err = 0; err |= __put_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00); err |= __put_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01); err |= __put_user(regs->UCreg_02, &sf->uc.uc_mcontext.regs.UCreg_02); err |= __put_user(regs->UCreg_03, &sf->uc.uc_mcontext.regs.UCreg_03); err |= __put_user(regs->UCreg_04, &sf->uc.uc_mcontext.regs.UCreg_04); err |= __put_user(regs->UCreg_05, &sf->uc.uc_mcontext.regs.UCreg_05); err |= __put_user(regs->UCreg_06, &sf->uc.uc_mcontext.regs.UCreg_06); err |= __put_user(regs->UCreg_07, &sf->uc.uc_mcontext.regs.UCreg_07); err |= __put_user(regs->UCreg_08, &sf->uc.uc_mcontext.regs.UCreg_08); err |= __put_user(regs->UCreg_09, &sf->uc.uc_mcontext.regs.UCreg_09); err |= __put_user(regs->UCreg_10, &sf->uc.uc_mcontext.regs.UCreg_10); err |= __put_user(regs->UCreg_11, &sf->uc.uc_mcontext.regs.UCreg_11); err |= __put_user(regs->UCreg_12, &sf->uc.uc_mcontext.regs.UCreg_12); err |= __put_user(regs->UCreg_13, &sf->uc.uc_mcontext.regs.UCreg_13); err |= __put_user(regs->UCreg_14, &sf->uc.uc_mcontext.regs.UCreg_14); err |= __put_user(regs->UCreg_15, &sf->uc.uc_mcontext.regs.UCreg_15); err |= __put_user(regs->UCreg_16, &sf->uc.uc_mcontext.regs.UCreg_16); err |= __put_user(regs->UCreg_17, &sf->uc.uc_mcontext.regs.UCreg_17); err |= __put_user(regs->UCreg_18, &sf->uc.uc_mcontext.regs.UCreg_18); err |= __put_user(regs->UCreg_19, &sf->uc.uc_mcontext.regs.UCreg_19); err |= __put_user(regs->UCreg_20, &sf->uc.uc_mcontext.regs.UCreg_20); err |= __put_user(regs->UCreg_21, &sf->uc.uc_mcontext.regs.UCreg_21); err |= __put_user(regs->UCreg_22, &sf->uc.uc_mcontext.regs.UCreg_22); err |= __put_user(regs->UCreg_23, &sf->uc.uc_mcontext.regs.UCreg_23); err |= __put_user(regs->UCreg_24, &sf->uc.uc_mcontext.regs.UCreg_24); err |= __put_user(regs->UCreg_25, &sf->uc.uc_mcontext.regs.UCreg_25); err |= __put_user(regs->UCreg_26, &sf->uc.uc_mcontext.regs.UCreg_26); err |= __put_user(regs->UCreg_fp, &sf->uc.uc_mcontext.regs.UCreg_fp); err |= __put_user(regs->UCreg_ip, &sf->uc.uc_mcontext.regs.UCreg_ip); err |= __put_user(regs->UCreg_sp, &sf->uc.uc_mcontext.regs.UCreg_sp); err |= __put_user(regs->UCreg_lr, &sf->uc.uc_mcontext.regs.UCreg_lr); err |= __put_user(regs->UCreg_pc, &sf->uc.uc_mcontext.regs.UCreg_pc); err |= __put_user(regs->UCreg_asr, &sf->uc.uc_mcontext.regs.UCreg_asr); err |= __put_user(current->thread.trap_no, &sf->uc.uc_mcontext.trap_no); err |= __put_user(current->thread.error_code, &sf->uc.uc_mcontext.error_code); err |= __put_user(current->thread.address, &sf->uc.uc_mcontext.fault_address); err |= __put_user(set->sig[0], &sf->uc.uc_mcontext.oldmask); err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set)); return err; }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe *frame; int err = 0; int signal; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; signal = current->exec_domain && current->exec_domain->signal_invmap && sig < 32 ? current->exec_domain->signal_invmap[sig] : sig; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->gpr[GPR_SP]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ /* minus 8 is offset to cater for "rtsd r15,8" */ if (ka->sa.sa_flags & SA_RESTORER) { regs->gpr[GPR_LP] = (unsigned long) ka->sa.sa_restorer-8; } else { /* addi r12, r0, __NR_sigreturn */ err |= __put_user(0x31800000 | __NR_sigreturn , frame->tramp + 0); /* brki r14, 0x8 */ err |= __put_user(0xb9cc0008, frame->tramp + 1); regs->gpr[GPR_LP] = (unsigned long)frame->tramp-8; flush_cache_sigtramp (regs->gpr[GPR_LP]); } if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->gpr[GPR_SP] = (unsigned long) frame; regs->gpr[GPR_ARG0] = signal; /* Arg for signal handler */ /* Offset to handle microblaze rtbd r14, 4 */ regs->pc = (unsigned long) ka->sa.sa_handler-4; set_fs(USER_DS); #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", current->comm, current->pid, frame, regs->pc, regs->pr); #endif return; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); }
static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask, unsigned long sp) { struct switch_stack *sw = (struct switch_stack *)regs - 1; long i, err = 0; err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack); err |= __put_user(mask, &sc->sc_mask); err |= __put_user(regs->pc, &sc->sc_pc); err |= __put_user(8, &sc->sc_ps); err |= __put_user(regs->r0 , sc->sc_regs+0); err |= __put_user(regs->r1 , sc->sc_regs+1); err |= __put_user(regs->r2 , sc->sc_regs+2); err |= __put_user(regs->r3 , sc->sc_regs+3); err |= __put_user(regs->r4 , sc->sc_regs+4); err |= __put_user(regs->r5 , sc->sc_regs+5); err |= __put_user(regs->r6 , sc->sc_regs+6); err |= __put_user(regs->r7 , sc->sc_regs+7); err |= __put_user(regs->r8 , sc->sc_regs+8); err |= __put_user(sw->r9 , sc->sc_regs+9); err |= __put_user(sw->r10 , sc->sc_regs+10); err |= __put_user(sw->r11 , sc->sc_regs+11); err |= __put_user(sw->r12 , sc->sc_regs+12); err |= __put_user(sw->r13 , sc->sc_regs+13); err |= __put_user(sw->r14 , sc->sc_regs+14); err |= __put_user(sw->r15 , sc->sc_regs+15); err |= __put_user(regs->r16, sc->sc_regs+16); err |= __put_user(regs->r17, sc->sc_regs+17); err |= __put_user(regs->r18, sc->sc_regs+18); err |= __put_user(regs->r19, sc->sc_regs+19); err |= __put_user(regs->r20, sc->sc_regs+20); err |= __put_user(regs->r21, sc->sc_regs+21); err |= __put_user(regs->r22, sc->sc_regs+22); err |= __put_user(regs->r23, sc->sc_regs+23); err |= __put_user(regs->r24, sc->sc_regs+24); err |= __put_user(regs->r25, sc->sc_regs+25); err |= __put_user(regs->r26, sc->sc_regs+26); err |= __put_user(regs->r27, sc->sc_regs+27); err |= __put_user(regs->r28, sc->sc_regs+28); err |= __put_user(regs->gp , sc->sc_regs+29); err |= __put_user(sp, sc->sc_regs+30); err |= __put_user(0, sc->sc_regs+31); for (i = 0; i < 31; i++) err |= __put_user(sw->fp[i], sc->sc_fpregs+i); err |= __put_user(0, sc->sc_fpregs+31); err |= __put_user(sw->fp[31], &sc->sc_fpcr); err |= __put_user(regs->trap_a0, &sc->sc_traparg_a0); err |= __put_user(regs->trap_a1, &sc->sc_traparg_a1); err |= __put_user(regs->trap_a2, &sc->sc_traparg_a2); return err; }
/* * Commands to do_syslog: * * 0 -- Close the log. Currently a NOP. * 1 -- Open the log. Currently a NOP. * 2 -- Read from the log. * 3 -- Read all messages remaining in the ring buffer. * 4 -- Read and clear all messages remaining in the ring buffer * 5 -- Clear ring buffer. * 6 -- Disable printk's to console * 7 -- Enable printk's to console * 8 -- Set level of messages printed to console * 9 -- Return number of unread characters in the log buffer * 10 -- Return size of the log buffer */ int do_syslog(int type, char __user *buf, int len) { unsigned i, j, limit, count; int do_clear = 0; char c; int error = 0; error = security_syslog(type); if (error) return error; switch (type) { case 0: /* Close log */ break; case 1: /* Open log */ break; case 2: /* Read from log */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } error = wait_event_interruptible(log_wait, (log_start - log_end)); if (error) goto out; i = 0; spin_lock_irq(&logbuf_lock); while (!error && (log_start != log_end) && i < len) { c = LOG_BUF(log_start); log_start++; spin_unlock_irq(&logbuf_lock); error = __put_user(c,buf); buf++; i++; cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (!error) error = i; break; case 4: /* Read/clear last kernel messages */ do_clear = 1; /* FALL THRU */ case 3: /* Read last kernel messages */ error = -EINVAL; if (!buf || len < 0) goto out; error = 0; if (!len) goto out; if (!access_ok(VERIFY_WRITE, buf, len)) { error = -EFAULT; goto out; } count = len; if (count > log_buf_len) count = log_buf_len; spin_lock_irq(&logbuf_lock); if (count > logged_chars) count = logged_chars; if (do_clear) logged_chars = 0; limit = log_end; /* * __put_user() could sleep, and while we sleep * printk() could overwrite the messages * we try to copy to user space. Therefore * the messages are copied in reverse. <manfreds> */ for (i = 0; i < count && !error; i++) { j = limit-1-i; if (j + log_buf_len < log_end) break; c = LOG_BUF(j); spin_unlock_irq(&logbuf_lock); error = __put_user(c,&buf[count-1-i]); cond_resched(); spin_lock_irq(&logbuf_lock); } spin_unlock_irq(&logbuf_lock); if (error) break; error = i; if (i != count) { int offset = count-error; /* buffer overflow during copy, correct user buffer. */ for (i = 0; i < error; i++) { if (__get_user(c,&buf[i+offset]) || __put_user(c,&buf[i])) { error = -EFAULT; break; } cond_resched(); } } break; case 5: /* Clear ring buffer */ logged_chars = 0; break; case 6: /* Disable logging to console */ if (saved_console_loglevel == -1) saved_console_loglevel = console_loglevel; console_loglevel = minimum_console_loglevel; break; case 7: /* Enable logging to console */ if (saved_console_loglevel != -1) { console_loglevel = saved_console_loglevel; saved_console_loglevel = -1; } break; case 8: /* Set level of messages printed to console */ error = -EINVAL; if (len < 1 || len > 8) goto out; if (len < minimum_console_loglevel) len = minimum_console_loglevel; console_loglevel = len; /* Implicitly re-enable logging to console */ saved_console_loglevel = -1; error = 0; break; case 9: /* Number of chars in the log buffer */ error = log_end - log_start; break; case 10: /* Size of the log buffer */ error = log_buf_len; break; default: error = -EINVAL; break; } out: return error; }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; int err = 0; int signal; unsigned long address = 0; #ifdef CONFIG_MMU pmd_t *pmdp; pte_t *ptep; #endif frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; signal = current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; if (info) err |= copy_siginfo_to_user(&frame->info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __save_altstack(&frame->uc.uc_stack, regs->r1); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. If provided, use a stub already in userspace. */ /* minus 8 is offset to cater for "rtsd r15,8" */ /* addi r12, r0, __NR_sigreturn */ err |= __put_user(0x31800000 | __NR_rt_sigreturn , frame->tramp + 0); /* brki r14, 0x8 */ err |= __put_user(0xb9cc0008, frame->tramp + 1); /* Return from sighandler will jump to the tramp. Negative 8 offset because return is rtsd r15, 8 */ regs->r15 = ((unsigned long)frame->tramp)-8; address = ((unsigned long)frame->tramp); #ifdef CONFIG_MMU pmdp = pmd_offset(pud_offset( pgd_offset(current->mm, address), address), address); preempt_disable(); ptep = pte_offset_map(pmdp, address); if (pte_present(*ptep)) { address = (unsigned long) page_address(pte_page(*ptep)); /* MS: I need add offset in page */ address += ((unsigned long)frame->tramp) & ~PAGE_MASK; /* MS address is virtual */ address = __virt_to_phys(address); invalidate_icache_range(address, address + 8); flush_dcache_range(address, address + 8); } pte_unmap(ptep); preempt_enable(); #else flush_icache_range(address, address + 8); flush_dcache_range(address, address + 8); #endif if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->r1 = (unsigned long) frame; /* Signal handler args: */ regs->r5 = signal; /* arg 0: signum */ regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */ regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */ /* Offset to handle microblaze rtid r14, 0 */ regs->pc = (unsigned long)ka->sa.sa_handler; set_fs(USER_DS); #ifdef DEBUG_SIG pr_info("SIG deliver (%s:%d): sp=%p pc=%08lx\n", current->comm, current->pid, frame, regs->pc); #endif return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
/* Copy native cmd structure to 32-bit cmd structure. */ static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32, struct comedi_cmd __user *cmd) { int err; unsigned int temp; /* Copy back most of cmd structure. */ /* Assume the pointer values are already valid. */ /* (Could use ptr_to_compat() to set them, but that wasn't implemented * until kernel version 2.6.11.) */ if (!access_ok(VERIFY_READ, cmd, sizeof(*cmd)) || !access_ok(VERIFY_WRITE, cmd32, sizeof(*cmd32))) return -EFAULT; err = 0; err |= __get_user(temp, &cmd->subdev); err |= __put_user(temp, &cmd32->subdev); err |= __get_user(temp, &cmd->flags); err |= __put_user(temp, &cmd32->flags); err |= __get_user(temp, &cmd->start_src); err |= __put_user(temp, &cmd32->start_src); err |= __get_user(temp, &cmd->start_arg); err |= __put_user(temp, &cmd32->start_arg); err |= __get_user(temp, &cmd->scan_begin_src); err |= __put_user(temp, &cmd32->scan_begin_src); err |= __get_user(temp, &cmd->scan_begin_arg); err |= __put_user(temp, &cmd32->scan_begin_arg); err |= __get_user(temp, &cmd->convert_src); err |= __put_user(temp, &cmd32->convert_src); err |= __get_user(temp, &cmd->convert_arg); err |= __put_user(temp, &cmd32->convert_arg); err |= __get_user(temp, &cmd->scan_end_src); err |= __put_user(temp, &cmd32->scan_end_src); err |= __get_user(temp, &cmd->scan_end_arg); err |= __put_user(temp, &cmd32->scan_end_arg); err |= __get_user(temp, &cmd->stop_src); err |= __put_user(temp, &cmd32->stop_src); err |= __get_user(temp, &cmd->stop_arg); err |= __put_user(temp, &cmd32->stop_arg); /* Assume chanlist pointer is unchanged. */ err |= __get_user(temp, &cmd->chanlist_len); err |= __put_user(temp, &cmd32->chanlist_len); /* Assume data pointer is unchanged. */ err |= __get_user(temp, &cmd->data_len); err |= __put_user(temp, &cmd32->data_len); return err ? -EFAULT : 0; }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { unsigned long restorer; struct rt_sigframe __user *frame; int err = 0; int usig; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; usig = current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] : sig; /* Always write at least the signal number for the stack backtracer. */ if (ka->sa.sa_flags & SA_SIGINFO) { /* At sigreturn time, restore the callee-save registers too. */ err |= copy_siginfo_to_user(&frame->info, info); regs->flags |= PT_FLAGS_RESTORE_REGS; } else { err |= __put_user(info->si_signo, &frame->info.si_signo); } /* Create the ucontext. */ err |= __clear_user(&frame->save_area, sizeof(frame->save_area)); err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(NULL, &frame->uc.uc_link); err |= __put_user((void __user *)(current->sas_ss_sp), &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; restorer = VDSO_BASE; if (ka->sa.sa_flags & SA_RESTORER) restorer = (unsigned long) ka->sa.sa_restorer; /* * Set up registers for signal handler. * Registers that we don't modify keep the value they had from * user-space at the time we took the signal. * We always pass siginfo and mcontext, regardless of SA_SIGINFO, * since some things rely on this (e.g. glibc's debug/segfault.c). */ regs->pc = (unsigned long) ka->sa.sa_handler; regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->sp = (unsigned long) frame; regs->lr = restorer; regs->regs[0] = (unsigned long) usig; regs->regs[1] = (unsigned long) &frame->info; regs->regs[2] = (unsigned long) &frame->uc; regs->flags |= PT_FLAGS_CALLER_SAVES; /* * Notify any tracer that was single-stepping it. * The tracer may want to single-step inside the * handler too. */ if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
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; }
int compat_mc_setsockopt(struct sock *sock, int level, int optname, char __user *optval, unsigned int optlen, int (*setsockopt)(struct sock *,int,int,char __user *,unsigned int)) { char __user *koptval = optval; int koptlen = optlen; switch (optname) { case MCAST_JOIN_GROUP: case MCAST_LEAVE_GROUP: { struct compat_group_req __user *gr32 = (void *)optval; struct group_req __user *kgr = compat_alloc_user_space(sizeof(struct group_req)); u32 interface; if (!access_ok(VERIFY_READ, gr32, sizeof(*gr32)) || !access_ok(VERIFY_WRITE, kgr, sizeof(struct group_req)) || __get_user(interface, &gr32->gr_interface) || __put_user(interface, &kgr->gr_interface) || copy_in_user(&kgr->gr_group, &gr32->gr_group, sizeof(kgr->gr_group))) return -EFAULT; koptval = (char __user *)kgr; koptlen = sizeof(struct group_req); break; } case MCAST_JOIN_SOURCE_GROUP: case MCAST_LEAVE_SOURCE_GROUP: case MCAST_BLOCK_SOURCE: case MCAST_UNBLOCK_SOURCE: { struct compat_group_source_req __user *gsr32 = (void *)optval; struct group_source_req __user *kgsr = compat_alloc_user_space( sizeof(struct group_source_req)); u32 interface; if (!access_ok(VERIFY_READ, gsr32, sizeof(*gsr32)) || !access_ok(VERIFY_WRITE, kgsr, sizeof(struct group_source_req)) || __get_user(interface, &gsr32->gsr_interface) || __put_user(interface, &kgsr->gsr_interface) || copy_in_user(&kgsr->gsr_group, &gsr32->gsr_group, sizeof(kgsr->gsr_group)) || copy_in_user(&kgsr->gsr_source, &gsr32->gsr_source, sizeof(kgsr->gsr_source))) return -EFAULT; koptval = (char __user *)kgsr; koptlen = sizeof(struct group_source_req); break; } case MCAST_MSFILTER: { struct compat_group_filter __user *gf32 = (void *)optval; struct group_filter __user *kgf; u32 interface, fmode, numsrc; if (!access_ok(VERIFY_READ, gf32, __COMPAT_GF0_SIZE) || __get_user(interface, &gf32->gf_interface) || __get_user(fmode, &gf32->gf_fmode) || __get_user(numsrc, &gf32->gf_numsrc)) return -EFAULT; koptlen = optlen + sizeof(struct group_filter) - sizeof(struct compat_group_filter); if (koptlen < GROUP_FILTER_SIZE(numsrc)) return -EINVAL; kgf = compat_alloc_user_space(koptlen); if (!access_ok(VERIFY_WRITE, kgf, koptlen) || __put_user(interface, &kgf->gf_interface) || __put_user(fmode, &kgf->gf_fmode) || __put_user(numsrc, &kgf->gf_numsrc) || copy_in_user(&kgf->gf_group, &gf32->gf_group, sizeof(kgf->gf_group)) || (numsrc && copy_in_user(kgf->gf_slist, gf32->gf_slist, numsrc * sizeof(kgf->gf_slist[0])))) return -EFAULT; koptval = (char __user *)kgf; break; } default: break; } return setsockopt(sock, level, optname, koptval, koptlen); }