diff options
Diffstat (limited to 'arch/sparc/kernel/signal.c')
-rw-r--r-- | arch/sparc/kernel/signal.c | 298 |
1 files changed, 169 insertions, 129 deletions
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 357d30af5..287ed6cdc 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.82 1998/07/31 05:18:51 jj Exp $ +/* $Id: signal.c,v 1.90 1998/10/18 03:31:05 davem Exp $ * linux/arch/sparc/kernel/signal.c * * Copyright (C) 1991, 1992 Linus Torvalds @@ -75,6 +75,7 @@ struct new_signal_frame { __siginfo_fpu_t *fpu_save; unsigned long insns [2] __attribute__ ((aligned (8))); unsigned int extramask[_NSIG_WORDS - 1]; + unsigned int extra_size; /* Should be 0 */ __siginfo_fpu_t fpu_state; }; @@ -86,6 +87,7 @@ struct rt_signal_frame { __siginfo_fpu_t *fpu_save; unsigned int insns [2]; stack_t stack; + unsigned int extra_size; /* Should be 0 */ __siginfo_fpu_t fpu_state; }; @@ -203,16 +205,19 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) #endif current->used_math = 1; current->flags &= ~PF_USEDFPU; + + if (verify_area (VERIFY_READ, fpu, sizeof(*fpu))) + return -EFAULT; - err = copy_from_user(¤t->tss.float_regs[0], &fpu->si_float_regs[0], - (sizeof(unsigned long) * 32)); + err = __copy_from_user(¤t->tss.float_regs[0], &fpu->si_float_regs[0], + (sizeof(unsigned long) * 32)); err |= __get_user(current->tss.fsr, &fpu->si_fsr); err |= __get_user(current->tss.fpqdepth, &fpu->si_fpqdepth); if (current->tss.fpqdepth != 0) - err |= copy_from_user(¤t->tss.fpqueue[0], - &fpu->si_fpqueue[0], - ((sizeof(unsigned long) + - (sizeof(unsigned long *)))*16)); + err |= __copy_from_user(¤t->tss.fpqueue[0], + &fpu->si_fpqueue[0], + ((sizeof(unsigned long) + + (sizeof(unsigned long *)))*16)); return err; } @@ -241,7 +246,7 @@ static inline void do_new_sigreturn (struct pt_regs *regs) /* 2. Restore the state */ up_psr = regs->psr; - err |= copy_from_user(regs, &sf->info.si_regs, sizeof (struct pt_regs)); + err |= __copy_from_user(regs, &sf->info.si_regs, sizeof (struct pt_regs)); /* User can only change condition codes and FPU enabling in %psr. */ regs->psr = (up_psr & ~(PSR_ICC | PSR_EF)) @@ -250,14 +255,14 @@ static inline void do_new_sigreturn (struct pt_regs *regs) err |= __get_user(fpu_save, &sf->fpu_save); if (fpu_save) - err |= restore_fpu_state(regs, sf->fpu_save); + err |= restore_fpu_state(regs, fpu_save); /* This is pretty much atomic, no amount locking would prevent * the races which exist anyways. */ err |= __get_user(set.sig[0], &sf->info.si_mask); - err |= copy_from_user(&set.sig[1], &sf->extramask, - (_NSIG_WORDS-1) * sizeof(unsigned int)); + err |= __copy_from_user(&set.sig[1], &sf->extramask, + (_NSIG_WORDS-1) * sizeof(unsigned int)); if (err) goto segv_and_exit; @@ -270,8 +275,6 @@ static inline void do_new_sigreturn (struct pt_regs *regs) return; segv_and_exit: - /* Ugh, we need to grab master lock in these rare cases ;-( */ - lock_kernel(); do_exit(SIGSEGV); } @@ -305,8 +308,8 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) */ err |= __get_user(set.sig[0], &scptr->sigc_mask); /* Note that scptr + 1 points to extramask */ - err |= copy_from_user(&set.sig[1], scptr + 1, - (_NSIG_WORDS - 1) * sizeof(unsigned int)); + err |= __copy_from_user(&set.sig[1], scptr + 1, + (_NSIG_WORDS - 1) * sizeof(unsigned int)); if (err) goto segv_and_exit; @@ -352,7 +355,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) (((unsigned long) sf) & 0x03)) goto segv; - err = get_user(pc, &sf->regs.pc); + err = __get_user(pc, &sf->regs.pc); err |= __get_user(npc, &sf->regs.npc); err |= ((pc | npc) & 0x03); @@ -366,8 +369,8 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) err |= __get_user(fpu_save, &sf->fpu_save); if(fpu_save) - err |= restore_fpu_state(regs, &sf->fpu_state); - err |= copy_from_user(&set, &sf->mask, sizeof(sigset_t)); + err |= restore_fpu_state(regs, fpu_save); + err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t)); @@ -423,7 +426,7 @@ setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, { struct signal_sframe *sframep; struct sigcontext *sc; - int window = 0; + int window = 0, err; synchronize_user_stack(); sframep = (struct signal_sframe *)get_sigframe(sa, regs, SF_ALIGNEDSZ); @@ -443,58 +446,63 @@ setup_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, sc = &sframep->sig_context; /* We've already made sure frame pointer isn't in kernel space... */ - __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), &sc->sigc_onstack); - __put_user(oldset->sig[0], &sc->sigc_mask); - __copy_to_user(sframep->extramask, &oldset->sig[1], - (_NSIG_WORDS - 1) * sizeof(unsigned int)); - __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); - __put_user(pc, &sc->sigc_pc); - __put_user(npc, &sc->sigc_npc); - __put_user(regs->psr, &sc->sigc_psr); - __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); - __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); - __put_user(current->tss.w_saved, &sc->sigc_oswins); + err = __put_user((sas_ss_flags(regs->u_regs[UREG_FP]) == SS_ONSTACK), + &sc->sigc_onstack); + err |= __put_user(oldset->sig[0], &sc->sigc_mask); + err |= __copy_to_user(sframep->extramask, &oldset->sig[1], + (_NSIG_WORDS - 1) * sizeof(unsigned int)); + err |= __put_user(regs->u_regs[UREG_FP], &sc->sigc_sp); + err |= __put_user(pc, &sc->sigc_pc); + err |= __put_user(npc, &sc->sigc_npc); + err |= __put_user(regs->psr, &sc->sigc_psr); + err |= __put_user(regs->u_regs[UREG_G1], &sc->sigc_g1); + err |= __put_user(regs->u_regs[UREG_I0], &sc->sigc_o0); + err |= __put_user(current->tss.w_saved, &sc->sigc_oswins); if(current->tss.w_saved) for(window = 0; window < current->tss.w_saved; window++) { sc->sigc_spbuf[window] = (char *)current->tss.rwbuf_stkptrs[window]; - copy_to_user(&sc->sigc_wbuf[window], - ¤t->tss.reg_window[window], - sizeof(struct reg_window)); + err |= __copy_to_user(&sc->sigc_wbuf[window], + ¤t->tss.reg_window[window], + sizeof(struct reg_window)); } else - copy_to_user(sframep, (char *)regs->u_regs[UREG_FP], - sizeof(struct reg_window)); + err |= __copy_to_user(sframep, (char *)regs->u_regs[UREG_FP], + sizeof(struct reg_window)); current->tss.w_saved = 0; /* So process is allowed to execute. */ - __put_user(signr, &sframep->sig_num); + err |= __put_user(signr, &sframep->sig_num); if(signr == SIGSEGV || signr == SIGILL || signr == SIGFPE || signr == SIGBUS || signr == SIGEMT) { - __put_user(current->tss.sig_desc, &sframep->sig_code); - __put_user(current->tss.sig_address, &sframep->sig_address); + err |= __put_user(current->tss.sig_desc, &sframep->sig_code); + err |= __put_user(current->tss.sig_address, &sframep->sig_address); } else { - __put_user(0, &sframep->sig_code); - __put_user(0, &sframep->sig_address); + err |= __put_user(0, &sframep->sig_code); + err |= __put_user(0, &sframep->sig_address); } - __put_user(sc, &sframep->sig_scptr); + err |= __put_user(sc, &sframep->sig_scptr); + if (err) + goto sigsegv; + regs->u_regs[UREG_FP] = (unsigned long) sframep; regs->pc = (unsigned long) sa->sa_handler; regs->npc = (regs->pc + 4); return; sigill_and_return: - /* Ugh, we need to grab master lock in these rare cases ;-( */ - lock_kernel(); do_exit(SIGILL); +sigsegv: + do_exit(SIGSEGV); } -static inline void +static inline int save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) { + int err = 0; #ifdef __SMP__ if (current->flags & PF_USEDFPU) { put_psr(get_psr() | PSR_EF); @@ -512,15 +520,16 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu) regs->psr &= ~(PSR_EF); } #endif - copy_to_user(&fpu->si_float_regs[0], ¤t->tss.float_regs[0], - (sizeof(unsigned long) * 32)); - __put_user(current->tss.fsr, &fpu->si_fsr); - __put_user(current->tss.fpqdepth, &fpu->si_fpqdepth); + err |= __copy_to_user(&fpu->si_float_regs[0], ¤t->tss.float_regs[0], + (sizeof(unsigned long) * 32)); + err |= __put_user(current->tss.fsr, &fpu->si_fsr); + err |= __put_user(current->tss.fpqdepth, &fpu->si_fpqdepth); if (current->tss.fpqdepth != 0) - copy_to_user(&fpu->si_fpqueue[0], ¤t->tss.fpqueue[0], - ((sizeof(unsigned long) + - (sizeof(unsigned long *)))*16)); + err |= __copy_to_user(&fpu->si_fpqueue[0], ¤t->tss.fpqueue[0], + ((sizeof(unsigned long) + + (sizeof(unsigned long *)))*16)); current->used_math = 0; + return err; } static inline void @@ -528,7 +537,7 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, int signo, sigset_t *oldset) { struct new_signal_frame *sf; - int sigframe_size; + int sigframe_size, err; /* 1. Make sure everything is clean */ synchronize_user_stack(); @@ -551,20 +560,24 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, } /* 2. Save the current process state */ - copy_to_user(&sf->info.si_regs, regs, sizeof (struct pt_regs)); + err = __copy_to_user(&sf->info.si_regs, regs, sizeof (struct pt_regs)); + + err |= __put_user(0, &sf->extra_size); if (current->used_math) { - save_fpu_state(regs, &sf->fpu_state); - __put_user(&sf->fpu_state, &sf->fpu_save); + err |= save_fpu_state(regs, &sf->fpu_state); + err |= __put_user(&sf->fpu_state, &sf->fpu_save); } else { - __put_user(0, &sf->fpu_save); + err |= __put_user(0, &sf->fpu_save); } - __put_user(oldset->sig[0], &sf->info.si_mask); - __copy_to_user(sf->extramask, &oldset->sig[1], - (_NSIG_WORDS - 1) * sizeof(unsigned int)); - copy_to_user(sf, (char *) regs->u_regs [UREG_FP], - sizeof (struct reg_window)); + 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)); + err |= __copy_to_user(sf, (char *) regs->u_regs [UREG_FP], + sizeof (struct reg_window)); + if (err) + goto sigsegv; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = (unsigned long) sf; @@ -581,8 +594,13 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, else { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); - __put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */ - __put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */ + /* 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])); @@ -590,8 +608,9 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs, return; sigill_and_return: - lock_kernel(); do_exit(SIGILL); +sigsegv: + do_exit(SIGSEGV); } static inline void @@ -601,7 +620,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, struct rt_signal_frame *sf; int sigframe_size; unsigned int psr; - int i; + int err; synchronize_user_stack(); sigframe_size = RT_ALIGNEDSZ; @@ -613,30 +632,33 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, if(current->tss.w_saved != 0) goto sigill; - put_user(regs->pc, &sf->regs.pc); - __put_user(regs->npc, &sf->regs.npc); - __put_user(regs->y, &sf->regs.y); + 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(current->used_math) psr |= PSR_EF; - __put_user(psr, &sf->regs.psr); - for(i = 0; i < 16; i++) - __put_user(regs->u_regs[i], &sf->regs.u_regs[i]); + 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) { - save_fpu_state(regs, &sf->fpu_state); - __put_user(&sf->fpu_state, &sf->fpu_save); + err |= save_fpu_state(regs, &sf->fpu_state); + err |= __put_user(&sf->fpu_state, &sf->fpu_save); } else { - __put_user(0, &sf->fpu_save); + err |= __put_user(0, &sf->fpu_save); } - __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); + err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - __put_user(current->sas_ss_size, &sf->stack.ss_size); + 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); - copy_to_user(sf, (char *) regs->u_regs [UREG_FP], - sizeof (struct reg_window)); + err |= __copy_to_user(sf, (char *) regs->u_regs [UREG_FP], + sizeof (struct reg_window)); + if (err) + goto sigsegv; regs->u_regs[UREG_FP] = (unsigned long) sf; regs->u_regs[UREG_I0] = signo; @@ -650,8 +672,13 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, else { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); - __put_user(0x821020d8, &sf->insns[0]); /* mov __NR_sigreturn, %g1 */ - __put_user(0x91d02010, &sf->insns[1]); /* t 0x10 */ + /* 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])); @@ -659,8 +686,9 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, return; sigill: - lock_kernel(); do_exit(SIGILL); +sigsegv: + do_exit(SIGSEGV); } /* Setup a Solaris stack frame */ @@ -675,7 +703,7 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, svr4_gwindows_t *gw; svr4_ucontext_t *uc; svr4_sigset_t setv; - int window = 0; + int window = 0, err; synchronize_user_stack(); sfp = (svr4_signal_frame_t *) get_sigframe(sa, regs, SVR4_SF_ALIGNED + REGWIN_SZ); @@ -688,7 +716,7 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, } /* Start with a clean frame pointer and fill it */ - clear_user(sfp, sizeof (*sfp)); + err = __clear_user(sfp, sizeof (*sfp)); /* Setup convenience variables */ si = &sfp->si; @@ -706,32 +734,32 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, if (_NSIG_WORDS >= 4) { setv.sigbits[2] = oldset->sig[2]; setv.sigbits[3] = oldset->sig[3]; - __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); + err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); } else - __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); + err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); /* Store registers */ - __put_user(regs->pc, &((*gr) [SVR4_PC])); - __put_user(regs->npc, &((*gr) [SVR4_NPC])); - __put_user(regs->psr, &((*gr) [SVR4_PSR])); - __put_user(regs->y, &((*gr) [SVR4_Y])); + err |= __put_user(regs->pc, &((*gr) [SVR4_PC])); + err |= __put_user(regs->npc, &((*gr) [SVR4_NPC])); + err |= __put_user(regs->psr, &((*gr) [SVR4_PSR])); + err |= __put_user(regs->y, &((*gr) [SVR4_Y])); /* Copy g [1..7] and o [0..7] registers */ - copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs [UREG_G1], sizeof (long) * 7); - copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs [UREG_I0], sizeof (long) * 8); + err |= __copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs [UREG_G1], sizeof (long) * 7); + err |= __copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs [UREG_I0], sizeof (long) * 8); /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &uc->stack.sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - __put_user(current->sas_ss_size, &uc->stack.size); + err |= __put_user(current->sas_ss_sp, &uc->stack.sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); + err |= __put_user(current->sas_ss_size, &uc->stack.size); /* Save the currently window file: */ /* 1. Link sfp->uc->gwins to our windows */ - __put_user(gw, &mc->gwin); + err |= __put_user(gw, &mc->gwin); /* 2. Number of windows to restore at setcontext (): */ - __put_user(current->tss.w_saved, &gw->count); + err |= __put_user(current->tss.w_saved, &gw->count); /* 3. Save each valid window * Currently, it makes a copy of the windows from the kernel copy. @@ -745,9 +773,11 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, * to flush the user windows. */ for(window = 0; window < current->tss.w_saved; window++) { - __put_user((int *) &(gw->win [window]), &gw->winptr [window]); - copy_to_user(&gw->win [window], ¤t->tss.reg_window [window], sizeof (svr4_rwindow_t)); - __put_user(0, gw->winptr [window]); + err |= __put_user((int *) &(gw->win [window]), &gw->winptr [window]); + err |= __copy_to_user(&gw->win [window], + ¤t->tss.reg_window [window], + sizeof (svr4_rwindow_t)); + err |= __put_user(0, gw->winptr [window]); } /* 4. We just pay attention to the gw->count field on setcontext */ @@ -758,8 +788,10 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, * that much currently, should use those that David already * is providing with tss.sig_desc */ - __put_user(signr, &si->siginfo.signo); - __put_user(SVR4_SINOINFO, &si->siginfo.code); + err |= __put_user(signr, &si->siginfo.signo); + err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); + if (err) + goto sigsegv; regs->u_regs[UREG_FP] = (unsigned long) sfp; regs->pc = (unsigned long) sa->sa_handler; @@ -772,10 +804,13 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, if (regs->u_regs [14]){ struct reg_window *rw = (struct reg_window *) regs->u_regs [14]; - __put_user(signr, &rw->ins [0]); - __put_user(si, &rw->ins [1]); - __put_user(uc, &rw->ins [2]); - __put_user(sfp, &rw->ins [6]); /* frame pointer */ + err |= __put_user(signr, &rw->ins [0]); + err |= __put_user(si, &rw->ins [1]); + err |= __put_user(uc, &rw->ins [2]); + err |= __put_user(sfp, &rw->ins [6]); /* frame pointer */ + if (err) + goto sigsegv; + regs->u_regs[UREG_I0] = signr; regs->u_regs[UREG_I1] = (uint) si; regs->u_regs[UREG_I2] = (uint) uc; @@ -783,8 +818,9 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, return; sigill_and_return: - lock_kernel(); do_exit(SIGILL); +sigsegv: + do_exit(SIGSEGV); } asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs) @@ -792,13 +828,15 @@ asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs) svr4_gregset_t *gr; svr4_mcontext_t *mc; svr4_sigset_t setv; + int err = 0; synchronize_user_stack(); if (current->tss.w_saved) goto sigsegv_and_return; - if(clear_user(uc, sizeof (*uc))) + err = clear_user(uc, sizeof (*uc)); + if (err) return -EFAULT; /* Setup convenience variables */ @@ -810,32 +848,31 @@ asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs) if (_NSIG_WORDS >= 4) { setv.sigbits[2] = current->blocked.sig[2]; setv.sigbits[3] = current->blocked.sig[3]; - __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); + err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); } else - __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); + err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned int)); /* Store registers */ - __put_user(regs->pc, &uc->mcontext.greg [SVR4_PC]); - __put_user(regs->npc, &uc->mcontext.greg [SVR4_NPC]); - __put_user(regs->psr, &uc->mcontext.greg [SVR4_PSR]); - __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]); + err |= __put_user(regs->pc, &uc->mcontext.greg [SVR4_PC]); + err |= __put_user(regs->npc, &uc->mcontext.greg [SVR4_NPC]); + err |= __put_user(regs->psr, &uc->mcontext.greg [SVR4_PSR]); + err |= __put_user(regs->y, &uc->mcontext.greg [SVR4_Y]); /* Copy g [1..7] and o [0..7] registers */ - copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs [UREG_G1], sizeof (uint) * 7); - copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs [UREG_I0], sizeof (uint) * 8); + err |= __copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs [UREG_G1], sizeof (uint) * 7); + err |= __copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs [UREG_I0], sizeof (uint) * 8); /* Setup sigaltstack */ - __put_user(current->sas_ss_sp, &uc->stack.sp); - __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - __put_user(current->sas_ss_size, &uc->stack.size); + err |= __put_user(current->sas_ss_sp, &uc->stack.sp); + err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); + err |= __put_user(current->sas_ss_size, &uc->stack.size); /* The register file is not saved * we have already stuffed all of it with sync_user_stack */ - return 0; + return (err ? -EFAULT : 0); sigsegv_and_return: - lock_kernel(); do_exit(SIGSEGV); } @@ -905,18 +942,19 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs) spin_unlock_irq(¤t->sigmask_lock); regs->pc = pc; regs->npc = npc | 1; - __get_user(regs->y, &((*gr) [SVR4_Y])); - __get_user(psr, &((*gr) [SVR4_PSR])); + err |= __get_user(regs->y, &((*gr) [SVR4_Y])); + err |= __get_user(psr, &((*gr) [SVR4_PSR])); regs->psr &= ~(PSR_ICC); regs->psr |= (psr & PSR_ICC); /* Restore g[1..7] and o[0..7] registers */ - copy_from_user(®s->u_regs [UREG_G1], &(*gr)[SVR4_G1], sizeof (long) * 7); - copy_from_user(®s->u_regs [UREG_I0], &(*gr)[SVR4_O0], sizeof (long) * 8); - return 0; + err |= __copy_from_user(®s->u_regs [UREG_G1], &(*gr)[SVR4_G1], + sizeof (long) * 7); + err |= __copy_from_user(®s->u_regs [UREG_I0], &(*gr)[SVR4_O0], + sizeof (long) * 8); + return (err ? -EFAULT : 0); sigsegv_and_return: - lock_kernel(); do_exit(SIGSEGV); } @@ -1069,7 +1107,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, case SIGABRT: case SIGFPE: case SIGSEGV: case SIGBUS: if(current->binfmt && current->binfmt->core_dump) { lock_kernel(); - if(current->binfmt->core_dump(signr, regs)) + if(current->binfmt && + current->binfmt->core_dump && + current->binfmt->core_dump(signr, regs)) exit_code |= 0x80; unlock_kernel(); } |