summaryrefslogtreecommitdiffstats
path: root/arch/mips64/kernel
diff options
context:
space:
mode:
authorUlf Carlsson <md1ulfc@mdstud.chalmers.se>2000-05-13 02:37:18 +0000
committerUlf Carlsson <md1ulfc@mdstud.chalmers.se>2000-05-13 02:37:18 +0000
commit35fd5eb6a16239d684d509f74380ddef0f59194b (patch)
tree66af40a70adf8197c2f7c2f90a2bb1a5302430a0 /arch/mips64/kernel
parent4bc5b42e99fed8e6e548feb8412dd5f987723557 (diff)
sigset_t fixes and a few new functions..
Diffstat (limited to 'arch/mips64/kernel')
-rw-r--r--arch/mips64/kernel/linux32.c4
-rw-r--r--arch/mips64/kernel/signal32.c228
2 files changed, 206 insertions, 26 deletions
diff --git a/arch/mips64/kernel/linux32.c b/arch/mips64/kernel/linux32.c
index 529c62031..c6487e40a 100644
--- a/arch/mips64/kernel/linux32.c
+++ b/arch/mips64/kernel/linux32.c
@@ -232,7 +232,7 @@ asmlinkage int sys_truncate64(const char *path, unsigned int high,
{
if ((int)high < 0)
return -EINVAL;
- return sys_truncate(path, (high << 32) | low);
+ return sys_truncate(path, ((long) high << 32) | low);
}
asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
@@ -242,7 +242,7 @@ asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
{
if ((int)high < 0)
return -EINVAL;
- return sys_ftruncate(fd, (high << 32) | low);
+ return sys_ftruncate(fd, ((long) high << 32) | low);
}
asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
diff --git a/arch/mips64/kernel/signal32.c b/arch/mips64/kernel/signal32.c
index e33a69d5e..7d4ce3050 100644
--- a/arch/mips64/kernel/signal32.c
+++ b/arch/mips64/kernel/signal32.c
@@ -61,7 +61,7 @@ struct sigaction32 {
/* IRIX compatible stack_t */
typedef struct sigaltstack32 {
void *ss_sp;
- size_t ss_size;
+ __kernel_size_t32 ss_size;
int ss_flags;
} stack32_t;
@@ -95,18 +95,72 @@ static inline int refill_fp_context(struct sigcontext *sc)
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(&regs);
+#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(&regs);
+ uset = (sigset32_t *) regs.regs[4];
+ if (get_sigset(&newset, uset))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
@@ -129,19 +183,22 @@ printk("%s called.\n", __FUNCTION__);
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(&regs);
+#if DEBUG_MIPS64
printk("%s called.\n", __FUNCTION__);
+#endif
+ save_static(&regs);
/* 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);
@@ -205,12 +262,37 @@ asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
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();
+
+ 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;
+ }
- return do_sigaltstack(uss, uoss, usp);
+ 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
@@ -724,26 +806,124 @@ extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set,
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;
+}
+
+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;
}
-/* Dummies ... */
+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 (new_sa.sa.sa_handler, &act->sa_handler);
+ err |= __get_user (new_sa.sa.sa_flags, &act->sa_flags);
+ err |= __get_user (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 (new_sa.sa.sa_handler, &oact->sa_handler);
+ err |= __put_user (new_sa.sa.sa_flags, &oact->sa_flags);
+ err |= __put_user (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."); }