2005-04-17 02:20:36 +04:00
/*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*
* Copyright ( C ) 1991 , 1992 Linus Torvalds
2006-02-18 18:21:30 +03:00
* Copyright ( C ) 1994 - 2000 , 2006 Ralf Baechle
2005-04-17 02:20:36 +04:00
* Copyright ( C ) 1999 , 2000 Silicon Graphics , Inc .
2016-06-17 18:03:45 +03:00
* Copyright ( C ) 2016 , Imagination Technologies Ltd .
2005-04-17 02:20:36 +04:00
*/
2016-06-17 18:03:45 +03:00
# include <linux/compiler.h>
# include <linux/errno.h>
2005-04-17 02:20:36 +04:00
# include <linux/kernel.h>
# include <linux/signal.h>
# include <linux/syscalls.h>
2016-06-17 18:03:45 +03:00
# include <asm/compat.h>
2007-02-13 03:05:11 +03:00
# include <asm/compat-signal.h>
2016-06-17 18:03:45 +03:00
# include <asm/uaccess.h>
# include <asm/unistd.h>
2005-04-17 02:20:36 +04:00
2007-02-05 17:24:22 +03:00
# include "signal-common.h"
2005-04-17 02:20:36 +04:00
/* 32-bit compatibility types */
typedef unsigned int __sighandler32_t ;
typedef void ( * vfptr_t ) ( void ) ;
/*
* Atomically swap in the new signal mask , and wait for a signal .
*/
2012-12-26 01:25:18 +04:00
asmlinkage int sys32_sigsuspend ( compat_sigset_t __user * uset )
2005-04-17 02:20:36 +04:00
{
2012-12-26 01:25:18 +04:00
return compat_sys_rt_sigsuspend ( uset , sizeof ( compat_sigset_t ) ) ;
2005-04-17 02:20:36 +04:00
}
2012-12-26 03:55:27 +04:00
SYSCALL_DEFINE3 ( 32 _sigaction , long , sig , const struct compat_sigaction __user * , act ,
struct compat_sigaction __user * , oact )
2005-04-17 02:20:36 +04:00
{
struct k_sigaction new_ka , old_ka ;
int ret ;
int err = 0 ;
if ( act ) {
old_sigset_t mask ;
2005-03-04 22:36:51 +03:00
s32 handler ;
2005-04-17 02:20:36 +04:00
if ( ! access_ok ( VERIFY_READ , act , sizeof ( * act ) ) )
return - EFAULT ;
2005-03-04 22:36:51 +03:00
err | = __get_user ( handler , & act - > sa_handler ) ;
2006-01-31 19:41:09 +03:00
new_ka . sa . sa_handler = ( void __user * ) ( s64 ) handler ;
2005-04-17 02:20:36 +04:00
err | = __get_user ( new_ka . sa . sa_flags , & act - > sa_flags ) ;
err | = __get_user ( mask , & act - > sa_mask . sig [ 0 ] ) ;
if ( err )
return - EFAULT ;
siginitset ( & new_ka . sa . sa_mask , mask ) ;
}
ret = do_sigaction ( sig , act ? & new_ka : NULL , oact ? & old_ka : NULL ) ;
if ( ! ret & & oact ) {
if ( ! access_ok ( VERIFY_WRITE , oact , sizeof ( * oact ) ) )
2006-02-18 23:06:32 +03:00
return - EFAULT ;
2005-04-17 02:20:36 +04:00
err | = __put_user ( old_ka . sa . sa_flags , & oact - > sa_flags ) ;
err | = __put_user ( ( u32 ) ( u64 ) old_ka . sa . sa_handler ,
2013-01-22 15:59:30 +04:00
& oact - > sa_handler ) ;
2005-04-17 02:20:36 +04:00
err | = __put_user ( old_ka . sa . sa_mask . sig [ 0 ] , oact - > sa_mask . sig ) ;
2006-02-18 23:06:32 +03:00
err | = __put_user ( 0 , & oact - > sa_mask . sig [ 1 ] ) ;
err | = __put_user ( 0 , & oact - > sa_mask . sig [ 2 ] ) ;
err | = __put_user ( 0 , & oact - > sa_mask . sig [ 3 ] ) ;
if ( err )
2005-04-17 02:20:36 +04:00
return - EFAULT ;
}
return ret ;
}
2013-10-14 01:23:53 +04:00
int copy_siginfo_to_user32 ( compat_siginfo_t __user * to , const siginfo_t * from )
2005-04-17 02:20:36 +04:00
{
int err ;
if ( ! access_ok ( VERIFY_WRITE , to , sizeof ( compat_siginfo_t ) ) )
return - EFAULT ;
/* 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 ) {
2005-02-17 00:24:16 +03:00
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 ;
2005-04-17 02:20:36 +04:00
case __SI_CHLD > > 16 :
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 ) ;
default :
err | = __put_user ( from - > si_pid , & to - > si_pid ) ;
err | = __put_user ( from - > si_uid , & to - > si_uid ) ;
break ;
case __SI_FAULT > > 16 :
2006-02-01 19:26:34 +03:00
err | = __put_user ( ( unsigned long ) from - > si_addr , & to - > si_addr ) ;
2005-04-17 02:20:36 +04:00
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_RT > > 16 : /* This is not generated by the kernel as of now. */
case __SI_MESGQ > > 16 :
err | = __put_user ( from - > si_pid , & to - > si_pid ) ;
err | = __put_user ( from - > si_uid , & to - > si_uid ) ;
err | = __put_user ( from - > si_int , & to - > si_int ) ;
break ;
2016-03-29 11:35:30 +03:00
case __SI_SYS > > 16 :
err | = __copy_to_user ( & to - > si_call_addr , & from - > si_call_addr ,
sizeof ( compat_uptr_t ) ) ;
err | = __put_user ( from - > si_syscall , & to - > si_syscall ) ;
err | = __put_user ( from - > si_arch , & to - > si_arch ) ;
break ;
2005-04-17 02:20:36 +04:00
}
}
return err ;
}
2008-08-17 18:49:25 +04:00
int copy_siginfo_from_user32 ( siginfo_t * to , compat_siginfo_t __user * from )
{
if ( copy_from_user ( to , from , 3 * sizeof ( int ) ) | |
copy_from_user ( to - > _sifields . _pad ,
from - > _sifields . _pad , SI_PAD_SIZE32 ) )
return - EFAULT ;
return 0 ;
}