static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long sp = regs->r29; /* Switch to signal stack if appropriate */ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1)); }
/* * Determine which stack to use.. */ static inline void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) { /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } return (void __user *)((sp - frame_size) & -8ul); }
static int copy_ucontext_to_user(struct ucontext __user *uc, struct _fpstate __user *fp, sigset_t *set, unsigned long sp) { int err = 0; err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, sp); err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); 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 *frame; int err = 0; frame = get_sigframe(ka, regs, sizeof(*frame)); err |= __put_user((current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain-> signal_invmap[sig] : sig), &frame->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(rdusp()), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= rt_setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; /* Set up registers for signal handler */ wrusp((unsigned long)frame); if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor *) ka->sa.sa_handler; __get_user(regs->pc, &funcptr->text); __get_user(regs->p3, &funcptr->GOT); } else regs->pc = (unsigned long)ka->sa.sa_handler; regs->rets = SIGRETURN_STUB; regs->r0 = frame->sig; regs->r1 = (unsigned long)(&frame->info); regs->r2 = (unsigned long)(&frame->uc); 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) { int err = 0; rt_sigframe __user *frame; frame = get_sigframe(ka, regs, sizeof(rt_sigframe)); if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe))) goto give_sigsegv; if (copy_siginfo_to_user(&frame->info, info)) goto give_sigsegv; /* Create the ucontext. */ err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_link); err |= __put_user((void *)current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->gprs[15]), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= save_sigregs(regs, &frame->uc.uc_mcontext); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err) goto give_sigsegv; /* Set up to return from userspace. If provided, use a stub already in userspace. */ if (ka->sa.sa_flags & SA_RESTORER) { regs->gprs[14] = (unsigned long) ka->sa.sa_restorer | PSW_ADDR_AMODE; } else { regs->gprs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE; err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, (u16 __user *)(frame->retcode)); } /* Set up backchain. */ if (__put_user(regs->gprs[15], (addr_t __user *) frame)) goto give_sigsegv; /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); regs->gprs[3] = (unsigned long) &frame->info; regs->gprs[4] = (unsigned long) &frame->uc; return; give_sigsegv: force_sigsegv(sig, current); }
static int copy_ucontext_to_user(struct ucontext *uc, void *fp, sigset_t *set, unsigned long sp) { int err = 0; err |= put_user(current->sas_ss_sp, &uc->uc_stack.ss_sp); err |= put_user(sas_ss_flags(sp), &uc->uc_stack.ss_flags); err |= put_user(current->sas_ss_size, &uc->uc_stack.ss_size); err |= copy_sc_to_user(&uc->uc_mcontext, fp, ¤t->thread.regs, &signal_frame_si.common.arch); err |= copy_to_user(&uc->uc_sigmask, set, sizeof(*set)); return(err); }
/* * OK, we're invoking a handler */ static int handle_signal(struct pt_regs *regs, unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset) { unsigned long sp; int err; /* Always make any pending restarted system calls return -EINTR */ current_thread_info()->restart_block.fn = do_no_restart_syscall; /* Did we come from a system call? */ if (PT_REGS_SYSCALL_NR(regs) >= 0) { /* If so, check system call restarting.. */ switch (PT_REGS_SYSCALL_RET(regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: PT_REGS_SYSCALL_RET(regs) = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { PT_REGS_SYSCALL_RET(regs) = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: PT_REGS_RESTART_SYSCALL(regs); PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); break; } } sp = PT_REGS_SP(regs); if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; #ifdef CONFIG_ARCH_HAS_SC_SIGNALS if (!(ka->sa.sa_flags & SA_SIGINFO)) err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); else #endif err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); if (err) force_sigsegv(signr, current); else block_sigmask(ka, signr); 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; frame = get_sigframe(ka, regs, sizeof(*frame)); 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(rdusp()), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= rt_setup_ucontext(&frame->uc, regs); err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set)); /* Set up to return from userspace. */ err |= __put_user(frame->retcode, &frame->pretcode); /* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */ err != __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff), (long *)(frame->retcode + 0)); err |= __put_user(0x5700, (short *)(frame->retcode + 4)); if (err) goto give_sigsegv; /* Set up registers for signal handler */ wrusp ((unsigned long) frame); regs->pc = (unsigned long) ka->sa.sa_handler; regs->er0 = (current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap && sig < 32 ? current_thread_info()->exec_domain->signal_invmap[sig] : sig); regs->er1 = (unsigned long)&(frame->info); regs->er2 = (unsigned long)&frame->uc; regs->er5 = current->mm->start_data; /* GOT base */ return; give_sigsegv: force_sigsegv(sig, current); }
static inline void * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long usp; /* Default to using normal stack. */ usp = rdusp(); /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (!sas_ss_flags(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } return (void *)((usp - frame_size) & -8UL); }
static inline void * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long usp; /* */ usp = rdusp(); /* */ if (ka->sa.sa_flags & SA_ONSTACK) { if (!sas_ss_flags(usp)) usp = current->sas_ss_sp + current->sas_ss_size; } return (void *)((usp - frame_size) & -8UL); }
static void __user * get_stack(struct k_sigaction *ka, struct pt_regs *regs, unsigned long size) { unsigned long rsp; /* Default to using normal stack - redzone*/ rsp = regs->rsp - 128; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(rsp) == 0) rsp = current->sas_ss_sp + current->sas_ss_size; } return (void __user *)round_down(rsp - size, 16); }
static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) { unsigned long sp = regs->ARM_sp; /* * This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; /* * ATPCS B01 mandates 8-byte alignment */ return (void __user *)((sp - framesize) & ~7); }
static inline void * get_sigframe(struct k_sigaction *ka, struct exregs_regs *regs, int framesize) { unsigned long sp = regs->sp; printk_dbg("%s called\n", __func__); /* * This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; /* * ATPCS B01 mandates 8-byte alignment */ return (void *)((sp - framesize) & ~7); }
/* * Determine which stack to use.. */ static inline void __user *get_sigframe(struct k_sigaction *ka, size_t frame_size) { unsigned long sp; /* Default to using normal stack */ sp = __frame->sp; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; } return (void __user *) ((sp - frame_size) & ~7UL); } /* end get_sigframe() */
/* * determine which stack to use.. */ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long sp; /* default to using normal stack */ sp = regs->sp; /* this is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } return (void __user *) ((sp - frame_size) & ~7UL); }
/* * OK, we're invoking a handler */ static void handle_signal(struct pt_regs *regs, unsigned long signr, struct k_sigaction *ka, siginfo_t *info) { sigset_t *oldset = sigmask_to_save(); unsigned long sp; int err; /* Did we come from a system call? */ if (PT_REGS_SYSCALL_NR(regs) >= 0) { /* If so, check system call restarting.. */ switch (PT_REGS_SYSCALL_RET(regs)) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: PT_REGS_SYSCALL_RET(regs) = -EINTR; break; case -ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { PT_REGS_SYSCALL_RET(regs) = -EINTR; break; } /* fallthrough */ case -ERESTARTNOINTR: PT_REGS_RESTART_SYSCALL(regs); PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); break; } } sp = PT_REGS_SP(regs); if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; #ifdef CONFIG_ARCH_HAS_SC_SIGNALS if (!(ka->sa.sa_flags & SA_SIGINFO)) err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); else #endif err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); if (err) force_sigsegv(signr, current); else signal_delivered(signr, info, ka, regs, 0); }
static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) { unsigned long sp = regs->sp; /* * This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; /* * No matter what happens, 'sp' must be dword * aligned. Otherwise, nasty things will happen */ return (void __user *)((sp - framesize) & ~7); }
static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) { unsigned long sp = regs->ARM_sp; void __user *frame; if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; frame = (void __user *)((sp - framesize) & ~7); if (!access_ok(VERIFY_WRITE, frame, framesize)) frame = NULL; return frame; }
static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); stack_t stack; int err = 0; if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) return 1; __put_user_error(&frame->info, &frame->pinfo, err); __put_user_error(&frame->uc, &frame->puc, err); err |= copy_siginfo_to_user(&frame->info, info); __put_user_error(0, &frame->uc.uc_flags, err); __put_user_error(NULL, &frame->uc.uc_link, err); memset(&stack, 0, sizeof(stack)); stack.ss_sp = (void *)current->sas_ss_sp; stack.ss_flags = sas_ss_flags(regs->ARM_sp); stack.ss_size = current->sas_ss_size; err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack)); err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/ regs, set->sig[0]); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (err == 0) err = setup_return(regs, ka, &frame->retcode, frame, usig); if (err == 0) { /* * For realtime signals we must also set the second and third * arguments for the signal handler. * -- Peter Maydell <*****@*****.**> 2000-12-06 */ regs->ARM_r1 = (unsigned long)&frame->info; regs->ARM_r2 = (unsigned long)&frame->uc; } return err; }
static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) { unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; if (on_sig_stack(sp) && !likely(on_sig_stack(sp - framesize))) return (void __user *) -1L; if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } sp -= framesize; sp &= ~15UL; return (void __user *) sp; }
/* * Determine which stack to use.. */ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, void **fpstate) { unsigned long sp; /* Default to using normal stack */ sp = regs->sp; /* * If we are on the alternate signal stack and would overflow it, don't. * Return an always-bogus address instead so we will die with SIGSEGV. */ if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) return (void __user *) -1L; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } else { /* This is the legacy signal stack switching. */ if ((regs->ss & 0xffff) != __USER_DS && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) sp = (unsigned long) ka->sa.sa_restorer; } if (used_math()) { sp = sp - sig_xstate_size; *fpstate = (struct _fpstate *) sp; } sp -= frame_size; /* * Align the stack pointer according to the i386 ABI, * i.e. so that on function entry ((sp + 4) & 15) == 0. */ sp = ((sp + 4) & -16ul) - 4; return (void __user *) sp; }
/* * Determine which stack to use.. */ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) { unsigned long sp; /* Default to using normal stack */ sp = (unsigned long) A(regs->gprs[15]); /* Overflow on alternate signal stack gives SIGSEGV. */ if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL)) return (void __user *) -1UL; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; } return (void __user *)((sp - frame_size) & -8ul); }
void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long sp; /* Default to using normal stack */ sp = regs->regs[29]; /* * FPU emulator may have it's own trampoline active just * above the user stack, 16-bytes before the next lowest * 16 byte boundary. Try to avoid trashing it. */ sp -= 32; /* This is the X/Open sanctioned signal stack switching. */ if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0)) sp = current->sas_ss_sp + current->sas_ss_size; return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); }
static inline void __user* get_sigframe(struct k_sigaction* ka,struct pt_regs* regs,int framesize) { unsigned long sp=regs->sp; void __user* frame; /* *This is The X/Open sanctioned signal stack switching. */ if((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) { sp=current->sas_ss_sp + current->sas_ss_size; } frame=(void __user*)((sp-framesize)&~4); if(!access_ok(VERIFY_WRITE,frame,framesize)) { frame=NULL; } return frame; }
static inline void __user *compat_get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) { unsigned long sp; sp = (unsigned long)compat_ptr(regs->sp); if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size))) return (void __user __force *)-1UL; if (ka->sa.sa_flags & SA_ONSTACK) { if (sas_ss_flags(sp) == 0) sp = current->sas_ss_sp + current->sas_ss_size; } sp -= frame_size; sp &= -16UL; return (void __user *) sp; }
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs * regs) { rt_sigframe *frame; addr_t orig_sp=regs->gprs[15]; int err; if((frame=setup_frame_common(sig,ka,set,regs,sizeof(rt_sigframe), (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0) goto give_sigsegv; err = __copy_to_user(&frame->info, info, sizeof(*info)); /* 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(orig_sp), &frame->uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); err |= __put_user(&frame->sc,&frame->uc.sc); regs->gprs[3] = (addr_t)&frame->info; regs->gprs[4] = (addr_t)&frame->uc; if (err) goto give_sigsegv; #if DEBUG_SIG printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", current->comm, current->pid, frame, regs->eip, frame->pretcode); #endif return; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; force_sig(SIGSEGV, current); }
/* * Determine which stack to use.. */ static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) { unsigned long sp; /* Default to using normal stack */ sp = regs->gprs[15]; /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { if (! sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; } /* This is the legacy signal stack switching. */ else if (!user_mode(regs) && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) { sp = (unsigned long) ka->sa.sa_restorer; } return (void __user *)((sp - frame_size) & -8ul); }
static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct pt_regs *regs) { struct rt_sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); stack_t stack; int err = 0; if (!frame) return 1; err |= copy_siginfo_to_user(&frame->info, info); err |= __put_user(0, &frame->sig.uc.uc_flags); err |= __put_user(NULL, &frame->sig.uc.uc_link); memset(&stack, 0, sizeof(stack)); stack.ss_sp = (void __user *)current->sas_ss_sp; stack.ss_flags = sas_ss_flags(regs->UCreg_sp); stack.ss_size = current->sas_ss_size; err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack)); err |= setup_sigframe(&frame->sig, regs, set); if (err == 0) err |= setup_return(regs, ka, frame->sig.retcode, frame, usig); if (err == 0) { /* * For realtime signals we must also set the second and third * arguments for the signal handler. */ regs->UCreg_01 = (unsigned long)&frame->info; regs->UCreg_02 = (unsigned long)&frame->sig.uc; } return err; }
/* * Determine which stack to use.. */ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) { unsigned long sp = regs->sp; void __user *frame; /* This is the X/Open sanctioned signal stack switching */ if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp)) sp = current->sas_ss_sp + current->sas_ss_size; /* No matter what happens, 'sp' must be word * aligned otherwise nasty things could happen */ /* ATPCS B01 mandates 8-byte alignment */ frame = (void __user *)((sp - framesize) & ~7); /* Check that we can actually write to the signal frame */ if (!access_ok(VERIFY_WRITE, frame, framesize)) frame = NULL; return frame; }
int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) { struct rt_sigframe32 __user *frame; int err = 0; s32 sp; frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) goto give_sigsegv; /* Set up to return from userspace. If provided, use a stub already in userspace. */ /* * Set up the return code ... * * li v0, __NR_O32_rt_sigreturn * syscall */ err |= __put_user(0x24020000 + __NR_O32_rt_sigreturn, frame->rs_code + 0); err |= __put_user(0x0000000c , frame->rs_code + 1); flush_cache_sigtramp((unsigned long) frame->rs_code); /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ err |= copy_siginfo_to_user32(&frame->rs_info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_link); sp = (int) (long) current->sas_ss_sp; err |= __put_user(sp, &frame->rs_uc.uc_stack.ss_sp); err |= __put_user(sas_ss_flags(regs->regs[29]), &frame->rs_uc.uc_stack.ss_flags); err |= __put_user(current->sas_ss_size, &frame->rs_uc.uc_stack.ss_size); err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext); err |= __copy_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_sigframe32. */ regs->regs[ 4] = signr; regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[29] = (unsigned long) frame; regs->regs[31] = (unsigned long) frame->rs_code; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; #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, frame->rs_code); #endif return 0; give_sigsegv: force_sigsegv(signr, current); return -EFAULT; }