2005-04-17 02:20:36 +04:00
/*
* Wrapper functions for 16 bit uid back compatibility . All nicely tied
* together in the faint hope we can take the out in five years time .
*/
# include <linux/mm.h>
# include <linux/mman.h>
# include <linux/notifier.h>
# include <linux/reboot.h>
# include <linux/prctl.h>
2006-01-11 23:17:46 +03:00
# include <linux/capability.h>
2005-04-17 02:20:36 +04:00
# include <linux/init.h>
# include <linux/highuid.h>
# include <linux/security.h>
# include <linux/syscalls.h>
# include <asm/uaccess.h>
2009-01-14 16:14:19 +03:00
SYSCALL_DEFINE3 ( chown16 , const char __user * , filename , old_uid_t , user , old_gid_t , group )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_chown ( filename , low2highuid ( user ) , low2highgid ( group ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 3 , ret , filename , user , group ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:19 +03:00
SYSCALL_DEFINE3 ( lchown16 , const char __user * , filename , old_uid_t , user , old_gid_t , group )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_lchown ( filename , low2highuid ( user ) , low2highgid ( group ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 3 , ret , filename , user , group ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:19 +03:00
SYSCALL_DEFINE3 ( fchown16 , unsigned int , fd , old_uid_t , user , old_gid_t , group )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_fchown ( fd , low2highuid ( user ) , low2highgid ( group ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 3 , ret , fd , user , group ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE2 ( setregid16 , old_gid_t , rgid , old_gid_t , egid )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_setregid ( low2highgid ( rgid ) , low2highgid ( egid ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 2 , ret , rgid , egid ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE1 ( setgid16 , old_gid_t , gid )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_setgid ( low2highgid ( gid ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 1 , ret , gid ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE2 ( setreuid16 , old_uid_t , ruid , old_uid_t , euid )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_setreuid ( low2highuid ( ruid ) , low2highuid ( euid ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 2 , ret , ruid , euid ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE1 ( setuid16 , old_uid_t , uid )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_setuid ( low2highuid ( uid ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 1 , ret , uid ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE3 ( setresuid16 , old_uid_t , ruid , old_uid_t , euid , old_uid_t , suid )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_setresuid ( low2highuid ( ruid ) , low2highuid ( euid ) ,
low2highuid ( suid ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 3 , ret , ruid , euid , suid ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE3 ( getresuid16 , old_uid_t __user * , ruid , old_uid_t __user * , euid , old_uid_t __user * , suid )
2005-04-17 02:20:36 +04:00
{
2008-11-14 02:39:18 +03:00
const struct cred * cred = current_cred ( ) ;
2005-04-17 02:20:36 +04:00
int retval ;
2008-11-14 02:39:18 +03:00
if ( ! ( retval = put_user ( high2lowuid ( cred - > uid ) , ruid ) ) & &
! ( retval = put_user ( high2lowuid ( cred - > euid ) , euid ) ) )
retval = put_user ( high2lowuid ( cred - > suid ) , suid ) ;
2005-04-17 02:20:36 +04:00
return retval ;
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE3 ( setresgid16 , old_gid_t , rgid , old_gid_t , egid , old_gid_t , sgid )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_setresgid ( low2highgid ( rgid ) , low2highgid ( egid ) ,
low2highgid ( sgid ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 3 , ret , rgid , egid , sgid ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE3 ( getresgid16 , old_gid_t __user * , rgid , old_gid_t __user * , egid , old_gid_t __user * , sgid )
2005-04-17 02:20:36 +04:00
{
2008-11-14 02:39:18 +03:00
const struct cred * cred = current_cred ( ) ;
2005-04-17 02:20:36 +04:00
int retval ;
2008-11-14 02:39:18 +03:00
if ( ! ( retval = put_user ( high2lowgid ( cred - > gid ) , rgid ) ) & &
! ( retval = put_user ( high2lowgid ( cred - > egid ) , egid ) ) )
retval = put_user ( high2lowgid ( cred - > sgid ) , sgid ) ;
2005-04-17 02:20:36 +04:00
return retval ;
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE1 ( setfsuid16 , old_uid_t , uid )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_setfsuid ( low2highuid ( uid ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 1 , ret , uid ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:20 +03:00
SYSCALL_DEFINE1 ( setfsgid16 , old_gid_t , gid )
2005-04-17 02:20:36 +04:00
{
2006-04-20 01:41:39 +04:00
long ret = sys_setfsgid ( low2highgid ( gid ) ) ;
/* avoid REGPARM breakage on x86: */
2008-04-11 02:37:38 +04:00
asmlinkage_protect ( 1 , ret , gid ) ;
2006-04-20 01:41:39 +04:00
return ret ;
2005-04-17 02:20:36 +04:00
}
static int groups16_to_user ( old_gid_t __user * grouplist ,
struct group_info * group_info )
{
int i ;
old_gid_t group ;
for ( i = 0 ; i < group_info - > ngroups ; i + + ) {
group = high2lowgid ( GROUP_AT ( group_info , i ) ) ;
if ( put_user ( group , grouplist + i ) )
return - EFAULT ;
}
return 0 ;
}
static int groups16_from_user ( struct group_info * group_info ,
old_gid_t __user * grouplist )
{
int i ;
old_gid_t group ;
for ( i = 0 ; i < group_info - > ngroups ; i + + ) {
if ( get_user ( group , grouplist + i ) )
return - EFAULT ;
GROUP_AT ( group_info , i ) = low2highgid ( group ) ;
}
return 0 ;
}
2009-01-14 16:14:21 +03:00
SYSCALL_DEFINE2 ( getgroups16 , int , gidsetsize , old_gid_t __user * , grouplist )
2005-04-17 02:20:36 +04:00
{
2008-11-14 02:39:18 +03:00
const struct cred * cred = current_cred ( ) ;
int i ;
2005-04-17 02:20:36 +04:00
if ( gidsetsize < 0 )
return - EINVAL ;
2008-11-14 02:39:18 +03:00
i = cred - > group_info - > ngroups ;
2005-04-17 02:20:36 +04:00
if ( gidsetsize ) {
if ( i > gidsetsize ) {
i = - EINVAL ;
goto out ;
}
2008-11-14 02:39:18 +03:00
if ( groups16_to_user ( grouplist , cred - > group_info ) ) {
2005-04-17 02:20:36 +04:00
i = - EFAULT ;
goto out ;
}
}
out :
return i ;
}
2009-01-14 16:14:21 +03:00
SYSCALL_DEFINE2 ( setgroups16 , int , gidsetsize , old_gid_t __user * , grouplist )
2005-04-17 02:20:36 +04:00
{
struct group_info * group_info ;
int retval ;
if ( ! capable ( CAP_SETGID ) )
return - EPERM ;
if ( ( unsigned ) gidsetsize > NGROUPS_MAX )
return - EINVAL ;
group_info = groups_alloc ( gidsetsize ) ;
if ( ! group_info )
return - ENOMEM ;
retval = groups16_from_user ( group_info , grouplist ) ;
if ( retval ) {
put_group_info ( group_info ) ;
return retval ;
}
retval = set_current_groups ( group_info ) ;
put_group_info ( group_info ) ;
return retval ;
}
2009-01-14 16:14:21 +03:00
SYSCALL_DEFINE0 ( getuid16 )
2005-04-17 02:20:36 +04:00
{
2008-11-14 02:39:18 +03:00
return high2lowuid ( current_uid ( ) ) ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:21 +03:00
SYSCALL_DEFINE0 ( geteuid16 )
2005-04-17 02:20:36 +04:00
{
2008-11-14 02:39:18 +03:00
return high2lowuid ( current_euid ( ) ) ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:21 +03:00
SYSCALL_DEFINE0 ( getgid16 )
2005-04-17 02:20:36 +04:00
{
2008-11-14 02:39:18 +03:00
return high2lowgid ( current_gid ( ) ) ;
2005-04-17 02:20:36 +04:00
}
2009-01-14 16:14:21 +03:00
SYSCALL_DEFINE0 ( getegid16 )
2005-04-17 02:20:36 +04:00
{
2008-11-14 02:39:18 +03:00
return high2lowgid ( current_egid ( ) ) ;
2005-04-17 02:20:36 +04:00
}