compat_signal.c revision 28f223782bca914ae65d08234c57c2175ecd7f5d
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 254dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens * arch/s390/kernel/compat_signal.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 454dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens * Copyright (C) IBM Corp. 2000,2006 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Gerhard Tonn (ton@de.ibm.com) 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/config.h> 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/compat.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/sched.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp_lock.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/signal.h> 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/wait.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/unistd.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/stddef.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/tty.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/personality.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/binfmts.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/ucontext.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/lowcore.h> 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "compat_linux.h" 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "compat_ptrace.h" 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sigcontext32 sc; 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds _sigregs32 sregs; 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int signo; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 retcode[S390_SYSCALL_SIZE]; 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} sigframe32; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 retcode[S390_SYSCALL_SIZE]; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compat_siginfo_t info; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ucontext32 uc; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} rt_sigframe32; 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t))) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* If you change siginfo_t structure, please be sure 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds this code is fixed accordingly. 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds It should never copy any pad contained in the structure 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds to avoid security leaks, but must copy the generic 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3 ints plus the relevant union member. 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds This routine must convert siginfo from 64bit to 32bit as well 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds at the same time. */ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = __put_user(from->si_signo, &to->si_signo); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_errno, &to->si_errno); 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user((short)from->si_code, &to->si_code); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (from->si_code < 0) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (from->si_code >> 16) { 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_MESGQ >> 16: 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_int, &to->si_int); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fallthrough */ 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_KILL >> 16: 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_pid, &to->si_pid); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_uid, &to->si_uid); 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_CHLD >> 16: 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_pid, &to->si_pid); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_uid, &to->si_uid); 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_utime, &to->si_utime); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_stime, &to->si_stime); 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_status, &to->si_status); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_FAULT >> 16: 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user((unsigned long) from->si_addr, 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &to->si_addr); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_POLL >> 16: 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_band, &to->si_band); 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_fd, &to->si_fd); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_TIMER >> 16: 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_tid, &to->si_tid); 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_overrun, &to->si_overrun); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(from->si_int, &to->si_int); 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 tmp; 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t))) 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = __get_user(to->si_signo, &from->si_signo); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_errno, &from->si_errno); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_code, &from->si_code); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (to->si_code < 0) 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE); 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (to->si_code >> 16) { 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_RT >> 16: /* This is not generated by the kernel as of now. */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_MESGQ >> 16: 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_int, &from->si_int); 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* fallthrough */ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_KILL >> 16: 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_pid, &from->si_pid); 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_uid, &from->si_uid); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_CHLD >> 16: 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_pid, &from->si_pid); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_uid, &from->si_uid); 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_utime, &from->si_utime); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_stime, &from->si_stime); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_status, &from->si_status); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_FAULT >> 16: 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(tmp, &from->si_addr); 143c28144763a7dcdceb2c16a5ac9c8e0022d547d28Al Viro to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_POLL >> 16: 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_band, &from->si_band); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_fd, &from->si_fd); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case __SI_TIMER >> 16: 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_tid, &from->si_tid); 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_overrun, &from->si_overrun); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(to->si_int, &from->si_int); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage long 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssys32_sigaction(int sig, const struct old_sigaction32 __user *act, 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct old_sigaction32 __user *oact) 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct k_sigaction new_ka, old_ka; 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long sa_handler, sa_restorer; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (act) { 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compat_old_sigset_t mask; 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(sa_handler, &act->sa_handler) || 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(sa_restorer, &act->sa_restorer)) 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_ka.sa.sa_handler = (__sighandler_t) sa_handler; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer; 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(new_ka.sa.sa_flags, &act->sa_flags); 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_user(mask, &act->sa_mask); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginitset(&new_ka.sa.sa_mask, mask); 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret && oact) { 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa_handler = (unsigned long) old_ka.sa.sa_handler; 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sa_restorer = (unsigned long) old_ka.sa.sa_restorer; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __put_user(sa_handler, &oact->sa_handler) || 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __put_user(sa_restorer, &oact->sa_restorer)) 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __put_user(old_ka.sa.sa_flags, &oact->sa_flags); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage long 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssys32_rt_sigaction(int sig, const struct sigaction32 __user *act, 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sigaction32 __user *oact, size_t sigsetsize) 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct k_sigaction new_ka, old_ka; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long sa_handler; 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds compat_sigset_t set32; 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* XXX: Don't preclude handling different sized sigset_t's. */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (sigsetsize != sizeof(compat_sigset_t)) 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (act) { 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = get_user(sa_handler, &act->sa_handler); 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret |= __copy_from_user(&set32, &act->sa_mask, 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(compat_sigset_t)); 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (_NSIG_WORDS) { 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | (((long)set32.sig[7]) << 32); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | (((long)set32.sig[5]) << 32); 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | (((long)set32.sig[3]) << 32); 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds | (((long)set32.sig[1]) << 32); 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags); 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds new_ka.sa.sa_handler = (__sighandler_t) sa_handler; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret && oact) { 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (_NSIG_WORDS) { 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 4: 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set32.sig[6] = old_ka.sa.sa_mask.sig[3]; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 3: 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set32.sig[4] = old_ka.sa.sa_mask.sig[2]; 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set32.sig[2] = old_ka.sa.sa_mask.sig[1]; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set32.sig[0] = old_ka.sa.sa_mask.sig[0]; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler); 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret |= __copy_to_user(&oact->sa_mask, &set32, 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(compat_sigset_t)); 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage long 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss, 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct pt_regs *regs) 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stack_t kss, koss; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long ss_sp; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret, err = 0; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mm_segment_t old_fs = get_fs(); 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (uss) { 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(ss_sp, &uss->ss_sp); 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(kss.ss_size, &uss->ss_size); 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(kss.ss_flags, &uss->ss_flags); 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 275c28144763a7dcdceb2c16a5ac9c8e0022d547d28Al Viro kss.ss_sp = (void __user *) ss_sp; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs (KERNEL_DS); 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = do_sigaltstack((stack_t __user *) (uss ? &kss : NULL), 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (stack_t __user *) (uoss ? &koss : NULL), 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[15]); 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs (old_fs); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!ret && uoss) { 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss))) 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ss_sp = (unsigned long) koss.ss_sp; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(ss_sp, &uoss->ss_sp); 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(koss.ss_size, &uoss->ss_size); 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(koss.ss_flags, &uoss->ss_flags); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs) 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds _s390_regs_common32 regs32; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err, i; 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs32.psw.mask = PSW32_MASK_MERGE(PSW32_USER_BITS, 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (__u32)(regs->psw.mask >> 32)); 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr; 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < NUM_GPRS; i++) 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs32.gprs[i] = (__u32) regs->gprs[i]; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save_access_regs(current->thread.acrs); 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(regs32.acrs, current->thread.acrs, sizeof(regs32.acrs)); 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = __copy_to_user(&sregs->regs, ®s32, sizeof(regs32)); 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds save_fp_regs(¤t->thread.fp_regs); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* s390_fp_regs and _s390_fp_regs32 are the same ! */ 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return __copy_to_user(&sregs->fpregs, ¤t->thread.fp_regs, 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(_s390_fp_regs32)); 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds _s390_regs_common32 regs32; 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err, i; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Alwys make any pending restarted system call return -EINTR */ 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current_thread_info()->restart_block.fn = do_no_restart_syscall; 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = __copy_from_user(®s32, &sregs->regs, sizeof(regs32)); 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask, 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (__u64)regs32.psw.mask << 32); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < NUM_GPRS; i++) 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[i] = (__u64) regs32.gprs[i]; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memcpy(current->thread.acrs, regs32.acrs, sizeof(current->thread.acrs)); 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds restore_access_regs(current->thread.acrs); 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = __copy_from_user(¤t->thread.fp_regs, &sregs->fpregs, 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sizeof(_s390_fp_regs32)); 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current->thread.fp_regs.fpc &= FPC_VALID_MASK; 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds restore_fp_regs(¤t->thread.fp_regs); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->trap = -1; /* disable syscall checks */ 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage long sys32_sigreturn(struct pt_regs *regs) 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigset_t set; 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32)) 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigdelsetmask(&set, ~_BLOCKABLE); 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(¤t->sighand->siglock); 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current->blocked = set; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds recalc_sigpending(); 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(¤t->sighand->siglock); 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (restore_sigregs32(regs, &frame->sregs)) 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return regs->gprs[2]; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbadframe: 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig(SIGSEGV, current); 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsasmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigset_t set; 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stack_t st; 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u32 ss_sp; 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mm_segment_t old_fs = get_fs(); 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigdelsetmask(&set, ~_BLOCKABLE); 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_lock_irq(¤t->sighand->siglock); 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds current->blocked = set; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds recalc_sigpending(); 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds spin_unlock_irq(¤t->sighand->siglock); 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (restore_sigregs32(regs, &frame->uc.uc_mcontext)) 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp); 398c28144763a7dcdceb2c16a5ac9c8e0022d547d28Al Viro st.ss_sp = compat_ptr(ss_sp); 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size); 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags); 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto badframe; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs (KERNEL_DS); 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]); 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds set_fs (old_fs); 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return regs->gprs[2]; 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsbadframe: 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sig(SIGSEGV, current); 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Set up a signal frame. 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Determine which stack to use.. 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void __user * 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsget_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unsigned long sp; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Default to using normal stack */ 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sp = (unsigned long) A(regs->gprs[15]); 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is the X/Open sanctioned signal stack switching. */ 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ka->sa.sa_flags & SA_ONSTACK) { 43328f223782bca914ae65d08234c57c2175ecd7f5dLaurent Meyer if (! sas_ss_flags(sp)) 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sp = current->sas_ss_sp + current->sas_ss_size; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* This is the legacy signal stack switching. */ 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (!user_mode(regs) && 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds !(ka->sa.sa_flags & SA_RESTORER) && 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ka->sa.sa_restorer) { 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sp = (unsigned long) ka->sa.sa_restorer; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (void __user *)((sp - frame_size) & -8ul); 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline int map_signal(int sig) 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (current_thread_info()->exec_domain 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && current_thread_info()->exec_domain->signal_invmap 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds && sig < 32) 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return current_thread_info()->exec_domain->signal_invmap[sig]; 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sig; 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45754dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstensstatic int setup_frame32(int sig, struct k_sigaction *ka, 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigset_t *set, struct pt_regs * regs) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32)); 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe32))) 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32)) 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (save_sigregs32(regs, &frame->sregs)) 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs)) 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up to return from userspace. If provided, use a stub 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds already in userspace. */ 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ka->sa.sa_flags & SA_RESTORER) { 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[14] = (__u64) ka->sa.sa_restorer; 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[14] = (__u64) frame->retcode; 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (u16 __user *)(frame->retcode))) 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up backchain. */ 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__put_user(regs->gprs[15], (unsigned int __user *) frame)) 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up registers for signal handler */ 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[15] = (__u64) frame; 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->psw.addr = (__u64) ka->sa.sa_handler; 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[2] = map_signal(sig); 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[3] = (__u64) &frame->sc; 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* We forgot to include these in the sigcontext. 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds To avoid breaking binary compatibility, they are passed as args. */ 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[4] = current->thread.trap_no; 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[5] = current->thread.prot_addr; 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Place signal number on stack to allow backtrace from handler. */ 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 50254dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens return 0; 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgive_sigsegv: 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sigsegv(sig, current); 50654dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens return -EFAULT; 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 50954dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstensstatic int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sigset_t *set, struct pt_regs * regs) 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err = 0; 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32)); 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe32))) 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (copy_siginfo_to_user32(&frame->info, info)) 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Create the ucontext. */ 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(0, &frame->uc.uc_flags); 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(0, &frame->uc.uc_link); 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(sas_ss_flags(regs->gprs[15]), 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &frame->uc.uc_stack.ss_flags); 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= save_sigregs32(regs, &frame->uc.uc_mcontext); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (err) 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up to return from userspace. If provided, use a stub 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds already in userspace. */ 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ka->sa.sa_flags & SA_RESTORER) { 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[14] = (__u64) ka->sa.sa_restorer; 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[14] = (__u64) frame->retcode; 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (u16 __user *)(frame->retcode)); 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up backchain. */ 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (__put_user(regs->gprs[15], (unsigned int __user *) frame)) 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto give_sigsegv; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up registers for signal handler */ 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[15] = (__u64) frame; 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->psw.addr = (__u64) ka->sa.sa_handler; 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[2] = map_signal(sig); 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[3] = (__u64) &frame->info; 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds regs->gprs[4] = (__u64) &frame->uc; 55354dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens return 0; 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsgive_sigsegv: 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds force_sigsegv(sig, current); 55754dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens return -EFAULT; 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * OK, we're invoking a handler 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 56454dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstensint 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshandle_signal32(unsigned long sig, struct k_sigaction *ka, 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds siginfo_t *info, sigset_t *oldset, struct pt_regs * regs) 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 56854dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens int ret; 56954dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Set up the stack frame */ 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ka->sa.sa_flags & SA_SIGINFO) 57254dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens ret = setup_rt_frame32(sig, ka, info, oldset, regs); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 57454dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens ret = setup_frame32(sig, ka, oldset, regs); 57554dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens 57654dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens if (ret == 0) { 57754dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens spin_lock_irq(¤t->sighand->siglock); 57854dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); 57954dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens if (!(ka->sa.sa_flags & SA_NODEFER)) 58054dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens sigaddset(¤t->blocked,sig); 58154dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens recalc_sigpending(); 58254dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens spin_unlock_irq(¤t->sighand->siglock); 58354dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens } 58454dfe5dd9abc547f63060d132dad2c024a47de1eHeiko Carstens return ret; 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 587