diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-04-29 21:13:14 +0000 |
commit | 19c9bba94152148523ba0f7ef7cffe3d45656b11 (patch) | |
tree | 40b1cb534496a7f1ca0f5c314a523c69f1fee464 /arch/mips/kernel/irixsig.c | |
parent | 7206675c40394c78a90e74812bbdbf8cf3cca1be (diff) |
Import of Linux/MIPS 2.1.36
Diffstat (limited to 'arch/mips/kernel/irixsig.c')
-rw-r--r-- | arch/mips/kernel/irixsig.c | 228 |
1 files changed, 143 insertions, 85 deletions
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 94f8004f6..6a5636c76 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -112,7 +112,8 @@ static void setup_irix_frame(struct sigaction * sa, struct pt_regs *regs, regs->regs[25] = regs->cp0_epc = current->tss.irix_trampoline; } -extern asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options); +asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr, + int options, unsigned long *ru); asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs) { @@ -150,7 +151,7 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs) if (signr != SIGCHLD) continue; /* check for SIGCHLD: it's special */ - while (sys_waitpid(-1,NULL,WNOHANG) > 0) + while (sys_wait4(-1,NULL,WNOHANG, NULL) > 0) /* nothing */; continue; } @@ -198,7 +199,7 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs) } } handler_signal |= 1 << (signr-1); - mask &= ~*to_k_sigset_t(&sa->sa_mask); + mask &= ~sa->sa_mask; } /* * Who's code doesn't conform to the restartable syscall convention @@ -224,8 +225,8 @@ asmlinkage int do_irix_signal(unsigned long oldmask, struct pt_regs * regs) setup_irix_frame(sa, regs, signr, oldmask); if (sa->sa_flags & SA_ONESHOT) sa->sa_handler = NULL; - current->blocked |= *to_k_sigset_t(&sa->sa_mask); - oldmask |= *to_k_sigset_t(&sa->sa_mask); + current->blocked |= sa->sa_mask; + oldmask |= sa->sa_mask; } return 1; @@ -282,7 +283,11 @@ asmlinkage unsigned long irix_sigreturn(struct pt_regs *regs) return res; badframe: + lock_kernel(); do_exit(SIGSEGV); + unlock_kernel(); + + return res; } struct sigact_irix5 { @@ -306,22 +311,22 @@ static inline void check_pending(int signum) struct sigaction *p; p = signum - 1 + current->sig->action; + spin_lock(¤t->sigmask_lock); if (p->sa_handler == SIG_IGN) { current->signal &= ~_S(signum); - return; - } - if (p->sa_handler == SIG_DFL) { + } else if if (p->sa_handler == SIG_DFL) { if (signum != SIGCONT && signum != SIGCHLD && signum != SIGWINCH) return; current->signal &= ~_S(signum); - return; } + spin_unlock(¤t->sigmask_lock); } asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, struct sigact_irix5 *old, unsigned long trampoline) { struct sigaction new_sa, *p; + int res; #ifdef DEBUG_SIG printk(" (%d,%s,%s,%08lx) ", sig, (!new ? "0" : "NEW"), @@ -330,16 +335,18 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, dump_sigact_irix5(new); printk(" "); } #endif - if(sig < 1 || sig > 32) + if(sig < 1 || sig > 32) { return -EINVAL; + } p = sig - 1 + current->sig->action; if(new) { - int err = verify_area(VERIFY_READ, new, sizeof(*new)); - if(err) - return err; - if(sig == SIGKILL || sig == SIGSTOP) + res = verify_area(VERIFY_READ, new, sizeof(*new)); + if(res) + return res; + if(sig == SIGKILL || sig == SIGSTOP) { return -EINVAL; + } new_sa.sa_flags = new->flags; new_sa.sa_handler = (__sighandler_t) new->handler; new_sa.sa_mask.__sigbits[1] = new_sa.sa_mask.__sigbits[2] = @@ -347,9 +354,9 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, new_sa.sa_mask.__sigbits[0] = new->sigset[0]; if(new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) { - err = verify_area(VERIFY_READ, new_sa.sa_handler, 1); - if(err) - return err; + res = verify_area(VERIFY_READ, new_sa.sa_handler, 1); + if(res) + return res; } } /* Hmmm... methinks IRIX libc always passes a valid trampoline @@ -358,9 +365,9 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, */ current->tss.irix_trampoline = trampoline; if(old) { - int err = verify_area(VERIFY_WRITE, old, sizeof(*old)); - if(err) - return err; + int res = verify_area(VERIFY_WRITE, old, sizeof(*old)); + if(res) + return res; old->flags = p->sa_flags; old->handler = (void *) p->sa_handler; old->sigset[1] = old->sigset[2] = old->sigset[3] = 0; @@ -369,23 +376,30 @@ asmlinkage int irix_sigaction(int sig, struct sigact_irix5 *new, } if(new) { + spin_lock_irq(¤t->sig->siglock); *p = new_sa; check_pending(sig); + spin_unlock_irq(¤t->sig->siglock); } - return 0; } asmlinkage int irix_sigpending(unsigned long *set) { - int err; - - err = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4)); - if(!err) { - set[1] = set[2] = set[3] = 0; - set[0] = (current->blocked & current->signal); + int res; + + lock_kernel(); + res = verify_area(VERIFY_WRITE, set, (sizeof(unsigned long) * 4)); + if(!res) { + /* fill in "set" with signals pending but blocked. */ + spin_lock_irq(¤t->sigmask_lock); + __put_user(0, &set[1]); + __put_user(0, &set[2]); + __put_user(0, &set[3]); + __put_user((current->blocked & current->signal), &set[0]); + spin_unlock_irq(¤t->sigmask_lock); } - return err; + return res; } asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old) @@ -420,9 +434,12 @@ asmlinkage int irix_sigprocmask(int how, unsigned long *new, unsigned long *old) error = verify_area(VERIFY_WRITE, old, (sizeof(unsigned long) * 4)); if(error) return error; - old[1] = old[2] = old[3] = 0; - old[0] = oldbits; + __put_user(0, &old[1]); + __put_user(0, &old[2]); + __put_user(0, &old[3]); + __put_user(oldbits, &old[0]); } + return 0; } @@ -430,15 +447,16 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs) { unsigned int mask; unsigned long *uset; - int base = 0; + int base = 0, error; if(regs->regs[2] == 1000) base = 1; - mask = current->blocked; uset = (unsigned long *) regs->regs[base + 4]; if(verify_area(VERIFY_READ, uset, (sizeof(unsigned long) * 4))) return -EFAULT; + mask = current->blocked; + current->blocked = uset[0] & _BLOCKABLE; while(1) { current->state = TASK_INTERRUPTIBLE; @@ -446,6 +464,7 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs) if(do_irix_signal(mask, regs)) return -EINTR; } + return error; } /* hate hate hate... */ @@ -492,6 +511,7 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, unsigned long mask, kset, expire = 0; int sig, error, timeo = 0; + lock_kernel(); #ifdef DEBUG_SIG printk("[%s:%d] irix_sigpoll_sys(%p,%p,%p)\n", current->comm, current->pid, set, info, tp); @@ -500,25 +520,24 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, /* Must always specify the signal set. */ if(!set) return -EINVAL; - kset = set[0]; - error = verify_area(VERIFY_READ, set, (sizeof(unsigned long) * 4)); + error = get_user(kset, &set[0]); if(error) - return error; + goto out; - if(info) { - error = verify_area(VERIFY_WRITE, info, sizeof(*info)); - if(error) - return error; - memset(info, 0, sizeof(*info)); + if(info && clear_user(info, sizeof(*info))) { + error = -EFAULT; + goto out; } if(tp) { error = verify_area(VERIFY_READ, tp, sizeof(*tp)); if(error) return error; - if(!tp->tv_sec && !tp->tv_nsec) - return -EINVAL; + if(!tp->tv_sec && !tp->tv_nsec) { + error = -EINVAL; + goto out; + } expire = timespectojiffies(tp)+(tp->tv_sec||tp->tv_nsec)+jiffies; current->timeout = expire; } @@ -539,12 +558,17 @@ asmlinkage int irix_sigpoll_sys(unsigned long *set, struct irix5_siginfo *info, if(mask & current->signal) { /* XXX need more than this... */ if(info) info->sig = sig; - return 0; + error = 0; + goto out; } } /* Should not get here, but do something sane if we do. */ - return -EINTR; + error = -EINTR; + +out: + unlock_kernel(); + return error; } /* This is here because of irix5_siginfo definition. */ @@ -570,20 +594,27 @@ asmlinkage int irix_waitsys(int type, int pid, struct irix5_siginfo *info, struct wait_queue wait = { current, NULL }; struct task_struct *p; - if(!info) - return -EINVAL; - flag = verify_area(VERIFY_WRITE, info, sizeof(*info)); - if(flag) - return flag; + lock_kernel(); + if(!info) { + retval = -EINVAL; + goto out; + } + retval = verify_area(VERIFY_WRITE, info, sizeof(*info)); + if(retval) + goto out; if(ru) { - flag = verify_area(VERIFY_WRITE, ru, sizeof(*ru)); - if(flag) - return flag; + retval = verify_area(VERIFY_WRITE, ru, sizeof(*ru)); + if(retval) + goto out; + } + if(options & ~(W_MASK)) { + retval = -EINVAL; + goto out; + } + if(type != P_PID && type != P_PGID && type != P_ALL) { + retval = -EINVAL; + goto out; } - if(options & ~(W_MASK)) - return -EINVAL; - if(type != P_PID && type != P_PGID && type != P_ALL) - return -EINVAL; add_wait_queue(¤t->wait_chldexit, &wait); repeat: flag = 0; @@ -604,15 +635,13 @@ repeat: continue; if (ru != NULL) getrusage(p, RUSAGE_BOTH, ru); - info->sig = SIGCHLD; - info->code = 0; - info->stuff.procinfo.pid = p->pid; - info->stuff.procinfo.procdata.child.status = - (p->exit_code >> 8) & 0xff; - info->stuff.procinfo.procdata.child.utime = - p->utime; - info->stuff.procinfo.procdata.child.stime = - p->stime; + __put_user(SIGCHLD, &info->sig); + __put_user(0, &info->code); + __put_user(p->pid, &info->stuff.procinfo.pid); + __put_user((p->exit_code >> 8) & 0xff, + &info->stuff.procinfo.procdata.child.status); + __put_user(p->utime, &info->stuff.procinfo.procdata.child.utime); + __put_user(p->stime, &info->stuff.procinfo.procdata.child.stime); p->exit_code = 0; retval = 0; goto end_waitsys; @@ -621,15 +650,15 @@ repeat: current->cstime += p->stime + p->cstime; if (ru != NULL) getrusage(p, RUSAGE_BOTH, ru); - info->sig = SIGCHLD; - info->code = 1; /* CLD_EXITED */ - info->stuff.procinfo.pid = p->pid; - info->stuff.procinfo.procdata.child.status = - (p->exit_code >> 8) & 0xff; - info->stuff.procinfo.procdata.child.utime = - p->utime; - info->stuff.procinfo.procdata.child.stime = - p->stime; + __put_user(SIGCHLD, &info->sig); + __put_user(1, &info->code); /* CLD_EXITED */ + __put_user(p->pid, &info->stuff.procinfo.pid); + __put_user((p->exit_code >> 8) & 0xff, + &info->stuff.procinfo.procdata.child.status); + __put_user(p->utime, + &info->stuff.procinfo.procdata.child.utime); + __put_user(p->stime, + &info->stuff.procinfo.procdata.child.stime); retval = 0; if (p->p_opptr != p->p_pptr) { REMOVE_LINKS(p); @@ -657,6 +686,9 @@ repeat: retval = -ECHILD; end_waitsys: remove_wait_queue(¤t->wait_chldexit, &wait); + +out: + unlock_kernel(); return retval; } @@ -678,6 +710,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) int error, i, base = 0; struct irix5_context *ctx; + lock_kernel(); if(regs->regs[2] == 1000) base = 1; ctx = (struct irix5_context *) regs->regs[base + 4]; @@ -689,7 +722,7 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) error = verify_area(VERIFY_WRITE, ctx, sizeof(*ctx)); if(error) - return error; + goto out; ctx->flags = 0x0f; ctx->link = current->tss.irix_oldctx; ctx->sigmask[1] = ctx->sigmask[2] = ctx->sigmask[4] = 0; @@ -712,7 +745,11 @@ asmlinkage int irix_getcontext(struct pt_regs *regs) /* XXX wheee... */ printk("Wheee, no code for saving IRIX FPU context yet.\n"); } - return 0; + error = 0; + +out: + unlock_kernel(); + return error; } asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) @@ -720,6 +757,7 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) int error, base = 0; struct irix5_context *ctx; + lock_kernel(); if(regs->regs[2] == 1000) base = 1; ctx = (struct irix5_context *) regs->regs[base + 4]; @@ -731,7 +769,7 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) error = verify_area(VERIFY_READ, ctx, sizeof(*ctx)); if(error) - return error; + goto out; if(ctx->flags & 0x02) { /* XXX sigstack garbage, todo... */ @@ -754,7 +792,11 @@ asmlinkage unsigned long irix_setcontext(struct pt_regs *regs) printk("Wheee, cannot restore FPU context yet...\n"); } current->tss.irix_oldctx = ctx->link; - return regs->regs[2]; + error = regs->regs[2]; + +out: + unlock_kernel(); + return error; } struct irix_sigstack { unsigned long sp; int status; }; @@ -763,6 +805,7 @@ asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *ol { int error; + lock_kernel(); #ifdef DEBUG_SIG printk("[%s:%d] irix_sigstack(%p,%p)\n", current->comm, current->pid, new, old); @@ -770,15 +813,18 @@ asmlinkage int irix_sigstack(struct irix_sigstack *new, struct irix_sigstack *ol if(new) { error = verify_area(VERIFY_READ, new, sizeof(*new)); if(error) - return error; + goto out; } if(old) { error = verify_area(VERIFY_WRITE, old, sizeof(*old)); if(error) - return error; + goto out; } - return 0; + error = 0; +out: + unlock_kernel(); + return error; } struct irix_sigaltstack { unsigned long sp; int size; int status; }; @@ -788,6 +834,7 @@ asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new, { int error; + lock_kernel(); #ifdef DEBUG_SIG printk("[%s:%d] irix_sigaltstack(%p,%p)\n", current->comm, current->pid, new, old); @@ -795,15 +842,19 @@ asmlinkage int irix_sigaltstack(struct irix_sigaltstack *new, if(new) { error = verify_area(VERIFY_READ, new, sizeof(*new)); if(error) - return error; + goto out; } if(old) { error = verify_area(VERIFY_WRITE, old, sizeof(*old)); if(error) - return error; + goto out; } - return 0; + error = 0; + +out: + error = 0; + unlock_kernel(); } struct irix_procset { @@ -814,7 +865,10 @@ asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig) { int error; + lock_kernel(); error = verify_area(VERIFY_READ, pset, sizeof(*pset)); + if(error) + goto out; #ifdef DEBUG_SIG printk("[%s:%d] irix_sigsendset([%d,%d,%d,%d,%d],%d)\n", current->comm, current->pid, @@ -822,5 +876,9 @@ asmlinkage int irix_sigsendset(struct irix_procset *pset, int sig) sig); #endif - return -EINVAL; + error = -EINVAL; + +out: + unlock_kernel(); + return error; } |