patch-2.4.0-test3 linux/arch/mips64/kernel/signal32.c
Next file: linux/arch/mips64/kernel/smp.c
Previous file: linux/arch/mips64/kernel/signal.c
Back to the patch index
Back to the overall index
- Lines: 377
- Date:
Sun Jul 9 22:18:16 2000
- Orig file:
v2.4.0-test2/linux/arch/mips64/kernel/signal32.c
- Orig date:
Tue May 23 15:31:33 2000
diff -u --recursive --new-file v2.4.0-test2/linux/arch/mips64/kernel/signal32.c linux/arch/mips64/kernel/signal32.c
@@ -1,5 +1,4 @@
-/* $Id: signal32.c,v 1.4 2000/03/15 22:46:55 kanoj Exp $
- *
+/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
@@ -8,6 +7,7 @@
* Copyright (C) 1994 - 1999 Ralf Baechle
* Copyright (C) 1999 Silicon Graphics, Inc.
*/
+#include <linux/config.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
@@ -37,6 +37,8 @@
extern asmlinkage int save_fp_context(struct sigcontext *sc);
extern asmlinkage int restore_fp_context(struct sigcontext *sc);
+extern asmlinkage void syscall_trace(void);
+
/* 32-bit compatibility types */
#define _NSIG32_BPW 32
@@ -60,7 +62,7 @@
/* IRIX compatible stack_t */
typedef struct sigaltstack32 {
void *ss_sp;
- size_t ss_size;
+ __kernel_size_t32 ss_size;
int ss_flags;
} stack32_t;
@@ -94,18 +96,72 @@
return err;
}
+extern void __put_sigset_unknown_nsig(void);
+extern void __get_sigset_unknown_nsig(void);
+
+static inline int
+put_sigset(const sigset_t *kbuf, sigset32_t *ubuf)
+{
+ int err = 0;
+
+ if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)))
+ return -EFAULT;
+
+ switch (_NSIG_WORDS) {
+ default:
+ __put_sigset_unknown_nsig();
+ case 2:
+ err |= __put_user (kbuf->sig[1] >> 32, &ubuf->sig[3]);
+ err |= __put_user (kbuf->sig[1] & 0xffffffff, &ubuf->sig[2]);
+ case 1:
+ err |= __put_user (kbuf->sig[0] >> 32, &ubuf->sig[1]);
+ err |= __put_user (kbuf->sig[0] & 0xffffffff, &ubuf->sig[0]);
+ }
+
+ return err;
+}
+
+static inline int
+get_sigset(sigset_t *kbuf, const sigset32_t *ubuf)
+{
+ int err = 0;
+ unsigned long sig[4];
+
+ if (!access_ok(VERIFY_READ, ubuf, sizeof(*ubuf)))
+ return -EFAULT;
+
+ switch (_NSIG_WORDS) {
+ default:
+ __get_sigset_unknown_nsig();
+ case 2:
+ err |= __get_user (sig[3], &ubuf->sig[3]);
+ err |= __get_user (sig[2], &ubuf->sig[2]);
+ kbuf->sig[1] = sig[2] | (sig[3] << 32);
+ case 1:
+ err |= __get_user (sig[1], &ubuf->sig[1]);
+ err |= __get_user (sig[0], &ubuf->sig[0]);
+ kbuf->sig[0] = sig[0] | (sig[1] << 32);
+ }
+
+ return err;
+}
+
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage inline int
sys32_sigsuspend(abi64_no_regargs, struct pt_regs regs)
{
- sigset_t *uset, saveset, newset;
+ sigset32_t *uset;
+ sigset_t newset, saveset;
- save_static(®s);
+#if DEBUG_MIPS64
printk("%s called.\n", __FUNCTION__);
- uset = (sigset_t *) regs.regs[4];
- if (copy_from_user(&newset, uset, sizeof(sigset_t)))
+#endif
+
+ save_static(®s);
+ uset = (sigset32_t *) regs.regs[4];
+ if (get_sigset(&newset, uset))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
@@ -128,19 +184,22 @@
asmlinkage int
sys32_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs)
{
- sigset_t *unewset, saveset, newset;
+ sigset32_t *uset;
+ sigset_t newset, saveset;
size_t sigsetsize;
- save_static(®s);
+#if DEBUG_MIPS64
printk("%s called.\n", __FUNCTION__);
+#endif
+ save_static(®s);
/* XXX Don't preclude handling different sized sigset_t's. */
sigsetsize = regs.regs[5];
- if (sigsetsize != sizeof(sigset_t))
+ if (sigsetsize != sizeof(sigset32_t))
return -EINVAL;
- unewset = (sigset_t *) regs.regs[4];
- if (copy_from_user(&newset, unewset, sizeof(newset)))
+ uset = (sigset32_t *) regs.regs[4];
+ if (get_sigset(&newset, uset))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
@@ -172,10 +231,12 @@
if (!access_ok(VERIFY_READ, act, sizeof(*act)))
return -EFAULT;
- err |= __get_user(new_ka.sa.sa_handler, &act->sa_handler);
+ err |= __get_user((u32)(u64)new_ka.sa.sa_handler,
+ &act->sa_handler);
err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
err |= __get_user(mask, &act->sa_mask.sig[0]);
- err |= __get_user(new_ka.sa.sa_restorer, &act->sa_restorer);
+ err |= __get_user((u32)(u64)new_ka.sa.sa_restorer,
+ &act->sa_restorer);
if (err)
return -EFAULT;
@@ -188,12 +249,14 @@
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
return -EFAULT;
err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
- err |= __put_user(old_ka.sa.sa_handler, &oact->sa_handler);
+ err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
+ &oact->sa_handler);
err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
err |= __put_user(0, &oact->sa_mask.sig[1]);
err |= __put_user(0, &oact->sa_mask.sig[2]);
err |= __put_user(0, &oact->sa_mask.sig[3]);
- err |= __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer);
+ err |= __put_user((u32)(u64)old_ka.sa.sa_restorer,
+ &oact->sa_restorer);
if (err)
return -EFAULT;
}
@@ -204,12 +267,37 @@
asmlinkage int
sys32_sigaltstack(abi64_no_regargs, struct pt_regs regs)
{
- const stack_t *uss = (const stack_t *) regs.regs[4];
- stack_t *uoss = (stack_t *) regs.regs[5];
+ const stack32_t *uss = (const stack32_t *) regs.regs[4];
+ stack32_t *uoss = (stack32_t *) regs.regs[5];
unsigned long usp = regs.regs[29];
-printk("%s called.\n", __FUNCTION__);
+ stack_t kss, koss;
+ int ret, err = 0;
+ mm_segment_t old_fs = get_fs();
- return do_sigaltstack(uss, uoss, usp);
+ if (uss) {
+ if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
+ return -EFAULT;
+ err |= __get_user(kss.ss_sp, &uss->ss_sp);
+ err |= __get_user(kss.ss_size, &uss->ss_size);
+ err |= __get_user(kss.ss_flags, &uss->ss_flags);
+ if (err)
+ return -EFAULT;
+ }
+
+ set_fs (KERNEL_DS);
+ ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, usp);
+ set_fs (old_fs);
+
+ if (!ret && uoss) {
+ if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
+ return -EFAULT;
+ err |= __put_user(koss.ss_sp, &uoss->ss_sp);
+ err |= __put_user(koss.ss_size, &uoss->ss_size);
+ err |= __put_user(koss.ss_flags, &uoss->ss_flags);
+ if (err)
+ return -EFAULT;
+ }
+ return ret;
}
static asmlinkage int
@@ -293,6 +381,8 @@
/*
* Don't let your children do this ...
*/
+ if (current->ptrace & PT_TRACESYS)
+ syscall_trace();
__asm__ __volatile__(
"move\t$29, %0\n\t"
"j\tret_from_sys_call"
@@ -610,7 +700,7 @@
if (!signr)
break;
- if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+ if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
/* Let the debugger run. */
current->exit_code = signr;
current->state = TASK_STOPPED;
@@ -684,7 +774,6 @@
/* FALLTHRU */
default:
- lock_kernel();
sigaddset(¤t->signal, signr);
recalc_sigpending(current);
current->flags |= PF_SIGNALED;
@@ -723,26 +812,128 @@
old_sigset_t *oset);
asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set,
- old_sigset_t32 *oset)
+ old_sigset_t32 *oset)
{
old_sigset_t s;
int ret;
mm_segment_t old_fs = get_fs();
- if (set && get_user (s, set)) return -EFAULT;
+ if (set && get_user (s, set))
+ return -EFAULT;
set_fs (KERNEL_DS);
ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
set_fs (old_fs);
- if (ret) return ret;
- if (oset && put_user (s, oset)) return -EFAULT;
- return 0;
+ if (!ret && oset && put_user (s, oset))
+ return -EFAULT;
+ return ret;
}
-/* Dummies ... */
+asmlinkage long sys_sigpending(old_sigset_t *set);
+
+asmlinkage int sys32_sigpending(old_sigset_t32 *set)
+{
+ old_sigset_t pending;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_sigpending(&pending);
+ set_fs (old_fs);
+
+ if (put_user(pending, set))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 *act,
+ struct sigaction32 *oact,
+ unsigned int sigsetsize)
+{
+ struct k_sigaction new_sa, old_sa;
+ int ret = -EINVAL;
+
+ /* XXX: Don't preclude handling different sized sigset_t's. */
+ if (sigsetsize != sizeof(sigset_t))
+ goto out;
+
+ if (act) {
+ int err = 0;
+
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+ return -EFAULT;
+ err |= __get_user((u32)(u64)new_sa.sa.sa_handler,
+ &act->sa_handler);
+ err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
+ err |= __get_user((u32)(u64)new_sa.sa.sa_restorer,
+ &act->sa_restorer);
+ err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
+ if (err)
+ return -EFAULT;
+ }
+
+ ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
+
+ if (!ret && oact) {
+ int err = 0;
+
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+ return -EFAULT;
+
+ err |= __put_user((u32)(u64)new_sa.sa.sa_handler,
+ &oact->sa_handler);
+ err |= __put_user(new_sa.sa.sa_flags, &oact->sa_flags);
+ err |= __put_user((u32)(u64)new_sa.sa.sa_restorer,
+ &oact->sa_restorer);
+ err |= put_sigset(&new_sa.sa.sa_mask, &oact->sa_mask);
+ if (err)
+ return -EFAULT;
+ }
+out:
+ return ret;
+}
+
+asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset,
+ size_t sigsetsize);
+
+asmlinkage int sys32_rt_sigprocmask(int how, sigset32_t *set, sigset32_t *oset,
+ unsigned int sigsetsize)
+{
+ sigset_t old_set, new_set;
+ int ret;
+ mm_segment_t old_fs = get_fs();
+
+ if (set && get_sigset(&new_set, set))
+ return -EFAULT;
+
+ set_fs (KERNEL_DS);
+ ret = sys_rt_sigprocmask(how, set ? &new_set : NULL,
+ oset ? &old_set : NULL, sigsetsize);
+ set_fs (old_fs);
+
+ if (!ret && oset && put_sigset(&old_set, oset))
+ return -EFAULT;
+
+ return ret;
+}
+
+asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
+
+asmlinkage int sys32_rt_sigpending(sigset32_t *uset, unsigned int sigsetsize)
+{
+ int ret;
+ sigset_t set;
+ mm_segment_t old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+ ret = sys_rt_sigpending(&set, sigsetsize);
+ set_fs (old_fs);
+
+ if (!ret && put_sigset(&set, uset))
+ return -EFAULT;
+
+ return ret;
+}
-asmlinkage void sys32_sigpending(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigaction(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigprocmask(void) { panic(__FUNCTION__ " called."); }
-asmlinkage void sys32_rt_sigpending(void) { panic(__FUNCTION__ " called."); }
asmlinkage void sys32_rt_sigtimedwait(void) { panic(__FUNCTION__ " called."); }
asmlinkage void sys32_rt_sigqueueinfo(void) { panic(__FUNCTION__ " called."); }
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)