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