int sys_sigreturn(struct pt_regs regs) { void *sc = sp_to_sc(PT_REGS_SP(¤t->thread.regs)); void *mask = sp_to_mask(PT_REGS_SP(¤t->thread.regs)); int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); spin_lock_irq(¤t->sighand->siglock); copy_from_user(¤t->blocked.sig[0], sc_sigmask(sc), sizeof(current->blocked.sig[0])); copy_from_user(¤t->blocked.sig[1], mask, sig_size); sigdelsetmask(¤t->blocked, ~_BLOCKABLE); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); copy_sc_from_user(¤t->thread.regs, sc, &signal_frame_sc.common.arch); return(PT_REGS_SYSCALL_RET(¤t->thread.regs)); }
int setup_signal_stack_sc(unsigned long stack_top, int sig, struct k_sigaction *ka, struct pt_regs *regs, sigset_t *mask) { struct frame_common *frame = &signal_frame_sc_sr.common; void *restorer; void *user_sc; int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long); unsigned long sigs, sr; unsigned long start = stack_top - frame->len - sig_size; restorer = NULL; if(ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer; user_sc = (void *) (start + signal_frame_sc_sr.sc_index); if(restorer == NULL){ frame = &signal_frame_sc.common; user_sc = (void *) (start + signal_frame_sc.sc_index); sr = (unsigned long) frame->data; sr += frame->sr_index; sr = *((unsigned long *) sr); restorer = ((void (*)(void)) sr); } sigs = start + frame->len; if(copy_to_user((void *) start, frame->data, frame->len) || copy_to_user((void *) (start + frame->sig_index), &sig, sizeof(sig)) || copy_sc_to_user(user_sc, NULL, regs, &signal_frame_sc.common.arch) || copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) || copy_to_user((void *) sigs, &mask->sig[1], sig_size) || copy_restorer(restorer, start, frame->sr_index, frame->sr_relative)) return(1); PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; PT_REGS_SP(regs) = start + frame->sp_index; return(0); }