2005-04-16 15:20:36 -07:00
/*
2012-07-20 11:15:04 +02:00
* Copyright IBM Corp . 2000 , 2006
2005-04-16 15:20:36 -07:00
* Author ( s ) : Denis Joseph Barrow ( djbarrow @ de . ibm . com , barrow_dj @ yahoo . com )
* Gerhard Tonn ( ton @ de . ibm . com )
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
*
* 1997 - 11 - 28 Modified for POSIX .1 b signals by Richard Henderson
*/
# include <linux/compat.h>
# include <linux/sched.h>
# include <linux/mm.h>
# include <linux/smp.h>
# include <linux/kernel.h>
# include <linux/signal.h>
# include <linux/errno.h>
# include <linux/wait.h>
# include <linux/ptrace.h>
# include <linux/unistd.h>
# include <linux/stddef.h>
# include <linux/tty.h>
# include <linux/personality.h>
# include <linux/binfmts.h>
# include <asm/ucontext.h>
# include <asm/uaccess.h>
# include <asm/lowcore.h>
2012-03-28 18:30:02 +01:00
# include <asm/switch_to.h>
2005-04-16 15:20:36 -07:00
# include "compat_linux.h"
# include "compat_ptrace.h"
2008-04-17 07:46:26 +02:00
# include "entry.h"
2005-04-16 15:20:36 -07:00
typedef struct
{
__u8 callee_used_stack [ __SIGNAL_FRAMESIZE32 ] ;
struct sigcontext32 sc ;
_sigregs32 sregs ;
int signo ;
2014-10-06 17:53:53 +02:00
_sigregs_ext32 sregs_ext ;
__u16 svc_insn ; /* Offset of svc_insn is NOT fixed! */
2005-04-16 15:20:36 -07:00
} sigframe32 ;
typedef struct
{
__u8 callee_used_stack [ __SIGNAL_FRAMESIZE32 ] ;
2014-10-06 17:53:53 +02:00
__u16 svc_insn ;
2005-04-16 15:20:36 -07:00
compat_siginfo_t info ;
struct ucontext32 uc ;
} rt_sigframe32 ;
2015-09-08 15:25:39 +02:00
static inline void sigset_to_sigset32 ( unsigned long * set64 ,
compat_sigset_word * set32 )
{
set32 [ 0 ] = ( compat_sigset_word ) set64 [ 0 ] ;
set32 [ 1 ] = ( compat_sigset_word ) ( set64 [ 0 ] > > 32 ) ;
}
static inline void sigset32_to_sigset ( compat_sigset_word * set32 ,
unsigned long * set64 )
{
set64 [ 0 ] = ( unsigned long ) set32 [ 0 ] | ( ( unsigned long ) set32 [ 1 ] < < 32 ) ;
}
2013-10-13 17:23:53 -04:00
int copy_siginfo_to_user32 ( compat_siginfo_t __user * to , const siginfo_t * from )
2005-04-16 15:20:36 -07:00
{
int err ;
/* If you change siginfo_t structure, please be sure
this code is fixed accordingly .
It should never copy any pad contained in the structure
to avoid security leaks , but must copy the generic
3 ints plus the relevant union member .
This routine must convert siginfo from 64 bit to 32 bit as well
at the same time . */
err = __put_user ( from - > si_signo , & to - > si_signo ) ;
err | = __put_user ( from - > si_errno , & to - > si_errno ) ;
err | = __put_user ( ( short ) from - > si_code , & to - > si_code ) ;
if ( from - > si_code < 0 )
err | = __copy_to_user ( & to - > _sifields . _pad , & from - > _sifields . _pad , SI_PAD_SIZE ) ;
else {
switch ( from - > si_code > > 16 ) {
case __SI_RT > > 16 : /* This is not generated by the kernel as of now. */
case __SI_MESGQ > > 16 :
err | = __put_user ( from - > si_int , & to - > si_int ) ;
/* fallthrough */
case __SI_KILL > > 16 :
err | = __put_user ( from - > si_pid , & to - > si_pid ) ;
err | = __put_user ( from - > si_uid , & to - > si_uid ) ;
break ;
case __SI_CHLD > > 16 :
err | = __put_user ( from - > si_pid , & to - > si_pid ) ;
err | = __put_user ( from - > si_uid , & to - > si_uid ) ;
err | = __put_user ( from - > si_utime , & to - > si_utime ) ;
err | = __put_user ( from - > si_stime , & to - > si_stime ) ;
err | = __put_user ( from - > si_status , & to - > si_status ) ;
break ;
case __SI_FAULT > > 16 :
err | = __put_user ( ( unsigned long ) from - > si_addr ,
& to - > si_addr ) ;
break ;
case __SI_POLL > > 16 :
err | = __put_user ( from - > si_band , & to - > si_band ) ;
err | = __put_user ( from - > si_fd , & to - > si_fd ) ;
break ;
case __SI_TIMER > > 16 :
err | = __put_user ( from - > si_tid , & to - > si_tid ) ;
err | = __put_user ( from - > si_overrun , & to - > si_overrun ) ;
err | = __put_user ( from - > si_int , & to - > si_int ) ;
break ;
default :
break ;
}
}
2013-10-14 12:09:37 +02:00
return err ? - EFAULT : 0 ;
2005-04-16 15:20:36 -07:00
}
int copy_siginfo_from_user32 ( siginfo_t * to , compat_siginfo_t __user * from )
{
int err ;
u32 tmp ;
err = __get_user ( to - > si_signo , & from - > si_signo ) ;
err | = __get_user ( to - > si_errno , & from - > si_errno ) ;
err | = __get_user ( to - > si_code , & from - > si_code ) ;
if ( to - > si_code < 0 )
err | = __copy_from_user ( & to - > _sifields . _pad , & from - > _sifields . _pad , SI_PAD_SIZE ) ;
else {
switch ( to - > si_code > > 16 ) {
case __SI_RT > > 16 : /* This is not generated by the kernel as of now. */
case __SI_MESGQ > > 16 :
err | = __get_user ( to - > si_int , & from - > si_int ) ;
/* fallthrough */
case __SI_KILL > > 16 :
err | = __get_user ( to - > si_pid , & from - > si_pid ) ;
err | = __get_user ( to - > si_uid , & from - > si_uid ) ;
break ;
case __SI_CHLD > > 16 :
err | = __get_user ( to - > si_pid , & from - > si_pid ) ;
err | = __get_user ( to - > si_uid , & from - > si_uid ) ;
err | = __get_user ( to - > si_utime , & from - > si_utime ) ;
err | = __get_user ( to - > si_stime , & from - > si_stime ) ;
err | = __get_user ( to - > si_status , & from - > si_status ) ;
break ;
case __SI_FAULT > > 16 :
err | = __get_user ( tmp , & from - > si_addr ) ;
2011-10-30 15:17:15 +01:00
to - > si_addr = ( void __force __user * )
( u64 ) ( tmp & PSW32_ADDR_INSN ) ;
2005-04-16 15:20:36 -07:00
break ;
case __SI_POLL > > 16 :
err | = __get_user ( to - > si_band , & from - > si_band ) ;
err | = __get_user ( to - > si_fd , & from - > si_fd ) ;
break ;
case __SI_TIMER > > 16 :
err | = __get_user ( to - > si_tid , & from - > si_tid ) ;
err | = __get_user ( to - > si_overrun , & from - > si_overrun ) ;
err | = __get_user ( to - > si_int , & from - > si_int ) ;
break ;
default :
break ;
}
}
2013-10-14 12:09:37 +02:00
return err ? - EFAULT : 0 ;
2005-04-16 15:20:36 -07:00
}
2014-10-06 17:53:53 +02:00
/* Store registers needed to create the signal frame */
static void store_sigregs ( void )
{
save_access_regs ( current - > thread . acrs ) ;
2015-06-29 16:43:06 +02:00
save_fpu_regs ( ) ;
2014-10-06 17:53:53 +02:00
}
/* Load registers after signal return */
static void load_sigregs ( void )
{
restore_access_regs ( current - > thread . acrs ) ;
}
2005-04-16 15:20:36 -07:00
static int save_sigregs32 ( struct pt_regs * regs , _sigregs32 __user * sregs )
{
2013-10-15 16:08:34 +02:00
_sigregs32 user_sregs ;
int i ;
2005-04-16 15:20:36 -07:00
2013-10-16 09:58:01 +02:00
user_sregs . regs . psw . mask = ( __u32 ) ( regs - > psw . mask > > 32 ) ;
user_sregs . regs . psw . mask & = PSW32_MASK_USER | PSW32_MASK_RI ;
2013-10-16 14:17:29 +02:00
user_sregs . regs . psw . mask | = PSW32_USER_BITS ;
2013-10-15 16:08:34 +02:00
user_sregs . regs . psw . addr = ( __u32 ) regs - > psw . addr |
2011-10-30 15:16:51 +01:00
( __u32 ) ( regs - > psw . mask & PSW_MASK_BA ) ;
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < NUM_GPRS ; i + + )
2013-10-15 16:08:34 +02:00
user_sregs . regs . gprs [ i ] = ( __u32 ) regs - > gprs [ i ] ;
memcpy ( & user_sregs . regs . acrs , current - > thread . acrs ,
sizeof ( user_sregs . regs . acrs ) ) ;
2015-06-11 15:33:54 +02:00
fpregs_store ( ( _s390_fp_regs * ) & user_sregs . fpregs , & current - > thread . fpu ) ;
2013-10-15 16:08:34 +02:00
if ( __copy_to_user ( sregs , & user_sregs , sizeof ( _sigregs32 ) ) )
2013-10-14 13:34:28 +02:00
return - EFAULT ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
static int restore_sigregs32 ( struct pt_regs * regs , _sigregs32 __user * sregs )
{
2013-10-15 16:08:34 +02:00
_sigregs32 user_sregs ;
int i ;
2005-04-16 15:20:36 -07:00
/* Alwys make any pending restarted system call return -EINTR */
2015-02-12 15:01:14 -08:00
current - > restart_block . fn = do_no_restart_syscall ;
2005-04-16 15:20:36 -07:00
2013-10-15 16:08:34 +02:00
if ( __copy_from_user ( & user_sregs , & sregs - > regs , sizeof ( user_sregs ) ) )
2013-10-14 13:34:28 +02:00
return - EFAULT ;
2013-10-15 16:08:34 +02:00
2013-10-16 09:58:01 +02:00
if ( ! is_ri_task ( current ) & & ( user_sregs . regs . psw . mask & PSW32_MASK_RI ) )
return - EINVAL ;
2015-04-28 11:30:40 +02:00
/* Test the floating-point-control word. */
if ( test_fp_ctl ( user_sregs . fpregs . fpc ) )
2013-10-15 16:08:34 +02:00
return - EINVAL ;
/* Use regs->psw.mask instead of PSW_USER_BITS to preserve PER bit. */
2013-11-19 12:26:09 +01:00
regs - > psw . mask = ( regs - > psw . mask & ~ ( PSW_MASK_USER | PSW_MASK_RI ) ) |
2013-10-15 16:08:34 +02:00
( __u64 ) ( user_sregs . regs . psw . mask & PSW32_MASK_USER ) < < 32 |
2013-10-16 09:58:01 +02:00
( __u64 ) ( user_sregs . regs . psw . mask & PSW32_MASK_RI ) < < 32 |
2013-10-15 16:08:34 +02:00
( __u64 ) ( user_sregs . regs . psw . addr & PSW32_ADDR_AMODE ) ;
2012-11-07 10:44:08 +01:00
/* Check for invalid user address space control. */
2013-09-24 09:14:56 +02:00
if ( ( regs - > psw . mask & PSW_MASK_ASC ) = = PSW_ASC_HOME )
regs - > psw . mask = PSW_ASC_PRIMARY |
2012-11-07 10:44:08 +01:00
( regs - > psw . mask & ~ PSW_MASK_ASC ) ;
2013-10-15 16:08:34 +02:00
regs - > psw . addr = ( __u64 ) ( user_sregs . regs . psw . addr & PSW32_ADDR_INSN ) ;
2005-04-16 15:20:36 -07:00
for ( i = 0 ; i < NUM_GPRS ; i + + )
2013-10-15 16:08:34 +02:00
regs - > gprs [ i ] = ( __u64 ) user_sregs . regs . gprs [ i ] ;
memcpy ( & current - > thread . acrs , & user_sregs . regs . acrs ,
sizeof ( current - > thread . acrs ) ) ;
2015-06-11 15:33:54 +02:00
fpregs_load ( ( _s390_fp_regs * ) & user_sregs . fpregs , & current - > thread . fpu ) ;
2005-04-16 15:20:36 -07:00
2014-04-15 12:55:07 +02:00
clear_pt_regs_flag ( regs , PIF_SYSCALL ) ; /* No longer in a system call */
2005-04-16 15:20:36 -07:00
return 0 ;
}
2014-10-06 17:53:53 +02:00
static int save_sigregs_ext32 ( struct pt_regs * regs ,
_sigregs_ext32 __user * sregs_ext )
2009-10-06 10:34:13 +02:00
{
__u32 gprs_high [ NUM_GPRS ] ;
2014-10-06 17:53:53 +02:00
__u64 vxrs [ __NUM_VXRS_LOW ] ;
2009-10-06 10:34:13 +02:00
int i ;
2014-10-06 17:53:53 +02:00
/* Save high gprs to signal stack */
2009-10-06 10:34:13 +02:00
for ( i = 0 ; i < NUM_GPRS ; i + + )
gprs_high [ i ] = regs - > gprs [ i ] > > 32 ;
2014-10-06 17:53:53 +02:00
if ( __copy_to_user ( & sregs_ext - > gprs_high , & gprs_high ,
sizeof ( sregs_ext - > gprs_high ) ) )
2013-10-14 13:34:28 +02:00
return - EFAULT ;
2014-10-06 17:53:53 +02:00
/* Save vector registers to signal stack */
2015-06-11 15:33:54 +02:00
if ( is_vx_task ( current ) ) {
2014-10-06 17:53:53 +02:00
for ( i = 0 ; i < __NUM_VXRS_LOW ; i + + )
2015-06-11 15:33:54 +02:00
vxrs [ i ] = * ( ( __u64 * ) ( current - > thread . fpu . vxrs + i ) + 1 ) ;
2014-10-06 17:53:53 +02:00
if ( __copy_to_user ( & sregs_ext - > vxrs_low , vxrs ,
sizeof ( sregs_ext - > vxrs_low ) ) | |
__copy_to_user ( & sregs_ext - > vxrs_high ,
2015-06-11 15:33:54 +02:00
current - > thread . fpu . vxrs + __NUM_VXRS_LOW ,
2014-10-06 17:53:53 +02:00
sizeof ( sregs_ext - > vxrs_high ) ) )
return - EFAULT ;
}
2013-10-14 13:34:28 +02:00
return 0 ;
2009-10-06 10:34:13 +02:00
}
2014-10-06 17:53:53 +02:00
static int restore_sigregs_ext32 ( struct pt_regs * regs ,
_sigregs_ext32 __user * sregs_ext )
2009-10-06 10:34:13 +02:00
{
__u32 gprs_high [ NUM_GPRS ] ;
2014-10-06 17:53:53 +02:00
__u64 vxrs [ __NUM_VXRS_LOW ] ;
2013-10-14 13:34:28 +02:00
int i ;
2009-10-06 10:34:13 +02:00
2014-10-06 17:53:53 +02:00
/* Restore high gprs from signal stack */
if ( __copy_from_user ( & gprs_high , & sregs_ext - > gprs_high ,
sizeof ( & sregs_ext - > gprs_high ) ) )
2013-10-14 13:34:28 +02:00
return - EFAULT ;
2009-10-06 10:34:13 +02:00
for ( i = 0 ; i < NUM_GPRS ; i + + )
* ( __u32 * ) & regs - > gprs [ i ] = gprs_high [ i ] ;
2014-10-06 17:53:53 +02:00
/* Restore vector registers from signal stack */
2015-06-11 15:33:54 +02:00
if ( is_vx_task ( current ) ) {
2014-10-06 17:53:53 +02:00
if ( __copy_from_user ( vxrs , & sregs_ext - > vxrs_low ,
sizeof ( sregs_ext - > vxrs_low ) ) | |
2015-06-11 15:33:54 +02:00
__copy_from_user ( current - > thread . fpu . vxrs + __NUM_VXRS_LOW ,
2014-10-06 17:53:53 +02:00
& sregs_ext - > vxrs_high ,
sizeof ( sregs_ext - > vxrs_high ) ) )
return - EFAULT ;
for ( i = 0 ; i < __NUM_VXRS_LOW ; i + + )
2015-06-11 15:33:54 +02:00
* ( ( __u64 * ) ( current - > thread . fpu . vxrs + i ) + 1 ) = vxrs [ i ] ;
2014-10-06 17:53:53 +02:00
}
2009-10-06 10:34:13 +02:00
return 0 ;
}
2014-03-05 10:05:56 +01:00
COMPAT_SYSCALL_DEFINE0 ( sigreturn )
2005-04-16 15:20:36 -07:00
{
2007-04-27 16:01:40 +02:00
struct pt_regs * regs = task_pt_regs ( current ) ;
2005-04-16 15:20:36 -07:00
sigframe32 __user * frame = ( sigframe32 __user * ) regs - > gprs [ 15 ] ;
2015-09-08 15:25:39 +02:00
compat_sigset_t cset ;
2005-04-16 15:20:36 -07:00
sigset_t set ;
2015-09-08 15:25:39 +02:00
if ( __copy_from_user ( & cset . sig , & frame - > sc . oldmask , _SIGMASK_COPY_SIZE32 ) )
2005-04-16 15:20:36 -07:00
goto badframe ;
2015-09-08 15:25:39 +02:00
sigset32_to_sigset ( cset . sig , set . sig ) ;
2011-08-03 16:44:26 +02:00
set_current_blocked ( & set ) ;
2015-06-29 16:43:06 +02:00
save_fpu_regs ( ) ;
2005-04-16 15:20:36 -07:00
if ( restore_sigregs32 ( regs , & frame - > sregs ) )
goto badframe ;
2014-10-06 17:53:53 +02:00
if ( restore_sigregs_ext32 ( regs , & frame - > sregs_ext ) )
2009-10-06 10:34:13 +02:00
goto badframe ;
2014-10-06 17:53:53 +02:00
load_sigregs ( ) ;
2005-04-16 15:20:36 -07:00
return regs - > gprs [ 2 ] ;
badframe :
force_sig ( SIGSEGV , current ) ;
return 0 ;
}
2014-03-05 10:05:56 +01:00
COMPAT_SYSCALL_DEFINE0 ( rt_sigreturn )
2005-04-16 15:20:36 -07:00
{
2007-04-27 16:01:40 +02:00
struct pt_regs * regs = task_pt_regs ( current ) ;
2005-04-16 15:20:36 -07:00
rt_sigframe32 __user * frame = ( rt_sigframe32 __user * ) regs - > gprs [ 15 ] ;
2015-09-08 15:25:39 +02:00
compat_sigset_t cset ;
2005-04-16 15:20:36 -07:00
sigset_t set ;
2015-09-08 15:25:39 +02:00
if ( __copy_from_user ( & cset , & frame - > uc . uc_sigmask , sizeof ( cset ) ) )
2005-04-16 15:20:36 -07:00
goto badframe ;
2015-09-08 15:25:39 +02:00
sigset32_to_sigset ( cset . sig , set . sig ) ;
2011-08-03 16:44:26 +02:00
set_current_blocked ( & set ) ;
2014-10-06 17:53:53 +02:00
if ( compat_restore_altstack ( & frame - > uc . uc_stack ) )
goto badframe ;
2015-06-29 16:43:06 +02:00
save_fpu_regs ( ) ;
2005-04-16 15:20:36 -07:00
if ( restore_sigregs32 ( regs , & frame - > uc . uc_mcontext ) )
goto badframe ;
2014-10-06 17:53:53 +02:00
if ( restore_sigregs_ext32 ( regs , & frame - > uc . uc_mcontext_ext ) )
2009-10-06 10:34:13 +02:00
goto badframe ;
2014-10-06 17:53:53 +02:00
load_sigregs ( ) ;
2005-04-16 15:20:36 -07:00
return regs - > gprs [ 2 ] ;
badframe :
2007-04-27 16:01:40 +02:00
force_sig ( SIGSEGV , current ) ;
return 0 ;
2005-04-16 15:20:36 -07:00
}
/*
* Set up a signal frame .
*/
/*
* Determine which stack to use . .
*/
static inline void __user *
get_sigframe ( struct k_sigaction * ka , struct pt_regs * regs , size_t frame_size )
{
unsigned long sp ;
/* Default to using normal stack */
sp = ( unsigned long ) A ( regs - > gprs [ 15 ] ) ;
2008-04-17 07:45:57 +02:00
/* Overflow on alternate signal stack gives SIGSEGV. */
if ( on_sig_stack ( sp ) & & ! on_sig_stack ( ( sp - frame_size ) & - 8UL ) )
return ( void __user * ) - 1UL ;
2005-04-16 15:20:36 -07:00
/* This is the X/Open sanctioned signal stack switching. */
if ( ka - > sa . sa_flags & SA_ONSTACK ) {
2006-04-27 18:40:07 -07:00
if ( ! sas_ss_flags ( sp ) )
2005-04-16 15:20:36 -07:00
sp = current - > sas_ss_sp + current - > sas_ss_size ;
}
return ( void __user * ) ( ( sp - frame_size ) & - 8ul ) ;
}
2014-07-13 22:21:03 +02:00
static int setup_frame32 ( struct ksignal * ksig , sigset_t * set ,
struct pt_regs * regs )
2005-04-16 15:20:36 -07:00
{
2014-07-13 22:21:03 +02:00
int sig = ksig - > sig ;
2014-10-06 17:53:53 +02:00
sigframe32 __user * frame ;
struct sigcontext32 sc ;
unsigned long restorer ;
size_t frame_size ;
/*
* gprs_high are always present for 31 - bit compat tasks .
* The space for vector registers is only allocated if
* the machine supports it
*/
frame_size = sizeof ( * frame ) - sizeof ( frame - > sregs_ext . __reserved ) ;
if ( ! MACHINE_HAS_VX )
frame_size - = sizeof ( frame - > sregs_ext . vxrs_low ) +
sizeof ( frame - > sregs_ext . vxrs_high ) ;
frame = get_sigframe ( & ksig - > ka , regs , frame_size ) ;
2008-04-17 07:45:57 +02:00
if ( frame = = ( void __user * ) - 1UL )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2008-04-17 07:45:57 +02:00
2014-10-06 17:53:53 +02:00
/* Set up backchain. */
if ( __put_user ( regs - > gprs [ 15 ] , ( unsigned int __user * ) frame ) )
return - EFAULT ;
/* Create struct sigcontext32 on the signal stack */
2015-09-08 15:25:39 +02:00
sigset_to_sigset32 ( set - > sig , sc . oldmask ) ;
2014-10-06 17:53:53 +02:00
sc . sregs = ( __u32 ) ( unsigned long __force ) & frame - > sregs ;
if ( __copy_to_user ( & frame - > sc , & sc , sizeof ( frame - > sc ) ) )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
2014-10-06 17:53:53 +02:00
/* Store registers needed to create the signal frame */
store_sigregs ( ) ;
/* Create _sigregs32 on the signal stack */
2005-04-16 15:20:36 -07:00
if ( save_sigregs32 ( regs , & frame - > sregs ) )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2014-10-06 17:53:53 +02:00
/* Place signal number on stack to allow backtrace from handler. */
if ( __put_user ( regs - > gprs [ 2 ] , ( int __force __user * ) & frame - > signo ) )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2014-10-06 17:53:53 +02:00
/* Create _sigregs_ext32 on the signal stack */
if ( save_sigregs_ext32 ( regs , & frame - > sregs_ext ) )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
/* Set up to return from userspace. If provided, use a stub
already in userspace . */
2014-07-13 22:21:03 +02:00
if ( ksig - > ka . sa . sa_flags & SA_RESTORER ) {
2014-10-06 17:53:53 +02:00
restorer = ( unsigned long __force )
ksig - > ka . sa . sa_restorer | PSW32_ADDR_AMODE ;
2005-04-16 15:20:36 -07:00
} else {
2014-10-06 17:53:53 +02:00
/* Signal frames without vectors registers are short ! */
2014-10-30 13:45:43 +01:00
__u16 __user * svc = ( void __user * ) frame + frame_size - 2 ;
2014-10-06 17:53:53 +02:00
if ( __put_user ( S390_SYSCALL_OPCODE | __NR_sigreturn , svc ) )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2014-10-06 17:53:53 +02:00
restorer = ( unsigned long __force ) svc | PSW32_ADDR_AMODE ;
2005-04-16 15:20:36 -07:00
}
/* Set up registers for signal handler */
2014-10-06 17:53:53 +02:00
regs - > gprs [ 14 ] = restorer ;
2011-10-30 15:17:15 +01:00
regs - > gprs [ 15 ] = ( __force __u64 ) frame ;
2012-11-07 10:44:08 +01:00
/* Force 31 bit amode and default user address space control. */
regs - > psw . mask = PSW_MASK_BA |
2013-09-24 09:14:56 +02:00
( PSW_USER_BITS & PSW_MASK_ASC ) |
2012-11-07 10:44:08 +01:00
( regs - > psw . mask & ~ PSW_MASK_ASC ) ;
2014-07-13 22:21:03 +02:00
regs - > psw . addr = ( __force __u64 ) ksig - > ka . sa . sa_handler ;
2005-04-16 15:20:36 -07:00
2014-09-09 23:50:11 +02:00
regs - > gprs [ 2 ] = sig ;
2011-10-30 15:17:15 +01:00
regs - > gprs [ 3 ] = ( __force __u64 ) & frame - > sc ;
2005-04-16 15:20:36 -07:00
/* We forgot to include these in the sigcontext.
To avoid breaking binary compatibility , they are passed as args . */
2011-12-27 11:27:18 +01:00
if ( sig = = SIGSEGV | | sig = = SIGBUS | | sig = = SIGILL | |
sig = = SIGTRAP | | sig = = SIGFPE ) {
/* set extra registers only for synchronous signals */
regs - > gprs [ 4 ] = regs - > int_code & 127 ;
regs - > gprs [ 5 ] = regs - > int_parm_long ;
2013-04-15 17:50:03 +02:00
regs - > gprs [ 6 ] = task_thread_info ( current ) - > last_break ;
2011-12-27 11:27:18 +01:00
}
2005-04-16 15:20:36 -07:00
2006-02-01 03:06:38 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
2014-07-13 22:21:03 +02:00
static int setup_rt_frame32 ( struct ksignal * ksig , sigset_t * set ,
struct pt_regs * regs )
2005-04-16 15:20:36 -07:00
{
2015-09-08 15:25:39 +02:00
compat_sigset_t cset ;
2014-10-06 17:53:53 +02:00
rt_sigframe32 __user * frame ;
unsigned long restorer ;
size_t frame_size ;
u32 uc_flags ;
frame_size = sizeof ( * frame ) -
sizeof ( frame - > uc . uc_mcontext_ext . __reserved ) ;
/*
* gprs_high are always present for 31 - bit compat tasks .
* The space for vector registers is only allocated if
* the machine supports it
*/
uc_flags = UC_GPRS_HIGH ;
if ( MACHINE_HAS_VX ) {
2015-06-11 15:33:54 +02:00
if ( is_vx_task ( current ) )
2014-10-06 17:53:53 +02:00
uc_flags | = UC_VXRS ;
} else
frame_size - = sizeof ( frame - > uc . uc_mcontext_ext . vxrs_low ) +
sizeof ( frame - > uc . uc_mcontext_ext . vxrs_high ) ;
frame = get_sigframe ( & ksig - > ka , regs , frame_size ) ;
2008-04-17 07:45:57 +02:00
if ( frame = = ( void __user * ) - 1UL )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2008-04-17 07:45:57 +02:00
2014-10-06 17:53:53 +02:00
/* Set up backchain. */
if ( __put_user ( regs - > gprs [ 15 ] , ( unsigned int __force __user * ) frame ) )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
/* Set up to return from userspace. If provided, use a stub
already in userspace . */
2014-07-13 22:21:03 +02:00
if ( ksig - > ka . sa . sa_flags & SA_RESTORER ) {
2014-10-06 17:53:53 +02:00
restorer = ( unsigned long __force )
ksig - > ka . sa . sa_restorer | PSW32_ADDR_AMODE ;
2005-04-16 15:20:36 -07:00
} else {
2014-10-06 17:53:53 +02:00
__u16 __user * svc = & frame - > svc_insn ;
if ( __put_user ( S390_SYSCALL_OPCODE | __NR_rt_sigreturn , svc ) )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2014-10-06 17:53:53 +02:00
restorer = ( unsigned long __force ) svc | PSW32_ADDR_AMODE ;
2005-04-16 15:20:36 -07:00
}
2014-10-06 17:53:53 +02:00
/* Create siginfo on the signal stack */
if ( copy_siginfo_to_user32 ( & frame - > info , & ksig - > info ) )
return - EFAULT ;
/* Store registers needed to create the signal frame */
store_sigregs ( ) ;
/* Create ucontext on the signal stack. */
2015-09-08 15:25:39 +02:00
sigset_to_sigset32 ( set - > sig , cset . sig ) ;
2014-10-06 17:53:53 +02:00
if ( __put_user ( uc_flags , & frame - > uc . uc_flags ) | |
__put_user ( 0 , & frame - > uc . uc_link ) | |
__compat_save_altstack ( & frame - > uc . uc_stack , regs - > gprs [ 15 ] ) | |
save_sigregs32 ( regs , & frame - > uc . uc_mcontext ) | |
2015-09-08 15:25:39 +02:00
__copy_to_user ( & frame - > uc . uc_sigmask , & cset , sizeof ( cset ) ) | |
2014-10-06 17:53:53 +02:00
save_sigregs_ext32 ( regs , & frame - > uc . uc_mcontext_ext ) )
2014-07-13 22:21:03 +02:00
return - EFAULT ;
2005-04-16 15:20:36 -07:00
/* Set up registers for signal handler */
2014-10-06 17:53:53 +02:00
regs - > gprs [ 14 ] = restorer ;
2011-10-30 15:17:15 +01:00
regs - > gprs [ 15 ] = ( __force __u64 ) frame ;
2012-11-07 10:44:08 +01:00
/* Force 31 bit amode and default user address space control. */
regs - > psw . mask = PSW_MASK_BA |
2013-09-24 09:14:56 +02:00
( PSW_USER_BITS & PSW_MASK_ASC ) |
2012-11-07 10:44:08 +01:00
( regs - > psw . mask & ~ PSW_MASK_ASC ) ;
2014-07-13 22:21:03 +02:00
regs - > psw . addr = ( __u64 __force ) ksig - > ka . sa . sa_handler ;
2005-04-16 15:20:36 -07:00
2014-09-09 23:50:11 +02:00
regs - > gprs [ 2 ] = ksig - > sig ;
2011-10-30 15:17:15 +01:00
regs - > gprs [ 3 ] = ( __force __u64 ) & frame - > info ;
regs - > gprs [ 4 ] = ( __force __u64 ) & frame - > uc ;
2013-04-15 17:50:03 +02:00
regs - > gprs [ 5 ] = task_thread_info ( current ) - > last_break ;
2006-02-01 03:06:38 -08:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
/*
* OK , we ' re invoking a handler
*/
2014-07-13 22:21:03 +02:00
void handle_signal32 ( struct ksignal * ksig , sigset_t * oldset ,
struct pt_regs * regs )
2005-04-16 15:20:36 -07:00
{
2006-02-01 03:06:38 -08:00
int ret ;
2005-04-16 15:20:36 -07:00
/* Set up the stack frame */
2014-07-13 22:21:03 +02:00
if ( ksig - > ka . sa . sa_flags & SA_SIGINFO )
ret = setup_rt_frame32 ( ksig , oldset , regs ) ;
2005-04-16 15:20:36 -07:00
else
2014-07-13 22:21:03 +02:00
ret = setup_frame32 ( ksig , oldset , regs ) ;
signal_setup_done ( ret , ksig , test_thread_flag ( TIF_SINGLE_STEP ) ) ;
2005-04-16 15:20:36 -07:00
}