11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public
31da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive
41da177e4SLinus Torvalds * for more details.
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
7dda73d0bSMartin Michlmayr * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
81da177e4SLinus Torvalds * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9d1e63c94SHarvey Hunt * Copyright (C) 2016, Imagination Technologies Ltd.
101da177e4SLinus Torvalds */
110d55303cSDeepa Dinamani #include <linux/compat.h>
12d1e63c94SHarvey Hunt #include <linux/compiler.h>
13d1e63c94SHarvey Hunt #include <linux/errno.h>
141da177e4SLinus Torvalds #include <linux/kernel.h>
151da177e4SLinus Torvalds #include <linux/signal.h>
161da177e4SLinus Torvalds #include <linux/syscalls.h>
171da177e4SLinus Torvalds
18431dc804SRalf Baechle #include <asm/compat-signal.h>
197c0f6ba6SLinus Torvalds #include <linux/uaccess.h>
20d1e63c94SHarvey Hunt #include <asm/unistd.h>
211da177e4SLinus Torvalds
2236a1f2c2SFranck Bui-Huu #include "signal-common.h"
2336a1f2c2SFranck Bui-Huu
241da177e4SLinus Torvalds /* 32-bit compatibility types */
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds typedef unsigned int __sighandler32_t;
271da177e4SLinus Torvalds typedef void (*vfptr_t)(void);
281da177e4SLinus Torvalds
299432a9baSFranck Bui-Huu /*
301da177e4SLinus Torvalds * Atomically swap in the new signal mask, and wait for a signal.
311da177e4SLinus Torvalds */
321da177e4SLinus Torvalds
sys32_sigsuspend(compat_sigset_t __user * uset)331910f4abSAl Viro asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
341da177e4SLinus Torvalds {
351910f4abSAl Viro return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds
38aa584802SAl Viro SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
39aa584802SAl Viro struct compat_sigaction __user *, oact)
401da177e4SLinus Torvalds {
411da177e4SLinus Torvalds struct k_sigaction new_ka, old_ka;
421da177e4SLinus Torvalds int ret;
431da177e4SLinus Torvalds int err = 0;
441da177e4SLinus Torvalds
451da177e4SLinus Torvalds if (act) {
461da177e4SLinus Torvalds old_sigset_t mask;
4777c728c2SRalf Baechle s32 handler;
481da177e4SLinus Torvalds
49*96d4f267SLinus Torvalds if (!access_ok(act, sizeof(*act)))
501da177e4SLinus Torvalds return -EFAULT;
5177c728c2SRalf Baechle err |= __get_user(handler, &act->sa_handler);
529bbf28a3SAtsushi Nemoto new_ka.sa.sa_handler = (void __user *)(s64)handler;
531da177e4SLinus Torvalds err |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
541da177e4SLinus Torvalds err |= __get_user(mask, &act->sa_mask.sig[0]);
551da177e4SLinus Torvalds if (err)
561da177e4SLinus Torvalds return -EFAULT;
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds siginitset(&new_ka.sa.sa_mask, mask);
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds
611da177e4SLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
621da177e4SLinus Torvalds
631da177e4SLinus Torvalds if (!ret && oact) {
64*96d4f267SLinus Torvalds if (!access_ok(oact, sizeof(*oact)))
651da177e4SLinus Torvalds return -EFAULT;
661da177e4SLinus Torvalds err |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
671da177e4SLinus Torvalds err |= __put_user((u32)(u64)old_ka.sa.sa_handler,
681da177e4SLinus Torvalds &oact->sa_handler);
691da177e4SLinus Torvalds err |= __put_user(old_ka.sa.sa_mask.sig[0], oact->sa_mask.sig);
701da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[1]);
711da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[2]);
721da177e4SLinus Torvalds err |= __put_user(0, &oact->sa_mask.sig[3]);
731da177e4SLinus Torvalds if (err)
741da177e4SLinus Torvalds return -EFAULT;
751da177e4SLinus Torvalds }
761da177e4SLinus Torvalds
771da177e4SLinus Torvalds return ret;
781da177e4SLinus Torvalds }
79