diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:02:30 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:02:30 +0000 |
commit | 76cb841cb886eef6b3bee341a2266c76578724ad (patch) | |
tree | f5892e5ba6cc11949952a6ce4ecbe6d516d6ce58 /arch/mips/kernel/signal32.c | |
parent | Initial commit. (diff) | |
download | linux-upstream/4.19.249.tar.xz linux-upstream/4.19.249.zip |
Adding upstream version 4.19.249.upstream/4.19.249upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r-- | arch/mips/kernel/signal32.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c new file mode 100644 index 000000000..b5d9e1784 --- /dev/null +++ b/arch/mips/kernel/signal32.c @@ -0,0 +1,78 @@ +/* + * 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. + * + * Copyright (C) 1991, 1992 Linus Torvalds + * Copyright (C) 1994 - 2000, 2006 Ralf Baechle + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 2016, Imagination Technologies Ltd. + */ +#include <linux/compat.h> +#include <linux/compiler.h> +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/signal.h> +#include <linux/syscalls.h> + +#include <asm/compat-signal.h> +#include <linux/uaccess.h> +#include <asm/unistd.h> + +#include "signal-common.h" + +/* 32-bit compatibility types */ + +typedef unsigned int __sighandler32_t; +typedef void (*vfptr_t)(void); + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ + +asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset) +{ + return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t)); +} + +SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act, + struct compat_sigaction __user *, oact) +{ + struct k_sigaction new_ka, old_ka; + int ret; + int err = 0; + + if (act) { + old_sigset_t mask; + s32 handler; + + if (!access_ok(VERIFY_READ, act, sizeof(*act))) + return -EFAULT; + err |= __get_user(handler, &act->sa_handler); + new_ka.sa.sa_handler = (void __user *)(s64)handler; + err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); + err |= __get_user(mask, &act->sa_mask.sig[0]); + if (err) + return -EFAULT; + + siginitset(&new_ka.sa.sa_mask, mask); + } + + ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + + if (!ret && oact) { + if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact))) + return -EFAULT; + err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); + 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]); + if (err) + return -EFAULT; + } + + return ret; +} |