static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame; unsigned long __user *retcode; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto segv_and_exit; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); /* Clear all the bits of the ucontext we don't use. */ err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); 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 */ retcode = (unsigned long __user *) &frame->retcode; /* The access_ok check was done above, so use __put_user here */ #define COPY(x) (err |= __put_user(x, retcode++)) COPY(0x0000002AUL | (__NR_rt_sigreturn << 7)); /* MVK __NR_rt_sigreturn,B0 */ COPY(0x10000000UL); /* SWE */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ COPY(0x00006000UL); /* NOP 4 */ #undef COPY if (err) goto segv_and_exit; flush_icache_range((unsigned long) &frame->retcode, (unsigned long) &frame->retcode + RETCODE_SIZE); retcode = (unsigned long __user *) &frame->retcode; /* Change user context to branch to signal handler */ regs->sp = (unsigned long) frame - 8; regs->b3 = (unsigned long) retcode; regs->pc = (unsigned long) ka->sa.sa_handler; /* Give the signal number to the handler */ regs->a4 = signr; /* * For realtime signals we must also set the second and third * arguments for the signal handler. * -- Peter Maydell <*****@*****.**> 2000-12-06 */ regs->b4 = (unsigned long)&frame->info; regs->a6 = (unsigned long)&frame->uc; return 0; segv_and_exit: force_sigsegv(signr, current); return -EFAULT; }
static int do_netfilter_replace(int fd, int level, int optname, char __user *optval, int optlen) { struct compat_ipt_replace __user *urepl; struct ipt_replace __user *repl_nat; char name[IPT_TABLE_MAXNAMELEN]; u32 origsize, tmp32, num_counters; unsigned int repl_nat_size; int ret; int i; compat_uptr_t ucntrs; urepl = (struct compat_ipt_replace __user *)optval; if (get_user(origsize, &urepl->size)) return -EFAULT; /* Hack: Causes ipchains to give correct error msg --RR */ if (optlen != sizeof(*urepl) + origsize) return -ENOPROTOOPT; /* XXX Assumes that size of ipt_entry is the same both in * native and compat environments. */ repl_nat_size = sizeof(*repl_nat) + origsize; repl_nat = compat_alloc_user_space(repl_nat_size); ret = -EFAULT; if (put_user(origsize, &repl_nat->size)) goto out; if (!access_ok(VERIFY_READ, urepl, optlen) || !access_ok(VERIFY_WRITE, repl_nat, optlen)) goto out; if (__copy_from_user(name, urepl->name, sizeof(urepl->name)) || __copy_to_user(repl_nat->name, name, sizeof(repl_nat->name))) goto out; if (__get_user(tmp32, &urepl->valid_hooks) || __put_user(tmp32, &repl_nat->valid_hooks)) goto out; if (__get_user(tmp32, &urepl->num_entries) || __put_user(tmp32, &repl_nat->num_entries)) goto out; if (__get_user(num_counters, &urepl->num_counters) || __put_user(num_counters, &repl_nat->num_counters)) goto out; if (__get_user(ucntrs, &urepl->counters) || __put_user(compat_ptr(ucntrs), &repl_nat->counters)) goto out; if (__copy_in_user(&repl_nat->entries[0], &urepl->entries[0], origsize)) goto out; for (i = 0; i < NF_IP_NUMHOOKS; i++) { if (__get_user(tmp32, &urepl->hook_entry[i]) || __put_user(tmp32, &repl_nat->hook_entry[i]) || __get_user(tmp32, &urepl->underflow[i]) || __put_user(tmp32, &repl_nat->underflow[i])) goto out; } /* * Since struct ipt_counters just contains two u_int64_t members * we can just do the access_ok check here and pass the (converted) * pointer into the standard syscall. We hope that the pointer is * not misaligned ... */ if (!access_ok(VERIFY_WRITE, compat_ptr(ucntrs), num_counters * sizeof(struct ipt_counters))) goto out; ret = sys_setsockopt(fd, level, optname, (char __user *)repl_nat, repl_nat_size); out: return ret; }
static void 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(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->regs[15]), &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. */ if (ka->sa.sa_flags & SA_RESTORER) { regs->pr = (unsigned long) ka->sa.sa_restorer; } else { /* Generate return code (system call to rt_sigreturn) */ err |= __put_user(MOVW(7), &frame->retcode[0]); err |= __put_user(TRAP16, &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; } 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; regs->pc = (unsigned long) ka->sa.sa_handler; 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 flush_cache_sigtramp(regs->pr); if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); return; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); }
asmlinkage void sparc64_get_context(struct pt_regs *regs) { struct ucontext __user *ucp = (struct ucontext __user *) regs->u_regs[UREG_I0]; mc_gregset_t __user *grp; mcontext_t __user *mcp; unsigned long fp, i7; unsigned char fenab; int err; synchronize_user_stack(); if (get_thread_wsaved() || 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_info()->fpsaved[0] & FPRS_FEF); #endif mcp = &ucp->uc_mcontext; grp = &mcp->mc_gregs; /* Skip over the trap instruction, first. */ if (test_thread_flag(TIF_32BIT)) { 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 __user *)&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 __user *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6]))); err |= __get_user(i7, (&(((struct reg_window __user *)(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 = current_thread_info()->fpregs; unsigned long fprs; fprs = current_thread_info()->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 __user *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16, (sizeof(unsigned int) * 32)); err |= __put_user(current_thread_info()->xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr)); err |= __put_user(current_thread_info()->gsr[0], &(mcp->mc_fpregs.mcfpu_gsr)); err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs)); } if (err) goto do_sigsegv; return; do_sigsegv: force_sig(SIGSEGV, current); }
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t __user *funct_desc_ptr; struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0); if (unlikely(frame == NULL)) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto badframe; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __save_altstack(&frame->uc.uc_stack, regs->gpr[1]); #ifdef CONFIG_PPC_TRANSACTIONAL_MEM if (MSR_TM_ACTIVE(regs->msr)) { /* The ucontext_t passed to userland points to the second * ucontext_t (for transactional state) with its uc_link ptr. */ err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, &frame->uc_transact.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler); } else #endif { err |= __put_user(0, &frame->uc.uc_link); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, NULL, (unsigned long)ka->sa.sa_handler, 1); } err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto badframe; /* Make sure signal handler doesn't get spurious FP exceptions */ current->thread.fpscr.val = 0; #ifdef CONFIG_PPC_TRANSACTIONAL_MEM /* Remove TM bits from thread's MSR. The MSR in the sigcontext * just indicates to userland that we were doing a transaction, but we * don't want to return in transactional state: */ regs->msr &= ~MSR_TS_MASK; #endif /* Set up to return from userspace. */ if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; regs->result = 0; if (ka->sa.sa_flags & SA_SIGINFO) { err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; } if (err) goto badframe; return 1; badframe: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif if (show_unhandled_signals) printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32, current->comm, current->pid, "setup_rt_frame", (long)frame, regs->nip, regs->link); force_sigsegv(signr, current); return 0; }
static void inline setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) { struct rt_sigframe *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; /* * Set up the return code ... * * li v0, __NR_rt_sigreturn * syscall */ if (PLAT_TRAMPOLINE_STUFF_LINE) __builtin_memset(frame->rs_code, '0', PLAT_TRAMPOLINE_STUFF_LINE); err |= __put_user(0x24020000 + __NR_rt_sigreturn, frame->rs_code + 0); err |= __put_user(0x0000000c , frame->rs_code + 1); flush_cache_sigtramp((unsigned long) frame->rs_code); /* Create siginfo. */ err |= copy_siginfo_to_user(&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); err |= __put_user((void *)current->sas_ss_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_sigcontext(regs, &frame->rs_uc.uc_mcontext); err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*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_sigframe. */ 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; #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n", current->comm, current->pid, frame, regs->cp0_epc, regs->regs[31]); #endif return; give_sigsegv: force_sigsegv(signr, current); }
static void setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset, siginfo_t *info) { struct rt_signal_frame __user *sf; int sigframe_size, wsaved; void __user *tail; unsigned int psr; int err; synchronize_user_stack(); wsaved = current_thread_info()->w_saved; sigframe_size = sizeof(*sf); if (used_math()) sigframe_size += sizeof(__siginfo_fpu_t); if (wsaved) sigframe_size += sizeof(__siginfo_rwin_t); sf = (struct rt_signal_frame __user *) get_sigframe(&ka->sa, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) goto sigill; tail = sf + 1; err = __put_user(regs->pc, &sf->regs.pc); err |= __put_user(regs->npc, &sf->regs.npc); err |= __put_user(regs->y, &sf->regs.y); psr = regs->psr; if (used_math()) psr |= PSR_EF; err |= __put_user(psr, &sf->regs.psr); err |= __copy_to_user(&sf->regs.u_regs, regs->u_regs, sizeof(regs->u_regs)); err |= __put_user(0, &sf->extra_size); if (psr & PSR_EF) { __siginfo_fpu_t *fp = tail; tail += sizeof(*fp); err |= save_fpu_state(regs, fp); err |= __put_user(fp, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } if (wsaved) { __siginfo_rwin_t *rwp = tail; tail += sizeof(*rwp); err |= save_rwin_state(wsaved, rwp); err |= __put_user(rwp, &sf->rwin_save); } else { err |= __put_user(0, &sf->rwin_save); } err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); /* 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); if (!wsaved) { err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], sizeof(struct reg_window32)); } else { struct reg_window32 *rp; rp = ¤t_thread_info()->reg_window[wsaved - 1]; err |= __copy_to_user(sf, rp, sizeof(struct reg_window32)); } err |= copy_siginfo_to_user(&sf->info, info); if (err) goto sigsegv; regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; regs->u_regs[UREG_I2] = (unsigned long) &sf->regs; regs->pc = (unsigned long) ka->sa.sa_handler; regs->npc = (regs->pc + 4); if (ka->ka_restorer) regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; else { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); /* mov __NR_sigreturn, %g1 */ err |= __put_user(0x821020d8, &sf->insns[0]); /* t 0x10 */ err |= __put_user(0x91d02010, &sf->insns[1]); if (err) goto sigsegv; /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } return; sigill: do_exit(SIGILL); sigsegv: force_sigsegv(signo, current); }
/* * NetBSD /dev/openprom ioctl calls. */ static int openprom_bsd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { DATA *data = (DATA *) file->private_data; struct opiocdesc op; unsigned long flags; int error, node, len; char *str, *tmp; char buffer[64]; static int cnt; switch (cmd) { case OPIOCGET: if (copy_from_user(&op, (void *)arg, sizeof(op))) return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; error = copyin_string(op.op_name, op.op_namelen, &str); if (error) return error; save_and_cli(flags); len = prom_getproplen(op.op_nodeid,str); restore_flags(flags); if (len > op.op_buflen) { kfree(str); return -ENOMEM; } op.op_buflen = len; if (len <= 0) { kfree(str); /* Verified by the above copy_from_user */ if (__copy_to_user((void *)arg, &op, sizeof(op))) return -EFAULT; return 0; } tmp = kmalloc(len + 1, GFP_KERNEL); if (!tmp) { kfree(str); return -ENOMEM; } save_and_cli(flags); prom_getproperty(op.op_nodeid, str, tmp, len); restore_flags(flags); tmp[len] = '\0'; error = __copy_to_user((void *)arg, &op, sizeof(op)); if (!error) error = copy_to_user(op.op_buf, tmp, len); kfree(tmp); kfree(str); return error; case OPIOCNEXTPROP: if (copy_from_user(&op, (void *)arg, sizeof(op))) return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; error = copyin_string(op.op_name, op.op_namelen, &str); if (error) return error; save_and_cli(flags); tmp = prom_nextprop(op.op_nodeid,str,buffer); restore_flags(flags); if (tmp) { len = strlen(tmp); if (len > op.op_buflen) len = op.op_buflen; else op.op_buflen = len; } else { len = op.op_buflen = 0; } error = verify_area(VERIFY_WRITE, (void *)arg, sizeof(op)); if (error) { kfree(str); return error; } error = verify_area(VERIFY_WRITE, op.op_buf, len); if (error) { kfree(str); return error; } error = __copy_to_user((void *)arg, &op, sizeof(op)); if (!error) error = __copy_to_user(op.op_buf, tmp, len); kfree(str); return error; case OPIOCSET: if (copy_from_user(&op, (void *)arg, sizeof(op))) return -EFAULT; if (!goodnode(op.op_nodeid,data)) return -EINVAL; error = copyin_string(op.op_name, op.op_namelen, &str); if (error) return error; error = copyin_string(op.op_buf, op.op_buflen, &tmp); if (error) { kfree(str); return error; } save_and_cli(flags); len = prom_setprop(op.op_nodeid,str,tmp,op.op_buflen+1); restore_flags(flags); if (len != op.op_buflen) return -EINVAL; kfree(str); kfree(tmp); return 0; case OPIOCGETOPTNODE: if (copy_to_user((void *)arg, &options_node, sizeof(int))) return -EFAULT; return 0; case OPIOCGETNEXT: case OPIOCGETCHILD: if (copy_from_user(&node, (void *)arg, sizeof(int))) return -EFAULT; save_and_cli(flags); if (cmd == OPIOCGETNEXT) node = __prom_getsibling(node); else node = __prom_getchild(node); restore_flags(flags); if (__copy_to_user((void *)arg, &node, sizeof(int))) return -EFAULT; return 0; default: if (cnt++ < 10) printk(KERN_INFO "openprom_bsd_ioctl: cmd 0x%X\n", cmd); return -EINVAL; } }
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; unsigned long return_ip; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto give_sigsegv; err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; if (ka->sa.sa_flags & SA_RESTORER) { return_ip = (unsigned long)ka->sa.sa_restorer; } else { return_ip = (unsigned long)&frame->retcode; err |= __put_user(0x9c5f, (short __user *)(frame->retcode+0)); err |= __put_user(__NR_rt_sigreturn, (short __user *)(frame->retcode+2)); err |= __put_user(0xe93d, (short __user *)(frame->retcode+4)); } if (err) goto give_sigsegv; regs->irp = (unsigned long) ka->sa.sa_handler; regs->srp = return_ip; regs->r10 = sig; regs->r11 = (unsigned long)&frame->info; regs->r12 = 0; wrusp((unsigned long)frame); return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
static void setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t *funct_desc_ptr; struct rt_sigframe *frame; unsigned long newsp; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&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->gpr[1]), &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, signr, NULL, (unsigned long)ka->sa.sa_handler); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; /* Set up to return from userspace. */ err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto give_sigsegv; funct_desc_ptr = (func_descr_t *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; err |= put_user(0, (unsigned long *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); regs->link = (unsigned long) &frame->tramp[0]; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; err |= get_user(regs->gpr[4], (unsigned long *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long *)&frame->puc); regs->gpr[6] = (unsigned long) frame; if (err) goto give_sigsegv; return; give_sigsegv: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p, newsp=0x%lx\n", regs, frame, newsp); #endif do_exit(SIGSEGV); }
static int proc_dodebug(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { char tmpbuf[20], c, *s; char __user *p; unsigned int value; size_t left, len; if ((*ppos && !write) || !*lenp) { *lenp = 0; return 0; } left = *lenp; if (write) { if (!access_ok(VERIFY_READ, buffer, left)) return -EFAULT; p = buffer; while (left && __get_user(c, p) >= 0 && isspace(c)) left--, p++; if (!left) goto done; if (left > sizeof(tmpbuf) - 1) return -EINVAL; if (copy_from_user(tmpbuf, p, left)) return -EFAULT; tmpbuf[left] = '\0'; for (s = tmpbuf, value = 0; '0' <= *s && *s <= '9'; s++, left--) value = 10 * value + (*s - '0'); if (*s && !isspace(*s)) return -EINVAL; while (left && isspace(*s)) left--, s++; *(unsigned int *) table->data = value; /* Display the RPC tasks on writing to rpc_debug */ if (strcmp(table->procname, "rpc_debug") == 0) rpc_show_tasks(&init_net); } else { if (!access_ok(VERIFY_WRITE, buffer, left)) return -EFAULT; len = sprintf(tmpbuf, "%d", *(unsigned int *) table->data); if (len > left) len = left; if (__copy_to_user(buffer, tmpbuf, len)) return -EFAULT; if ((left -= len) > 0) { if (put_user('\n', (char __user *)buffer + len)) return -EFAULT; left--; } } done: *lenp -= left; *ppos += *lenp; return 0; }
/* * Save the current user registers on the user stack. * We only save the altivec/spe registers if the process has used * altivec/spe instructions at some point. */ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, int sigret) { /* save general and floating-point registers */ CHECK_FULL_REGS(regs); preempt_disable(); if (regs->msr & MSR_FP) giveup_fpu(current); #ifdef CONFIG_ALTIVEC if (current->thread.used_vr && (regs->msr & MSR_VEC)) giveup_altivec(current); #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_SPE if (current->thread.used_spe && (regs->msr & MSR_SPE)) giveup_spe(current); #endif /* CONFIG_ALTIVEC */ preempt_enable(); if (__copy_to_user(&frame->mc_gregs, regs, GP_REGS_SIZE) || __copy_to_user(&frame->mc_fregs, current->thread.fpr, ELF_NFPREG * sizeof(double))) return 1; current->thread.fpscr = 0; /* turn off all fp exceptions */ #ifdef CONFIG_ALTIVEC /* save altivec registers */ if (current->thread.used_vr) { if (__copy_to_user(&frame->mc_vregs, current->thread.vr, ELF_NVRREG * sizeof(vector128))) return 1; /* set MSR_VEC in the saved MSR value to indicate that frame->mc_vregs contains valid data */ if (__put_user(regs->msr | MSR_VEC, &frame->mc_gregs[PT_MSR])) return 1; } /* else assert((regs->msr & MSR_VEC) == 0) */ /* We always copy to/from vrsave, it's 0 if we don't have or don't * use altivec. Since VSCR only contains 32 bits saved in the least * significant bits of a vector, we "cheat" and stuff VRSAVE in the * most significant bits of that same vector. --BenH */ if (__put_user(current->thread.vrsave, (u32 __user *)&frame->mc_vregs[32])) return 1; #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_SPE /* save spe registers */ if (current->thread.used_spe) { if (__copy_to_user(&frame->mc_vregs, current->thread.evr, ELF_NEVRREG * sizeof(u32))) return 1; /* set MSR_SPE in the saved MSR value to indicate that frame->mc_vregs contains valid data */ if (__put_user(regs->msr | MSR_SPE, &frame->mc_gregs[PT_MSR])) return 1; } /* else assert((regs->msr & MSR_SPE) == 0) */ /* We always copy to/from spefscr */ if (__put_user(current->thread.spefscr, (u32 *)&frame->mc_vregs + ELF_NEVRREG)) return 1; #endif /* CONFIG_SPE */ if (sigret) { /* Set up the sigreturn trampoline: li r0,sigret; sc */ if (__put_user(0x38000000UL + sigret, &frame->tramp[0]) || __put_user(0x44000002UL, &frame->tramp[1])) return 1; flush_icache_range((unsigned long) &frame->tramp[0], (unsigned long) &frame->tramp[2]); } return 0; }
static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { rt_sigframe32 __user *frame; unsigned long restorer; size_t frame_size; u32 uc_flags; frame_size = sizeof(*frame) - sizeof(frame->uc.uc_mcontext_ext.__reserved); /* * gprs_high are always present for 31-bit compat tasks. * The space for vector registers is only allocated if * the machine supports it */ uc_flags = UC_GPRS_HIGH; if (MACHINE_HAS_VX) { if (current->thread.vxrs) uc_flags |= UC_VXRS; } else frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) + sizeof(frame->uc.uc_mcontext_ext.vxrs_high); frame = get_sigframe(&ksig->ka, regs, frame_size); if (frame == (void __user *) -1UL) return -EFAULT; /* Set up backchain. */ if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame)) return -EFAULT; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ksig->ka.sa.sa_flags & SA_RESTORER) { restorer = (unsigned long __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE; } else { __u16 __user *svc = &frame->svc_insn; if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc)) return -EFAULT; restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE; } /* Create siginfo on the signal stack */ if (copy_siginfo_to_user32(&frame->info, &ksig->info)) return -EFAULT; /* Store registers needed to create the signal frame */ store_sigregs(); /* Create ucontext on the signal stack. */ if (__put_user(uc_flags, &frame->uc.uc_flags) || __put_user(0, &frame->uc.uc_link) || __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) || save_sigregs32(regs, &frame->uc.uc_mcontext) || __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) || save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext)) return -EFAULT; /* Set up registers for signal handler */ regs->gprs[14] = restorer; regs->gprs[15] = (__force __u64) frame; /* Force 31 bit amode and default user address space control. */ regs->psw.mask = PSW_MASK_BA | (PSW_USER_BITS & PSW_MASK_ASC) | (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64 __force) ksig->ka.sa.sa_handler; regs->gprs[2] = map_signal(ksig->sig); regs->gprs[3] = (__force __u64) &frame->info; regs->gprs[4] = (__force __u64) &frame->uc; regs->gprs[5] = task_thread_info(current)->last_break; return 0; }
static int setup_frame32(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) { int sig = ksig->sig; sigframe32 __user *frame; struct sigcontext32 sc; unsigned long restorer; size_t frame_size; /* * gprs_high are always present for 31-bit compat tasks. * The space for vector registers is only allocated if * the machine supports it */ frame_size = sizeof(*frame) - sizeof(frame->sregs_ext.__reserved); if (!MACHINE_HAS_VX) frame_size -= sizeof(frame->sregs_ext.vxrs_low) + sizeof(frame->sregs_ext.vxrs_high); frame = get_sigframe(&ksig->ka, regs, frame_size); if (frame == (void __user *) -1UL) return -EFAULT; /* Set up backchain. */ if (__put_user(regs->gprs[15], (unsigned int __user *) frame)) return -EFAULT; /* Create struct sigcontext32 on the signal stack */ memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32); sc.sregs = (__u32)(unsigned long __force) &frame->sregs; if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc))) return -EFAULT; /* Store registers needed to create the signal frame */ store_sigregs(); /* Create _sigregs32 on the signal stack */ if (save_sigregs32(regs, &frame->sregs)) return -EFAULT; /* Place signal number on stack to allow backtrace from handler. */ if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo)) return -EFAULT; /* Create _sigregs_ext32 on the signal stack */ if (save_sigregs_ext32(regs, &frame->sregs_ext)) return -EFAULT; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ksig->ka.sa.sa_flags & SA_RESTORER) { restorer = (unsigned long __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE; } else { /* Signal frames without vectors registers are short ! */ __u16 __user *svc = (void __user *) frame + frame_size - 2; if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc)) return -EFAULT; restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE; } /* Set up registers for signal handler */ regs->gprs[14] = restorer; regs->gprs[15] = (__force __u64) frame; /* Force 31 bit amode and default user address space control. */ regs->psw.mask = PSW_MASK_BA | (PSW_USER_BITS & PSW_MASK_ASC) | (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__force __u64) ksig->ka.sa.sa_handler; regs->gprs[2] = map_signal(sig); regs->gprs[3] = (__force __u64) &frame->sc; /* We forgot to include these in the sigcontext. To avoid breaking binary compatibility, they are passed as args. */ if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL || sig == SIGTRAP || sig == SIGFPE) { /* set extra registers only for synchronous signals */ regs->gprs[4] = regs->int_code & 127; regs->gprs[5] = regs->int_parm_long; regs->gprs[6] = task_thread_info(current)->last_break; } return 0; }
static void 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->spu, 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 |= __put_user(signal, &frame->sig); if (err) goto give_sigsegv; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&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->spu), &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)); if (err) goto give_sigsegv; /* Set up to return from userspace. */ regs->lr = (unsigned long)ka->sa.sa_restorer; /* Set up registers for signal handler */ regs->spu = (unsigned long)frame; regs->r0 = signal; /* Arg for signal handler */ regs->r1 = (unsigned long)&frame->info; regs->r2 = (unsigned long)&frame->uc; regs->bpc = (unsigned long)ka->sa.sa_handler; set_fs(USER_DS); #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p\n", current->comm, current->pid, frame, regs->pc); #endif return; give_sigsegv: force_sigsegv(sig, current); }
int save_i387_xstate(void __user *buf) { struct task_struct *tsk = current; int err = 0; if (!access_ok(VERIFY_WRITE, buf, sig_xstate_size)) return -EACCES; BUG_ON(sig_xstate_size < xstate_size); if ((unsigned long)buf % 64) printk("save_i387_xstate: bad fpstate %p\n", buf); if (!used_math()) return 0; if (user_has_fpu()) { if (use_xsave()) err = xsave_user(buf); else err = fxsave_user(buf); if (err) return err; user_fpu_end(); } else { sanitize_i387_state(tsk); if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, xstate_size)) return -1; } clear_used_math(); /* trigger finit */ if (use_xsave()) { struct _fpstate __user *fx = buf; struct _xstate __user *x = buf; u64 xstate_bv; err = __copy_to_user(&fx->sw_reserved, &fx_sw_reserved, sizeof(struct _fpx_sw_bytes)); err |= __put_user(FP_XSTATE_MAGIC2, (__u32 __user *) (buf + sig_xstate_size - FP_XSTATE_MAGIC2_SIZE)); /* * Read the xstate_bv which we copied (directly from the cpu or * from the state in task struct) to the user buffers and * set the FP/SSE bits. */ err |= __get_user(xstate_bv, &x->xstate_hdr.xstate_bv); /* * For legacy compatible, we always set FP/SSE bits in the bit * vector while saving the state to the user context. This will * enable us capturing any changes(during sigreturn) to * the FP/SSE bits by the legacy applications which don't touch * xstate_bv in the xsave header. * * xsave aware apps can change the xstate_bv in the xsave * header as well as change any contents in the memory layout. * xrestore as part of sigreturn will capture all the changes. */ xstate_bv |= XSTATE_FPSSE; err |= __put_user(xstate_bv, &x->xstate_hdr.xstate_bv); if (err) return err; } return 1; }
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 |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->regs[15]), &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. */ 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; } 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; __get_user(regs->pc, &funcptr->text); __get_user(regs->regs[12], &funcptr->GOT); } else regs->pc = (unsigned long)ka->sa.sa_handler; 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); flush_icache_range(regs->pr, regs->pr + sizeof(frame->retcode)); return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) { unsigned long oldsp, r26, err = 0; struct rt_sigframe *frame; oldsp = rdusp(); frame = get_sigframe(ka, oldsp, sizeof(*frame)); if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; 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(set->sig[0], &frame->uc.uc_osf_sigmask); err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(oldsp), &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, sw, set->sig[0], oldsp); 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->ka_restorer) { r26 = (unsigned long) ka->ka_restorer; } else { err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn, frame->retcode+1); err |= __put_user(INSN_CALLSYS, frame->retcode+2); imb(); r26 = (unsigned long) frame->retcode; } if (err) goto give_sigsegv; /* "Return" to the handler */ regs->r26 = r26; regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; regs->r16 = sig; /* a0: signal number */ regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */ wrusp((unsigned long) frame); #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", current->comm, current->pid, frame, regs->pc, regs->r26); #endif return; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); }
static void setup_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset) { struct signal_frame __user *sf; int sigframe_size, err; /* 1. Make sure everything is clean */ synchronize_user_stack(); sigframe_size = SF_ALIGNEDSZ; if (!used_math()) sigframe_size -= sizeof(__siginfo_fpu_t); sf = (struct signal_frame __user *) get_sigframe(&ka->sa, regs, sigframe_size); if (invalid_frame_pointer(sf, sigframe_size)) goto sigill_and_return; tail = sf + 1; /* 2. Save the current process state */ err = __copy_to_user(&sf->info.si_regs, regs, sizeof(struct pt_regs)); err |= __put_user(0, &sf->extra_size); if (used_math()) { __siginfo_fpu_t __user *fp = tail; tail += sizeof(*fp); err |= save_fpu_state(regs, fp); err |= __put_user(fp, &sf->fpu_save); } else { err |= __put_user(0, &sf->fpu_save); } if (wsaved) { __siginfo_rwin_t __user *rwp = tail; tail += sizeof(*rwp); err |= save_rwin_state(wsaved, rwp); err |= __put_user(rwp, &sf->rwin_save); } else { err |= __put_user(0, &sf->rwin_save); } err |= __put_user(oldset->sig[0], &sf->info.si_mask); err |= __copy_to_user(sf->extramask, &oldset->sig[1], (_NSIG_WORDS - 1) * sizeof(unsigned int)); if (!wsaved) { err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], sizeof(struct reg_window32)); } else { struct reg_window32 *rp; rp = ¤t_thread_info()->reg_window[wsaved - 1]; err |= __copy_to_user(sf, rp, sizeof(struct reg_window32)); } if (err) goto sigsegv; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; regs->u_regs[UREG_I2] = (unsigned long) &sf->info; /* 4. signal handler */ regs->pc = (unsigned long) ka->sa.sa_handler; regs->npc = (regs->pc + 4); /* 5. return to kernel instructions */ if (ka->ka_restorer) regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; else { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); /* mov __NR_sigreturn, %g1 */ err |= __put_user(0x821020d8, &sf->insns[0]); /* t 0x10 */ err |= __put_user(0x91d02010, &sf->insns[1]); if (err) goto sigsegv; /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } return; sigill_and_return: do_exit(SIGILL); sigsegv: force_sigsegv(signo, current); }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set) { struct rt_sigframe __user *frame; int rsig; frame = get_sigframe(ka, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; rsig = sig; if (sig < 32 && __current_thread_info->exec_domain && __current_thread_info->exec_domain->signal_invmap) rsig = __current_thread_info->exec_domain->signal_invmap[sig]; if (__put_user(rsig, &frame->sig) || __put_user(&frame->info, &frame->pinfo) || __put_user(&frame->uc, &frame->puc)) goto give_sigsegv; if (copy_siginfo_to_user(&frame->info, info)) goto give_sigsegv; /* Create the ucontext. */ if (__put_user(0, &frame->uc.uc_flags) || __put_user(NULL, &frame->uc.uc_link) || __put_user((void __user *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp) || __put_user(sas_ss_flags(__frame->sp), &frame->uc.uc_stack.ss_flags) || __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size)) goto give_sigsegv; if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0])) goto give_sigsegv; if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) goto give_sigsegv; /* Set up to return from userspace. If provided, use a stub * already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { if (__put_user(ka->sa.sa_restorer, &frame->pretcode)) goto give_sigsegv; } else { /* Set up the following code on the stack: * setlos #__NR_sigreturn,gr7 * tira gr0,0 */ if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) || __put_user(0xc0700000, &frame->retcode[1])) goto give_sigsegv; flush_icache_range((unsigned long) frame->retcode, (unsigned long) (frame->retcode + 2)); } /* Set up registers for signal handler */ __frame->sp = (unsigned long) frame; __frame->lr = (unsigned long) &frame->retcode; __frame->gr8 = sig; __frame->gr9 = (unsigned long) &frame->info; if (get_personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); __get_user(__frame->gr15, &funcptr->GOT); } else { __frame->pc = (unsigned long) ka->sa.sa_handler; __frame->gr15 = 0; } set_fs(USER_DS); /* the tracer may want to single-step inside the handler */ if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); #if DEBUG_SIG printk("SIG deliver %d (%s:%d): sp=%p pc=%lx ra=%p\n", sig, current->comm, current->pid, frame, __frame->pc, frame->pretcode); #endif return 0; give_sigsegv: force_sig(SIGSEGV, current); return -EFAULT; } /* end setup_rt_frame() */
/* * As above, but Transactional Memory is in use, so deliver sigcontexts * containing checkpointed and transactional register states. * * To do this, we treclaim (done before entering here) to gather both sets of * registers and set up the 'normal' sigcontext registers with rolled-back * register values such that a simple signal handler sees a correct * checkpointed register state. If interested, a TM-aware sighandler can * examine the transactional registers in the 2nd sigcontext to determine the * real origin of the signal. */ static long setup_tm_sigcontexts(struct sigcontext __user *sc, struct sigcontext __user *tm_sc, struct pt_regs *regs, int signr, sigset_t *set, unsigned long handler) { /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the * process never used altivec yet (MSR_VEC is zero in pt_regs of * the context). This is very important because we must ensure we * don't lose the VRSAVE content that may have been set prior to * the process doing its first vector operation * Userland shall check AT_HWCAP to know wether it can rely on the * v_regs pointer or not. */ #ifdef CONFIG_ALTIVEC elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *) (((unsigned long)sc->vmx_reserve + 15) & ~0xful); elf_vrreg_t __user *tm_v_regs = (elf_vrreg_t __user *) (((unsigned long)tm_sc->vmx_reserve + 15) & ~0xful); #endif unsigned long msr = regs->msr; long err = 0; BUG_ON(!MSR_TM_ACTIVE(regs->msr)); /* Remove TM bits from thread's MSR. The MSR in the sigcontext * just indicates to userland that we were doing a transaction, but we * don't want to return in transactional state. This also ensures * that flush_fp_to_thread won't set TIF_RESTORE_TM again. */ regs->msr &= ~MSR_TS_MASK; flush_fp_to_thread(current); #ifdef CONFIG_ALTIVEC err |= __put_user(v_regs, &sc->v_regs); err |= __put_user(tm_v_regs, &tm_sc->v_regs); /* save altivec registers */ if (current->thread.used_vr) { flush_altivec_to_thread(current); /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ err |= __copy_to_user(v_regs, ¤t->thread.vr_state, 33 * sizeof(vector128)); /* If VEC was enabled there are transactional VRs valid too, * else they're a copy of the checkpointed VRs. */ if (msr & MSR_VEC) err |= __copy_to_user(tm_v_regs, ¤t->thread.transact_vr, 33 * sizeof(vector128)); else err |= __copy_to_user(tm_v_regs, ¤t->thread.vr_state, 33 * sizeof(vector128)); /* set MSR_VEC in the MSR value in the frame to indicate * that sc->v_reg contains valid data. */ msr |= MSR_VEC; } /* We always copy to/from vrsave, it's 0 if we don't have or don't * use altivec. */ if (cpu_has_feature(CPU_FTR_ALTIVEC)) current->thread.vrsave = mfspr(SPRN_VRSAVE); err |= __put_user(current->thread.vrsave, (u32 __user *)&v_regs[33]); if (msr & MSR_VEC) err |= __put_user(current->thread.transact_vrsave, (u32 __user *)&tm_v_regs[33]); else err |= __put_user(current->thread.vrsave, (u32 __user *)&tm_v_regs[33]); #else /* CONFIG_ALTIVEC */ err |= __put_user(0, &sc->v_regs); err |= __put_user(0, &tm_sc->v_regs); #endif /* CONFIG_ALTIVEC */ /* copy fpr regs and fpscr */ err |= c
static int lcd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { struct lcd_display button_display; unsigned long address, a; switch (cmd) { case LCD_On: udelay(150); BusyCheck(); LCDWriteInst(0x0F); break; case LCD_Off: udelay(150); BusyCheck(); LCDWriteInst(0x08); break; case LCD_Reset: udelay(150); LCDWriteInst(0x3F); udelay(150); LCDWriteInst(0x3F); udelay(150); LCDWriteInst(0x3F); udelay(150); LCDWriteInst(0x3F); udelay(150); LCDWriteInst(0x01); udelay(150); LCDWriteInst(0x06); break; case LCD_Clear: udelay(150); BusyCheck(); LCDWriteInst(0x01); break; case LCD_Cursor_Left: udelay(150); BusyCheck(); LCDWriteInst(0x10); break; case LCD_Cursor_Right: udelay(150); BusyCheck(); LCDWriteInst(0x14); break; case LCD_Cursor_Off: udelay(150); BusyCheck(); LCDWriteInst(0x0C); break; case LCD_Cursor_On: udelay(150); BusyCheck(); LCDWriteInst(0x0F); break; case LCD_Blink_Off: udelay(150); BusyCheck(); LCDWriteInst(0x0E); break; case LCD_Get_Cursor_Pos:{ struct lcd_display display; udelay(150); BusyCheck(); display.cursor_address = (LCDReadInst); display.cursor_address = (display.cursor_address & 0x07F); if (copy_to_user ((struct lcd_display *) arg, &display, sizeof(struct lcd_display))) return -EFAULT; break; } case LCD_Set_Cursor_Pos:{ struct lcd_display display; if (copy_from_user (&display, (struct lcd_display *) arg, sizeof(struct lcd_display))) return -EFAULT; a = (display.cursor_address | kLCD_Addr); udelay(150); BusyCheck(); LCDWriteInst(a); break; } case LCD_Get_Cursor:{ struct lcd_display display; udelay(150); BusyCheck(); display.character = LCDReadData; if (copy_to_user ((struct lcd_display *) arg, &display, sizeof(struct lcd_display))) return -EFAULT; udelay(150); BusyCheck(); LCDWriteInst(0x10); break; } case LCD_Set_Cursor:{ struct lcd_display display; if (copy_from_user (&display, (struct lcd_display *) arg, sizeof(struct lcd_display))) return -EFAULT; udelay(150); BusyCheck(); LCDWriteData(display.character); udelay(150); BusyCheck(); LCDWriteInst(0x10); break; } case LCD_Disp_Left: udelay(150); BusyCheck(); LCDWriteInst(0x18); break; case LCD_Disp_Right: udelay(150); BusyCheck(); LCDWriteInst(0x1C); break; case LCD_Home: udelay(150); BusyCheck(); LCDWriteInst(0x02); break; case LCD_Write:{ struct lcd_display display; unsigned int index; if (copy_from_user (&display, (struct lcd_display *) arg, sizeof(struct lcd_display))) return -EFAULT; udelay(150); BusyCheck(); LCDWriteInst(0x80); udelay(150); BusyCheck(); for (index = 0; index < (display.size1); index++) { udelay(150); BusyCheck(); LCDWriteData(display.line1[index]); BusyCheck(); } udelay(150); BusyCheck(); LCDWriteInst(0xC0); udelay(150); BusyCheck(); for (index = 0; index < (display.size2); index++) { udelay(150); BusyCheck(); LCDWriteData(display.line2[index]); } break; } case LCD_Read:{ struct lcd_display display; BusyCheck(); for (address = kDD_R00; address <= kDD_R01; address++) { a = (address | kLCD_Addr); udelay(150); BusyCheck(); LCDWriteInst(a); udelay(150); BusyCheck(); display.line1[address] = LCDReadData; } display.line1[0x27] = '\0'; for (address = kDD_R10; address <= kDD_R11; address++) { a = (address | kLCD_Addr); udelay(150); BusyCheck(); LCDWriteInst(a); udelay(150); BusyCheck(); display.line2[address - 0x40] = LCDReadData; } display.line2[0x27] = '\0'; if (copy_to_user ((struct lcd_display *) arg, &display, sizeof(struct lcd_display))) return -EFAULT; break; } // set all GPIO leds to led_display.leds case LED_Set:{ struct lcd_display led_display; if (copy_from_user (&led_display, (struct lcd_display *) arg, sizeof(struct lcd_display))) return -EFAULT; led_state = led_display.leds; LEDSet(led_state); break; } // set only bit led_display.leds case LED_Bit_Set:{ unsigned int i; int bit = 1; struct lcd_display led_display; if (copy_from_user (&led_display, (struct lcd_display *) arg, sizeof(struct lcd_display))) return -EFAULT; for (i = 0; i < (int) led_display.leds; i++) { bit = 2 * bit; } led_state = led_state | bit; LEDSet(led_state); break; } // clear only bit led_display.leds case LED_Bit_Clear:{ unsigned int i; int bit = 1; struct lcd_display led_display; if (copy_from_user (&led_display, (struct lcd_display *) arg, sizeof(struct lcd_display))) return -EFAULT; for (i = 0; i < (int) led_display.leds; i++) { bit = 2 * bit; } led_state = led_state & ~bit; LEDSet(led_state); break; } case BUTTON_Read:{ button_display.buttons = GPIRead; if (copy_to_user ((struct lcd_display *) arg, &button_display, sizeof(struct lcd_display))) return -EFAULT; break; } case LINK_Check:{ button_display.buttons = *((volatile unsigned long *) (0xB0100060)); if (copy_to_user ((struct lcd_display *) arg, &button_display, sizeof(struct lcd_display))) return -EFAULT; break; } case LINK_Check_2:{ int iface_num; /* panel-utils should pass in the desired interface status is wanted for * in "buttons" of the structure. We will set this to non-zero if the * link is in fact up for the requested interface. --DaveM */ if (copy_from_user (&button_display, (struct lcd_display *) arg, sizeof(button_display))) return -EFAULT; iface_num = button_display.buttons; #if defined(CONFIG_TULIP) && 0 if (iface_num >= 0 && iface_num < MAX_INTERFACES && linkcheck_callbacks[iface_num] != NULL) { button_display.buttons = linkcheck_callbacks[iface_num] (linkcheck_cookies[iface_num]); } else #endif button_display.buttons = 0; if (__copy_to_user ((struct lcd_display *) arg, &button_display, sizeof(struct lcd_display))) return -EFAULT; break; } default: return -EINVAL; } return 0; }
/* * Handle {get,set,swap}_context operations */ int sys_swapcontext(struct ucontext __user *old_ctx, struct ucontext __user *new_ctx, long ctx_size, long r6, long r7, long r8, struct pt_regs *regs) { unsigned char tmp; sigset_t set; unsigned long new_msr = 0; int ctx_has_vsx_region = 0; if (new_ctx && get_user(new_msr, &new_ctx->uc_mcontext.gp_regs[PT_MSR])) return -EFAULT; /* * Check that the context is not smaller than the original * size (with VMX but without VSX) */ if (ctx_size < UCONTEXTSIZEWITHOUTVSX) return -EINVAL; /* * If the new context state sets the MSR VSX bits but * it doesn't provide VSX state. */ if ((ctx_size < sizeof(struct ucontext)) && (new_msr & MSR_VSX)) return -EINVAL; /* Does the context have enough room to store VSX data? */ if (ctx_size >= sizeof(struct ucontext)) ctx_has_vsx_region = 1; if (old_ctx != NULL) { if (!access_ok(VERIFY_WRITE, old_ctx, ctx_size) || setup_sigcontext(&old_ctx->uc_mcontext, regs, 0, NULL, 0, ctx_has_vsx_region) || __copy_to_user(&old_ctx->uc_sigmask, ¤t->blocked, sizeof(sigset_t))) return -EFAULT; } if (new_ctx == NULL) return 0; if (!access_ok(VERIFY_READ, new_ctx, ctx_size) || __get_user(tmp, (u8 __user *) new_ctx) || __get_user(tmp, (u8 __user *) new_ctx + ctx_size - 1)) return -EFAULT; /* * If we get a fault copying the context into the kernel's * image of the user's registers, we can't just return -EFAULT * because the user's registers will be corrupted. For instance * the NIP value may have been updated but not some of the * other registers. Given that we have done the access_ok * and successfully read the first and last bytes of the region * above, this should only happen in an out-of-memory situation * or if another thread unmaps the region containing the context. * We kill the task with a SIGSEGV in this situation. */ if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set))) do_exit(SIGSEGV); set_current_blocked(&set); if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext)) do_exit(SIGSEGV); /* This returns like rt_sigreturn */ set_thread_flag(TIF_RESTOREALL); return 0; }
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { /* Handler is *really* a pointer to the function descriptor for * the signal routine. The first entry in the function * descriptor is the entry address of signal and the second * entry is the TOC value we need to use. */ func_descr_t __user *funct_desc_ptr; struct rt_sigframe __user *frame; unsigned long newsp = 0; long err = 0; frame = get_sigframe(ka, regs, sizeof(*frame), 0); if (unlikely(frame == NULL)) goto badframe; err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto badframe; /* 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->gpr[1]), &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, signr, NULL, (unsigned long)ka->sa.sa_handler, 1); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto badframe; /* Make sure signal handler doesn't get spurious FP exceptions */ current->thread.fpscr.val = 0; /* Set up to return from userspace. */ if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; } else { err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); if (err) goto badframe; regs->link = (unsigned long) &frame->tramp[0]; } funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; /* Allocate a dummy caller frame for the signal handler. */ newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); /* Set up "regs" so we "return" to the signal handler. */ err |= get_user(regs->nip, &funct_desc_ptr->entry); /* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE; regs->gpr[1] = newsp; err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); regs->gpr[3] = signr; regs->result = 0; if (ka->sa.sa_flags & SA_SIGINFO) { err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); regs->gpr[6] = (unsigned long) frame; } else { regs->gpr[4] = (unsigned long)&frame->uc.uc_mcontext; } if (err) goto badframe; return 1; badframe: #if DEBUG_SIG printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); #endif if (show_unhandled_signals && printk_ratelimit()) printk(regs->msr & MSR_SF ? fmt64 : fmt32, current->comm, current->pid, "setup_rt_frame", (long)frame, regs->nip, regs->link); force_sigsegv(signr, current); return 0; }
static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int signr, sigset_t *set, unsigned long handler, int ctx_has_vsx_region) { /* When CONFIG_ALTIVEC is set, we _always_ setup v_regs even if the * process never used altivec yet (MSR_VEC is zero in pt_regs of * the context). This is very important because we must ensure we * don't lose the VRSAVE content that may have been set prior to * the process doing its first vector operation * Userland shall check AT_HWCAP to know whether it can rely on the * v_regs pointer or not */ #ifdef CONFIG_ALTIVEC elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve + 15) & ~0xful); #endif unsigned long msr = regs->msr; long err = 0; flush_fp_to_thread(current); #ifdef CONFIG_ALTIVEC err |= __put_user(v_regs, &sc->v_regs); /* save altivec registers */ if (current->thread.used_vr) { flush_altivec_to_thread(current); /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128)); /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) * contains valid data. */ msr |= MSR_VEC; } /* We always copy to/from vrsave, it's 0 if we don't have or don't * use altivec. */ err |= __put_user(current->thread.vrsave, (u32 __user *)&v_regs[33]); #else /* CONFIG_ALTIVEC */ err |= __put_user(0, &sc->v_regs); #endif /* CONFIG_ALTIVEC */ flush_fp_to_thread(current); /* copy fpr regs and fpscr */ err |= copy_fpr_to_user(&sc->fp_regs, current); /* * Clear the MSR VSX bit to indicate there is no valid state attached * to this context, except in the specific case below where we set it. */ msr &= ~MSR_VSX; #ifdef CONFIG_VSX /* * Copy VSX low doubleword to local buffer for formatting, * then out to userspace. Update v_regs to point after the * VMX data. */ if (current->thread.used_vsr && ctx_has_vsx_region) { __giveup_vsx(current); v_regs += ELF_NVRREG; err |= copy_vsx_to_user(v_regs, current); /* set MSR_VSX in the MSR value in the frame to * indicate that sc->vs_reg) contains valid data. */ msr |= MSR_VSX; } #endif /* CONFIG_VSX */ err |= __put_user(&sc->gp_regs, &sc->regs); WARN_ON(!FULL_REGS(regs)); err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE); err |= __put_user(msr, &sc->gp_regs[PT_MSR]); err |= __put_user(signr, &sc->signal); err |= __put_user(handler, &sc->handler); if (set != NULL) err |= __put_user(set->sig[0], &sc->oldmask); return err; }
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; struct _fpstate __user *fp = NULL; int err = 0; struct task_struct *me = current; if (used_math()) { fp = get_stack(ka, regs, sizeof(struct _fpstate)); frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto give_sigsegv; if (save_i387(fp) < 0) err |= -1; } else frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; if (ka->sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&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(me->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(me->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); 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 give_sigsegv; } if (err) goto give_sigsegv; /* Set up registers for signal handler */ regs->di = sig; /* In case the signal handler was declared without prototypes */ regs->ax = 0; /* This also works for non SA_SIGINFO handlers because they expect the next argument after the signal number on the stack. */ regs->si = (unsigned long)&frame->info; regs->dx = (unsigned long)&frame->uc; regs->ip = (unsigned long) ka->sa.sa_handler; regs->sp = (unsigned long)frame; /* Set up the CS register to run signal handlers in 64-bit mode, even if the handler happens to be interrupting 32-bit code. */ regs->cs = __USER_CS; return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
int ia32_setup_frame(int sig, struct ksignal *ksig, compat_sigset_t *set, struct pt_regs *regs) { struct sigframe_ia32 __user *frame; void __user *restorer; int err = 0; void __user *fpstate = NULL; /* copy_to_user optimizes that into a single 8 byte store */ static const struct { u16 poplmovl; u32 val; u16 int80; } __attribute__((packed)) code = { 0xb858, /* popl %eax ; movl $...,%eax */ __NR_ia32_sigreturn, 0x80cd, /* int $0x80 */ }; frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) return -EFAULT; if (__put_user(sig, &frame->sig)) return -EFAULT; if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0])) return -EFAULT; if (_COMPAT_NSIG_WORDS > 1) { if (__copy_to_user(frame->extramask, &set->sig[1], sizeof(frame->extramask))) return -EFAULT; } if (ksig->ka.sa.sa_flags & SA_RESTORER) { restorer = ksig->ka.sa.sa_restorer; } else { /* Return stub is in 32bit vsyscall page */ if (current->mm->context.vdso) restorer = current->mm->context.vdso + vdso_image_32.sym___kernel_sigreturn; else restorer = &frame->retcode; } put_user_try { put_user_ex(ptr_to_compat(restorer), &frame->pretcode); /* * These are actually not used anymore, but left because some * gdb versions depend on them as a marker. */ put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode); } put_user_catch(err); if (err) return -EFAULT; /* Set up registers for signal handler */ regs->sp = (unsigned long) frame; regs->ip = (unsigned long) ksig->ka.sa.sa_handler; /* Make -mregparm=3 work */ regs->ax = sig; regs->dx = 0; regs->cx = 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; struct _fpstate __user *fp = NULL; int err = 0; struct task_struct *me = current; if (used_math()) { fp = get_stack(ka, regs, sizeof(struct _fpstate)); frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto give_sigsegv; if (save_i387(fp) < 0) err |= -1; } else frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; if (ka->sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&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(me->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(me->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); 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 give_sigsegv; } if (err) goto give_sigsegv; #ifdef DEBUG_SIG printk("%d old rip %lx old rsp %lx old rax %lx\n", current->pid,regs->rip,regs->rsp,regs->rax); #endif /* Set up registers for signal handler */ regs->rdi = sig; /* In case the signal handler was declared without prototypes */ regs->rax = 0; /* This also works for non SA_SIGINFO handlers because they expect the next argument after the signal number on the stack. */ regs->rsi = (unsigned long)&frame->info; regs->rdx = (unsigned long)&frame->uc; regs->rip = (unsigned long) ka->sa.sa_handler; regs->rsp = (unsigned long)frame; /* Set up the CS register to run signal handlers in 64-bit mode, even if the handler happens to be interrupting 32-bit code. */ regs->cs = __USER_CS; /* This, by contrast, has nothing to do with segment registers - see include/asm-x86_64/uaccess.h for details. */ set_fs(USER_DS); regs->eflags &= ~TF_MASK; if (test_thread_flag(TIF_SINGLESTEP)) ptrace_notify(SIGTRAP); #ifdef DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", current->comm, current->pid, frame, regs->rip, frame->pretcode); #endif return 0; give_sigsegv: force_sigsegv(sig, current); return -EFAULT; }
int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { unsigned long restorer; struct compat_rt_sigframe __user *frame; int err = 0; int usig; frame = compat_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_user32(&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(0, &frame->uc.uc_link); err |= __put_user(ptr_to_compat((void *)(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 = ptr_to_compat_reg(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. */ regs->pc = ptr_to_compat_reg(ka->sa.sa_handler); regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->sp = ptr_to_compat_reg(frame); regs->lr = restorer; regs->regs[0] = (unsigned long) usig; if (ka->sa.sa_flags & SA_SIGINFO) { /* Need extra arguments, so mark to restore caller-saves. */ regs->regs[1] = ptr_to_compat_reg(&frame->info); regs->regs[2] = ptr_to_compat_reg(&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; }
static int setup_signal_frame( unsigned long signum, siginfo_t * siginfo, struct sigaction * sigact, sigset_t * oldset, struct pt_regs * regs ) { struct rt_sigframe __user *frame; struct _fpstate __user *fp; int err = 0; fp = get_stack(regs, sizeof(struct _fpstate)); frame = (void __user *)round_down( (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8; if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate))) goto give_sigsegv; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; // Save essential state needed by sys_rt_sigreturn() to user-stack err |= save_ptregs_to_user_stack(&frame->uc.uc_mcontext, regs); err |= save_fpu_state_to_user_stack(&frame->uc.uc_mcontext, fp); err |= __copy_to_user(&frame->uc.uc_sigmask, oldset, sizeof(*oldset)); // Save other misc-state to user-stack. Userspace might expect // this stuff but kernel does not need it for sys_rt_sigreturn() err |= save_misc_state_to_user_stack(frame, oldset); err |= copy_siginfo_to_user(&frame->siginfo, siginfo); // Setup for return from userspace signal handler. // When signal handler returns, &frame->pretcode is executed, // which then calls sys_rt_sigreturn(). err |= __put_user(sigact->sa_restorer, &frame->pretcode); if (err) goto give_sigsegv; // Set up registers for signal handler regs->rsp = (unsigned long)frame; regs->cs = __USER_CS; regs->rax = 0; regs->rdi = signum; // ARG0 regs->rsi = (unsigned long)&frame->siginfo; // ARG1 regs->rdx = (unsigned long)&frame->uc; // ARG2 regs->rip = (unsigned long)sigact->sa_handler; // signal handler() // This has nothing to do with segment registers - // see include/asm-x86_64/uaccess.h for details. set_fs(USER_DS); return 1; give_sigsegv: //force_sigsegv(signum, current) printk("GIVE_SIGSEGV\n"); return 0; }