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 */ 11*0d55303cSDeepa 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 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 491da177e4SLinus Torvalds if (!access_ok(VERIFY_READ, 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) { 641da177e4SLinus Torvalds if (!access_ok(VERIFY_WRITE, 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