2009-08-05 10:50:03 +10:00
/*
2014-01-17 14:43:01 +01:00
* Copyright ( c ) 2009 Andrew Tridgell
* Copyright ( c ) 2011 - 2013 Andreas Schneider < asn @ samba . org >
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2009-08-05 10:50:03 +10:00
*/
2014-01-17 14:43:01 +01:00
# include "config.h"
2010-01-30 14:25:51 +01:00
2014-01-17 14:43:01 +01:00
# include <errno.h>
# include <stdarg.h>
# include <stdbool.h>
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <sys/types.h>
# include <unistd.h>
# include <grp.h>
# ifdef HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
# endif
# ifdef HAVE_SYSCALL_H
# include <syscall.h>
# endif
# include <dlfcn.h>
# include <pthread.h>
# ifdef HAVE_GCC_THREAD_LOCAL_STORAGE
# define UWRAP_THREAD __thread
# else
# define UWRAP_THREAD
# endif
2015-01-23 14:00:49 +01:00
# define UWRAP_LOCK(m) do { \
pthread_mutex_lock ( & ( m # # _mutex ) ) ; \
} while ( 0 )
# define UWRAP_UNLOCK(m) do { \
pthread_mutex_unlock ( & ( m # # _mutex ) ) ; \
} while ( 0 )
2015-01-23 15:10:02 +01:00
# ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
# define CONSTRUCTOR_ATTRIBUTE __attribute__ ((constructor))
# else
# define CONSTRUCTOR_ATTRIBUTE
# endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
2014-01-17 14:43:01 +01:00
# ifdef HAVE_DESTRUCTOR_ATTRIBUTE
# define DESTRUCTOR_ATTRIBUTE __attribute__ ((destructor))
# else
# define DESTRUCTOR_ATTRIBUTE
# endif /* HAVE_DESTRUCTOR_ATTRIBUTE */
2015-01-23 15:22:18 +01:00
# ifdef HAVE_ADDRESS_SANITIZER_ATTRIBUTE
# define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE __attribute__((no_sanitize_address))
# else /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
# define DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
# endif /* DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE */
2014-07-31 10:18:13 +02:00
/* GCC have printf type attribute check. */
# ifdef HAVE_FUNCTION_ATTRIBUTE_FORMAT
# define PRINTF_ATTRIBUTE(a,b) __attribute__ ((__format__ (__printf__, a, b)))
# else
# define PRINTF_ATTRIBUTE(a,b)
# endif /* HAVE_FUNCTION_ATTRIBUTE_FORMAT */
2014-01-17 14:43:01 +01:00
# define UWRAP_DLIST_ADD(list,item) do { \
if ( ! ( list ) ) { \
( item ) - > prev = NULL ; \
( item ) - > next = NULL ; \
( list ) = ( item ) ; \
} else { \
( item ) - > prev = NULL ; \
( item ) - > next = ( list ) ; \
( list ) - > prev = ( item ) ; \
( list ) = ( item ) ; \
} \
} while ( 0 )
2010-01-30 14:25:51 +01:00
2014-01-17 14:43:01 +01:00
# define UWRAP_DLIST_REMOVE(list,item) do { \
if ( ( list ) = = ( item ) ) { \
( list ) = ( item ) - > next ; \
if ( list ) { \
( list ) - > prev = NULL ; \
} \
} else { \
if ( ( item ) - > prev ) { \
( item ) - > prev - > next = ( item ) - > next ; \
} \
if ( ( item ) - > next ) { \
( item ) - > next - > prev = ( item ) - > prev ; \
} \
} \
( item ) - > prev = NULL ; \
( item ) - > next = NULL ; \
} while ( 0 )
# ifndef SAFE_FREE
# define SAFE_FREE(x) do { if ((x) != NULL) {free(x); (x)=NULL;} } while(0)
# endif
2010-01-30 14:25:51 +01:00
2014-07-31 10:18:59 +02:00
/*****************
* LOGGING
* * * * * * * * * * * * * * * * */
enum uwrap_dbglvl_e {
UWRAP_LOG_ERROR = 0 ,
UWRAP_LOG_WARN ,
UWRAP_LOG_DEBUG ,
UWRAP_LOG_TRACE
} ;
# ifdef NDEBUG
# define UWRAP_LOG(...)
# else /* NDEBUG */
static void uwrap_log ( enum uwrap_dbglvl_e dbglvl , const char * format , . . . ) PRINTF_ATTRIBUTE ( 2 , 3 ) ;
# define UWRAP_LOG(dbglvl, ...) uwrap_log((dbglvl), __VA_ARGS__)
static void uwrap_log ( enum uwrap_dbglvl_e dbglvl , const char * format , . . . )
{
char buffer [ 1024 ] ;
va_list va ;
const char * d ;
unsigned int lvl = 0 ;
d = getenv ( " UID_WRAPPER_DEBUGLEVEL " ) ;
if ( d ! = NULL ) {
lvl = atoi ( d ) ;
}
va_start ( va , format ) ;
vsnprintf ( buffer , sizeof ( buffer ) , format , va ) ;
va_end ( va ) ;
if ( lvl > = dbglvl ) {
switch ( dbglvl ) {
case UWRAP_LOG_ERROR :
fprintf ( stderr ,
" UWRAP_ERROR(%d): %s \n " ,
( int ) getpid ( ) , buffer ) ;
break ;
case UWRAP_LOG_WARN :
fprintf ( stderr ,
" UWRAP_WARN(%d): %s \n " ,
( int ) getpid ( ) , buffer ) ;
break ;
case UWRAP_LOG_DEBUG :
fprintf ( stderr ,
" UWRAP_DEBUG(%d): %s \n " ,
( int ) getpid ( ) , buffer ) ;
break ;
case UWRAP_LOG_TRACE :
fprintf ( stderr ,
" UWRAP_TRACE(%d): %s \n " ,
( int ) getpid ( ) , buffer ) ;
break ;
}
}
}
# endif /* NDEBUG */
/*****************
* LIBC
* * * * * * * * * * * * * * * * */
2014-01-17 14:43:01 +01:00
# define LIBC_NAME "libc.so"
2010-01-30 14:25:51 +01:00
2014-01-17 14:43:01 +01:00
struct uwrap_libc_fns {
int ( * _libc_setuid ) ( uid_t uid ) ;
uid_t ( * _libc_getuid ) ( void ) ;
# ifdef HAVE_SETEUID
int ( * _libc_seteuid ) ( uid_t euid ) ;
# endif
# ifdef HAVE_SETREUID
int ( * _libc_setreuid ) ( uid_t ruid , uid_t euid ) ;
# endif
# ifdef HAVE_SETRESUID
int ( * _libc_setresuid ) ( uid_t ruid , uid_t euid , uid_t suid ) ;
2010-01-30 14:25:51 +01:00
# endif
2014-01-17 14:43:01 +01:00
uid_t ( * _libc_geteuid ) ( void ) ;
2009-08-05 10:50:03 +10:00
2014-01-17 14:43:01 +01:00
int ( * _libc_setgid ) ( gid_t gid ) ;
gid_t ( * _libc_getgid ) ( void ) ;
# ifdef HAVE_SETEGID
int ( * _libc_setegid ) ( uid_t egid ) ;
# endif
# ifdef HAVE_SETREGID
int ( * _libc_setregid ) ( uid_t rgid , uid_t egid ) ;
# endif
# ifdef HAVE_SETRESGID
int ( * _libc_setresgid ) ( uid_t rgid , uid_t egid , uid_t sgid ) ;
# endif
gid_t ( * _libc_getegid ) ( void ) ;
int ( * _libc_getgroups ) ( int size , gid_t list [ ] ) ;
int ( * _libc_setgroups ) ( size_t size , const gid_t * list ) ;
# ifdef HAVE_SYSCALL
long int ( * _libc_syscall ) ( long int sysno , . . . ) ;
2009-08-05 10:50:03 +10:00
# endif
2014-01-17 14:43:01 +01:00
} ;
2009-08-05 10:50:03 +10:00
/*
2014-01-17 14:43:01 +01:00
* We keep the virtualised euid / egid / groups information here
2009-08-05 10:50:03 +10:00
*/
2014-01-17 14:43:01 +01:00
struct uwrap_thread {
pthread_t tid ;
bool dead ;
uid_t ruid ;
uid_t euid ;
uid_t suid ;
gid_t rgid ;
gid_t egid ;
gid_t sgid ;
gid_t * groups ;
int ngroups ;
struct uwrap_thread * next ;
struct uwrap_thread * prev ;
} ;
struct uwrap {
2015-01-23 15:24:39 +01:00
pthread_t tid ;
2014-01-17 14:43:01 +01:00
struct {
void * handle ;
struct uwrap_libc_fns fns ;
} libc ;
2009-08-05 10:50:03 +10:00
bool initialised ;
bool enabled ;
2014-01-17 14:43:01 +01:00
2015-01-23 15:16:34 +01:00
uid_t ruid ;
uid_t euid ;
uid_t suid ;
gid_t rgid ;
gid_t egid ;
gid_t sgid ;
/* Real uid and gid of user who run uid wrapper */
2011-10-07 18:58:58 +02:00
uid_t myuid ;
2015-01-23 15:16:34 +01:00
gid_t mygid ;
2014-01-17 14:43:01 +01:00
struct uwrap_thread * ids ;
} ;
static struct uwrap uwrap ;
/* Shortcut to the list item */
static UWRAP_THREAD struct uwrap_thread * uwrap_tls_id ;
/* The mutex or accessing the id */
static pthread_mutex_t uwrap_id_mutex = PTHREAD_MUTEX_INITIALIZER ;
2015-01-23 15:12:02 +01:00
/* The mutex for accessing the global libc.fns */
static pthread_mutex_t libc_symbol_binding_mutex = PTHREAD_MUTEX_INITIALIZER ;
2014-01-17 14:43:01 +01:00
/*********************************************************
* UWRAP PROTOTYPES
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
bool uid_wrapper_enabled ( void ) ;
2015-01-23 15:10:02 +01:00
void uwrap_constructor ( void ) CONSTRUCTOR_ATTRIBUTE ;
2014-01-17 14:43:01 +01:00
void uwrap_destructor ( void ) DESTRUCTOR_ATTRIBUTE ;
/*********************************************************
* UWRAP LIBC LOADER FUNCTIONS
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum uwrap_lib {
UWRAP_LIBC ,
UWRAP_LIBNSL ,
UWRAP_LIBSOCKET ,
} ;
static void * uwrap_load_lib_handle ( enum uwrap_lib lib )
{
int flags = RTLD_LAZY ;
void * handle = NULL ;
int i ;
# ifdef RTLD_DEEPBIND
flags | = RTLD_DEEPBIND ;
# endif
switch ( lib ) {
case UWRAP_LIBNSL :
/* FALL TROUGH */
case UWRAP_LIBSOCKET :
/* FALL TROUGH */
case UWRAP_LIBC :
handle = uwrap . libc . handle ;
if ( handle = = NULL ) {
2015-01-23 13:59:14 +01:00
for ( i = 10 ; i > = 0 ; i - - ) {
2014-01-17 14:43:01 +01:00
char soname [ 256 ] = { 0 } ;
snprintf ( soname , sizeof ( soname ) , " libc.so.%d " , i ) ;
handle = dlopen ( soname , flags ) ;
2015-01-23 13:59:14 +01:00
if ( handle ! = NULL ) {
break ;
}
2014-01-17 14:43:01 +01:00
}
uwrap . libc . handle = handle ;
}
break ;
}
if ( handle = = NULL ) {
2014-07-31 10:13:40 +02:00
# ifdef RTLD_NEXT
handle = uwrap . libc . handle = RTLD_NEXT ;
# else
2014-01-17 14:43:01 +01:00
fprintf ( stderr ,
" Failed to dlopen library: %s \n " ,
dlerror ( ) ) ;
exit ( - 1 ) ;
2014-07-31 10:13:40 +02:00
# endif
2014-01-17 14:43:01 +01:00
}
return handle ;
}
static void * _uwrap_load_lib_function ( enum uwrap_lib lib , const char * fn_name )
{
void * handle ;
void * func ;
handle = uwrap_load_lib_handle ( lib ) ;
func = dlsym ( handle , fn_name ) ;
if ( func = = NULL ) {
fprintf ( stderr ,
" Failed to find %s: %s \n " ,
fn_name , dlerror ( ) ) ;
exit ( - 1 ) ;
}
return func ;
}
# define uwrap_load_lib_function(lib, fn_name) \
2015-01-23 15:12:02 +01:00
UWRAP_LOCK ( libc_symbol_binding ) ; \
2014-01-17 14:43:01 +01:00
if ( uwrap . libc . fns . _libc_ # # fn_name = = NULL ) { \
* ( void * * ) ( & uwrap . libc . fns . _libc_ # # fn_name ) = \
_uwrap_load_lib_function ( lib , # fn_name ) ; \
2015-01-23 15:12:02 +01:00
} \
UWRAP_UNLOCK ( libc_symbol_binding )
2014-01-17 14:43:01 +01:00
/*
* IMPORTANT
*
* Functions expeciall from libc need to be loaded individually , you can ' t load
* all at once or gdb will segfault at startup . The same applies to valgrind and
* has probably something todo with with the linker .
* So we need load each function at the point it is called the first time .
*/
static int libc_setuid ( uid_t uid )
{
uwrap_load_lib_function ( UWRAP_LIBC , setuid ) ;
return uwrap . libc . fns . _libc_setuid ( uid ) ;
}
static uid_t libc_getuid ( void )
{
uwrap_load_lib_function ( UWRAP_LIBC , getuid ) ;
return uwrap . libc . fns . _libc_getuid ( ) ;
}
# ifdef HAVE_SETEUID
static int libc_seteuid ( uid_t euid )
{
uwrap_load_lib_function ( UWRAP_LIBC , seteuid ) ;
return uwrap . libc . fns . _libc_seteuid ( euid ) ;
}
# endif
# ifdef HAVE_SETREUID
static int libc_setreuid ( uid_t ruid , uid_t euid )
{
uwrap_load_lib_function ( UWRAP_LIBC , setreuid ) ;
return uwrap . libc . fns . _libc_setreuid ( ruid , euid ) ;
}
# endif
# ifdef HAVE_SETRESUID
static int libc_setresuid ( uid_t ruid , uid_t euid , uid_t suid )
{
uwrap_load_lib_function ( UWRAP_LIBC , setresuid ) ;
return uwrap . libc . fns . _libc_setresuid ( ruid , euid , suid ) ;
}
# endif
static uid_t libc_geteuid ( void )
{
uwrap_load_lib_function ( UWRAP_LIBC , geteuid ) ;
return uwrap . libc . fns . _libc_geteuid ( ) ;
}
static int libc_setgid ( gid_t gid )
{
uwrap_load_lib_function ( UWRAP_LIBC , setgid ) ;
return uwrap . libc . fns . _libc_setgid ( gid ) ;
}
static gid_t libc_getgid ( void )
{
uwrap_load_lib_function ( UWRAP_LIBC , getgid ) ;
return uwrap . libc . fns . _libc_getgid ( ) ;
}
# ifdef HAVE_SETEGID
static int libc_setegid ( gid_t egid )
{
uwrap_load_lib_function ( UWRAP_LIBC , setegid ) ;
return uwrap . libc . fns . _libc_setegid ( egid ) ;
}
# endif
# ifdef HAVE_SETREGID
static int libc_setregid ( gid_t rgid , gid_t egid )
{
uwrap_load_lib_function ( UWRAP_LIBC , setregid ) ;
return uwrap . libc . fns . _libc_setregid ( rgid , egid ) ;
}
# endif
# ifdef HAVE_SETRESGID
static int libc_setresgid ( gid_t rgid , gid_t egid , gid_t sgid )
{
uwrap_load_lib_function ( UWRAP_LIBC , setresgid ) ;
return uwrap . libc . fns . _libc_setresgid ( rgid , egid , sgid ) ;
}
# endif
static gid_t libc_getegid ( void )
{
uwrap_load_lib_function ( UWRAP_LIBC , getegid ) ;
return uwrap . libc . fns . _libc_getegid ( ) ;
}
static int libc_getgroups ( int size , gid_t list [ ] )
{
uwrap_load_lib_function ( UWRAP_LIBC , getgroups ) ;
return uwrap . libc . fns . _libc_getgroups ( size , list ) ;
}
static int libc_setgroups ( size_t size , const gid_t * list )
{
uwrap_load_lib_function ( UWRAP_LIBC , setgroups ) ;
return uwrap . libc . fns . _libc_setgroups ( size , list ) ;
}
# ifdef HAVE_SYSCALL
2015-01-23 15:22:18 +01:00
DO_NOT_SANITIZE_ADDRESS_ATTRIBUTE
2014-01-17 14:43:01 +01:00
static long int libc_vsyscall ( long int sysno , va_list va )
{
long int args [ 8 ] ;
long int rc ;
int i ;
uwrap_load_lib_function ( UWRAP_LIBC , syscall ) ;
for ( i = 0 ; i < 8 ; i + + ) {
args [ i ] = va_arg ( va , long int ) ;
}
rc = uwrap . libc . fns . _libc_syscall ( sysno ,
args [ 0 ] ,
args [ 1 ] ,
args [ 2 ] ,
args [ 3 ] ,
args [ 4 ] ,
args [ 5 ] ,
args [ 6 ] ,
args [ 7 ] ) ;
return rc ;
}
# endif
/*********************************************************
* UWRAP ID HANDLING
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static struct uwrap_thread * find_uwrap_id ( pthread_t tid )
{
struct uwrap_thread * id ;
for ( id = uwrap . ids ; id ; id = id - > next ) {
if ( pthread_equal ( id - > tid , tid ) ) {
return id ;
}
}
return NULL ;
}
static int uwrap_new_id ( pthread_t tid , bool do_alloc )
{
struct uwrap_thread * id = uwrap_tls_id ;
if ( do_alloc ) {
id = malloc ( sizeof ( struct uwrap_thread ) ) ;
if ( id = = NULL ) {
2014-07-31 10:19:28 +02:00
UWRAP_LOG ( UWRAP_LOG_ERROR , " Unable to allocate memory " ) ;
2014-01-17 14:43:01 +01:00
errno = ENOMEM ;
return - 1 ;
}
id - > groups = malloc ( sizeof ( gid_t ) * 1 ) ;
if ( id - > groups = = NULL ) {
2014-07-31 10:19:28 +02:00
UWRAP_LOG ( UWRAP_LOG_ERROR , " Unable to allocate memory " ) ;
2014-07-31 10:12:15 +02:00
SAFE_FREE ( id ) ;
2014-01-17 14:43:01 +01:00
errno = ENOMEM ;
return - 1 ;
}
UWRAP_DLIST_ADD ( uwrap . ids , id ) ;
uwrap_tls_id = id ;
}
id - > tid = tid ;
id - > dead = false ;
2015-01-23 15:16:34 +01:00
id - > ruid = uwrap . ruid ;
id - > euid = uwrap . euid ;
id - > suid = uwrap . suid ;
id - > rgid = uwrap . rgid ;
id - > egid = uwrap . egid ;
id - > sgid = uwrap . sgid ;
2014-01-17 14:43:01 +01:00
id - > ngroups = 1 ;
id - > groups [ 0 ] = uwrap . mygid ;
return 0 ;
}
static void uwrap_thread_prepare ( void )
{
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2015-01-23 15:12:02 +01:00
UWRAP_LOCK ( libc_symbol_binding ) ;
2014-01-17 14:43:01 +01:00
/*
* What happens if another atfork prepare functions calls a uwrap
* function ? So disable it in case another atfork prepare function
* calls a ( s ) uid function .
*/
uwrap . enabled = false ;
}
static void uwrap_thread_parent ( void )
{
uwrap . enabled = true ;
2015-01-23 15:12:02 +01:00
UWRAP_UNLOCK ( libc_symbol_binding ) ;
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
}
static void uwrap_thread_child ( void )
{
uwrap . enabled = true ;
2015-01-23 15:24:39 +01:00
/* We need to update to the new tid if we fork */
uwrap . tid = pthread_self ( ) ;
2015-01-23 15:12:02 +01:00
UWRAP_UNLOCK ( libc_symbol_binding ) ;
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
}
2009-08-05 10:50:03 +10:00
static void uwrap_init ( void )
{
2015-01-23 15:15:42 +01:00
const char * env ;
2014-01-17 14:43:01 +01:00
pthread_t tid = pthread_self ( ) ;
2015-01-23 15:12:43 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
if ( uwrap . initialised ) {
struct uwrap_thread * id = uwrap_tls_id ;
int rc ;
if ( id ! = NULL ) {
2015-01-23 15:12:43 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
return ;
}
id = find_uwrap_id ( tid ) ;
if ( id = = NULL ) {
rc = uwrap_new_id ( tid , true ) ;
if ( rc < 0 ) {
exit ( - 1 ) ;
}
} else {
/* We reuse an old thread id */
uwrap_tls_id = id ;
uwrap_new_id ( tid , false ) ;
}
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
return ;
}
2014-07-31 10:19:58 +02:00
UWRAP_LOG ( UWRAP_LOG_DEBUG , " Initialize uid_wrapper " ) ;
2009-08-05 10:50:03 +10:00
uwrap . initialised = true ;
2014-01-17 14:43:01 +01:00
uwrap . enabled = false ;
2015-01-23 15:15:42 +01:00
env = getenv ( " UID_WRAPPER " ) ;
2014-01-17 14:43:01 +01:00
if ( env ! = NULL & & env [ 0 ] = = ' 1 ' ) {
const char * root = getenv ( " UID_WRAPPER_ROOT " ) ;
int rc ;
2015-01-23 15:16:34 +01:00
uwrap . myuid = libc_geteuid ( ) ;
uwrap . mygid = libc_getegid ( ) ;
2009-08-05 13:31:06 +10:00
/* put us in one group */
2014-01-17 14:43:01 +01:00
if ( root ! = NULL & & root [ 0 ] = = ' 1 ' ) {
2015-01-23 15:16:34 +01:00
uwrap . ruid = uwrap . euid = uwrap . suid = 0 ;
uwrap . rgid = uwrap . egid = uwrap . sgid = 0 ;
2014-01-17 14:43:01 +01:00
} else {
2015-01-23 15:24:04 +01:00
uwrap . ruid = uwrap . euid = uwrap . suid = uwrap . myuid ;
uwrap . rgid = uwrap . egid = uwrap . sgid = uwrap . mygid ;
2014-01-17 14:43:01 +01:00
}
rc = uwrap_new_id ( tid , true ) ;
if ( rc < 0 ) {
exit ( - 1 ) ;
}
2015-01-23 15:24:39 +01:00
uwrap . tid = tid ;
2014-01-17 14:43:01 +01:00
uwrap . enabled = true ;
2014-07-31 10:19:58 +02:00
UWRAP_LOG ( UWRAP_LOG_DEBUG ,
" Enabled uid_wrapper as %s " ,
uwrap . myuid = = 0 ? " root " : " user " ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-07-31 10:19:58 +02:00
UWRAP_LOG ( UWRAP_LOG_DEBUG , " Succeccfully initialized uid_wrapper " ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
bool uid_wrapper_enabled ( void )
2009-08-05 11:21:06 +10:00
{
2015-01-23 15:15:04 +01:00
bool enabled = false ;
# ifdef HAVE_GCC_ATOMIC_BUILTINS
__atomic_load ( & uwrap . enabled , & enabled , __ATOMIC_RELAXED ) ;
# else
UWRAP_LOCK ( uwrap_id ) ;
enabled = uwrap . enabled ;
UWRAP_UNLOCK ( uwrap_id ) ;
# endif
return enabled ;
2009-08-05 11:21:06 +10:00
}
2014-01-17 14:43:01 +01:00
static int uwrap_setresuid_thread ( uid_t ruid , uid_t euid , uid_t suid )
2009-08-05 10:50:03 +10:00
{
2014-01-17 14:43:01 +01:00
struct uwrap_thread * id = uwrap_tls_id ;
if ( ruid = = ( uid_t ) - 1 & & euid = = ( uid_t ) - 1 & & suid = = ( uid_t ) - 1 ) {
errno = EINVAL ;
return - 1 ;
}
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
if ( ruid ! = ( uid_t ) - 1 ) {
id - > ruid = ruid ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
if ( euid ! = ( uid_t ) - 1 ) {
id - > euid = euid ;
2011-10-07 18:58:58 +02:00
}
2014-01-17 14:43:01 +01:00
if ( suid ! = ( uid_t ) - 1 ) {
id - > suid = suid ;
}
2015-01-23 15:24:39 +01:00
/* Check If syscall is called from main thread. */
if ( pthread_equal ( id - > tid , uwrap . tid ) ) {
if ( ruid ! = ( uid_t ) - 1 ) {
uwrap . ruid = ruid ;
}
if ( euid ! = ( uid_t ) - 1 ) {
uwrap . euid = euid ;
}
if ( suid ! = ( uid_t ) - 1 ) {
uwrap . suid = suid ;
}
}
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
2009-08-05 10:50:03 +10:00
return 0 ;
}
2014-01-17 14:43:01 +01:00
static int uwrap_setresuid ( uid_t ruid , uid_t euid , uid_t suid )
{
struct uwrap_thread * id ;
if ( ruid = = ( uid_t ) - 1 & & euid = = ( uid_t ) - 1 & & suid = = ( uid_t ) - 1 ) {
errno = EINVAL ;
return - 1 ;
}
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
for ( id = uwrap . ids ; id ; id = id - > next ) {
if ( id - > dead ) {
continue ;
}
if ( ruid ! = ( uid_t ) - 1 ) {
id - > ruid = ruid ;
}
if ( euid ! = ( uid_t ) - 1 ) {
id - > euid = euid ;
}
if ( suid ! = ( uid_t ) - 1 ) {
id - > suid = suid ;
}
}
2015-01-23 15:16:34 +01:00
/* Reflect changes in thread to main process. */
if ( ruid ! = ( uid_t ) - 1 ) {
uwrap . ruid = ruid ;
}
if ( euid ! = ( uid_t ) - 1 ) {
uwrap . euid = euid ;
}
if ( suid ! = ( uid_t ) - 1 ) {
uwrap . suid = suid ;
}
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
return 0 ;
}
/*
* SETUID
*/
int setuid ( uid_t uid )
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_setuid ( uid ) ;
}
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setresuid ( uid , - 1 , - 1 ) ;
}
# ifdef HAVE_SETEUID
int seteuid ( uid_t euid )
{
if ( euid = = ( uid_t ) - 1 ) {
errno = EINVAL ;
return - 1 ;
}
if ( ! uid_wrapper_enabled ( ) ) {
return libc_seteuid ( euid ) ;
}
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setresuid ( - 1 , euid , - 1 ) ;
}
2011-10-08 10:08:37 +02:00
# endif
2009-08-05 10:50:03 +10:00
2011-10-08 10:08:37 +02:00
# ifdef HAVE_SETREUID
2014-01-17 14:43:01 +01:00
int setreuid ( uid_t ruid , uid_t euid )
2011-10-06 16:25:32 +02:00
{
2014-01-17 14:43:01 +01:00
if ( ruid = = ( uid_t ) - 1 & & euid = = ( uid_t ) - 1 ) {
errno = EINVAL ;
return - 1 ;
2011-10-06 16:25:32 +02:00
}
2014-01-17 14:43:01 +01:00
if ( ! uid_wrapper_enabled ( ) ) {
return libc_setreuid ( ruid , euid ) ;
2011-10-07 18:58:58 +02:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setresuid ( ruid , euid , - 1 ) ;
2011-10-06 16:25:32 +02:00
}
2011-10-08 10:08:37 +02:00
# endif
2011-10-06 16:25:32 +02:00
2011-10-08 10:08:37 +02:00
# ifdef HAVE_SETRESUID
2014-01-17 14:43:01 +01:00
int setresuid ( uid_t ruid , uid_t euid , uid_t suid )
2011-10-07 10:30:23 +02:00
{
2014-01-17 14:43:01 +01:00
if ( ! uid_wrapper_enabled ( ) ) {
return libc_setresuid ( ruid , euid , suid ) ;
2011-10-07 18:58:58 +02:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setresuid ( ruid , euid , suid ) ;
2011-10-07 10:30:23 +02:00
}
2011-10-08 10:08:37 +02:00
# endif
2011-10-07 10:30:23 +02:00
2014-01-17 14:43:01 +01:00
/*
* GETUID
*/
static uid_t uwrap_getuid ( void )
2009-08-05 10:50:03 +10:00
{
2014-01-17 14:43:01 +01:00
struct uwrap_thread * id = uwrap_tls_id ;
uid_t uid ;
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
uid = id - > ruid ;
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
return uid ;
}
uid_t getuid ( void )
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_getuid ( ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_getuid ( ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
/*
* GETEUID
*/
static uid_t uwrap_geteuid ( void )
2009-08-05 10:50:03 +10:00
{
2014-01-17 14:43:01 +01:00
const char * env = getenv ( " UID_WRAPPER_MYUID " ) ;
struct uwrap_thread * id = uwrap_tls_id ;
uid_t uid ;
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
uid = id - > euid ;
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
/* Disable root and return myuid */
if ( env ! = NULL & & env [ 0 ] = = ' 1 ' ) {
uid = uwrap . myuid ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
return uid ;
}
uid_t geteuid ( void )
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_geteuid ( ) ;
2011-10-07 18:58:58 +02:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_geteuid ( ) ;
}
static int uwrap_setresgid_thread ( gid_t rgid , gid_t egid , gid_t sgid )
{
struct uwrap_thread * id = uwrap_tls_id ;
if ( rgid = = ( gid_t ) - 1 & & egid = = ( gid_t ) - 1 & & sgid = = ( gid_t ) - 1 ) {
errno = EINVAL ;
return - 1 ;
}
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
if ( rgid ! = ( gid_t ) - 1 ) {
id - > rgid = rgid ;
}
if ( egid ! = ( gid_t ) - 1 ) {
id - > egid = egid ;
}
if ( sgid ! = ( gid_t ) - 1 ) {
id - > sgid = sgid ;
}
2015-01-23 15:24:39 +01:00
if ( pthread_equal ( id - > tid , uwrap . tid ) ) {
if ( rgid ! = ( gid_t ) - 1 ) {
uwrap . rgid = rgid ;
}
if ( egid ! = ( gid_t ) - 1 ) {
uwrap . egid = egid ;
}
if ( sgid ! = ( gid_t ) - 1 ) {
uwrap . sgid = sgid ;
}
}
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
2009-08-05 10:50:03 +10:00
return 0 ;
}
2014-01-17 14:43:01 +01:00
static int uwrap_setresgid ( gid_t rgid , gid_t egid , gid_t sgid )
2011-10-06 16:52:03 +02:00
{
2014-01-17 14:43:01 +01:00
struct uwrap_thread * id ;
if ( rgid = = ( gid_t ) - 1 & & egid = = ( gid_t ) - 1 & & sgid = = ( gid_t ) - 1 ) {
errno = EINVAL ;
return - 1 ;
2011-10-06 16:52:03 +02:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
for ( id = uwrap . ids ; id ; id = id - > next ) {
if ( id - > dead ) {
continue ;
}
if ( rgid ! = ( gid_t ) - 1 ) {
id - > rgid = rgid ;
}
if ( egid ! = ( gid_t ) - 1 ) {
id - > egid = egid ;
}
if ( sgid ! = ( gid_t ) - 1 ) {
id - > sgid = sgid ;
}
2011-10-07 18:58:58 +02:00
}
2015-01-23 15:16:34 +01:00
/* Reflect changes in thread to main process. */
if ( rgid ! = ( gid_t ) - 1 ) {
uwrap . rgid = rgid ;
}
if ( egid ! = ( gid_t ) - 1 ) {
uwrap . egid = egid ;
}
if ( sgid ! = ( gid_t ) - 1 ) {
uwrap . sgid = sgid ;
}
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
2011-10-06 16:52:03 +02:00
return 0 ;
}
2014-01-17 14:43:01 +01:00
/*
* SETGID
*/
int setgid ( gid_t gid )
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_setgid ( gid ) ;
}
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setresgid ( gid , - 1 , - 1 ) ;
}
# ifdef HAVE_SETEGID
int setegid ( gid_t egid )
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_setegid ( egid ) ;
}
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setresgid ( - 1 , egid , - 1 ) ;
}
2011-10-08 10:08:37 +02:00
# endif
2011-10-06 16:52:03 +02:00
2014-01-17 14:43:01 +01:00
# ifdef HAVE_SETREGID
int setregid ( gid_t rgid , gid_t egid )
2011-10-08 10:52:02 +02:00
{
2014-01-17 14:43:01 +01:00
if ( ! uid_wrapper_enabled ( ) ) {
return libc_setregid ( rgid , egid ) ;
2011-10-08 10:52:02 +02:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setresgid ( rgid , egid , - 1 ) ;
}
# endif
# ifdef HAVE_SETRESGID
int setresgid ( gid_t rgid , gid_t egid , gid_t sgid )
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_setresgid ( rgid , egid , sgid ) ;
2011-10-08 10:52:02 +02:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setresgid ( rgid , egid , sgid ) ;
2011-10-08 10:52:02 +02:00
}
# endif
2014-01-17 14:43:01 +01:00
/*
* GETGID
*/
static gid_t uwrap_getgid ( void )
2009-08-05 10:50:03 +10:00
{
2014-01-17 14:43:01 +01:00
struct uwrap_thread * id = uwrap_tls_id ;
gid_t gid ;
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
gid = id - > rgid ;
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
return gid ;
}
gid_t getgid ( void )
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_getgid ( ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_getgid ( ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
/*
* GETEGID
*/
static uid_t uwrap_getegid ( void )
2009-08-05 10:50:03 +10:00
{
2014-01-17 14:43:01 +01:00
struct uwrap_thread * id = uwrap_tls_id ;
gid_t gid ;
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
gid = id - > egid ;
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
return gid ;
}
uid_t getegid ( void )
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_getegid ( ) ;
2009-08-05 10:50:03 +10:00
}
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_getegid ( ) ;
}
static int uwrap_setgroups_thread ( size_t size , const gid_t * list )
{
struct uwrap_thread * id = uwrap_tls_id ;
int rc = - 1 ;
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
2014-07-31 10:20:40 +02:00
if ( size = = 0 ) {
free ( id - > groups ) ;
id - > groups = NULL ;
id - > ngroups = 0 ;
} else if ( size > 0 ) {
2014-01-17 14:43:01 +01:00
gid_t * tmp ;
2009-08-05 13:31:06 +10:00
2014-01-17 14:43:01 +01:00
tmp = realloc ( id - > groups , sizeof ( gid_t ) * size ) ;
if ( tmp = = NULL ) {
2009-08-05 13:31:06 +10:00
errno = ENOMEM ;
2014-01-17 14:43:01 +01:00
goto out ;
2009-08-05 13:31:06 +10:00
}
2014-01-17 14:43:01 +01:00
id - > groups = tmp ;
id - > ngroups = size ;
memcpy ( id - > groups , list , size * sizeof ( gid_t ) ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
rc = 0 ;
out :
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
return rc ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
static int uwrap_setgroups ( size_t size , const gid_t * list )
2009-08-05 10:50:03 +10:00
{
2014-01-17 14:43:01 +01:00
struct uwrap_thread * id ;
int rc = - 1 ;
2011-02-19 23:21:07 +01:00
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
2014-07-31 10:20:40 +02:00
if ( size = = 0 ) {
for ( id = uwrap . ids ; id ; id = id - > next ) {
free ( id - > groups ) ;
id - > groups = NULL ;
id - > ngroups = 0 ;
}
} else if ( size > 0 ) {
2014-01-17 14:43:01 +01:00
for ( id = uwrap . ids ; id ; id = id - > next ) {
gid_t * tmp ;
tmp = realloc ( id - > groups , sizeof ( gid_t ) * size ) ;
if ( tmp = = NULL ) {
errno = ENOMEM ;
goto out ;
}
id - > groups = tmp ;
id - > ngroups = size ;
memcpy ( id - > groups , list , size * sizeof ( gid_t ) ) ;
}
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
rc = 0 ;
out :
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
return rc ;
}
# ifdef HAVE_SETGROUPS_INT
int setgroups ( int size , const gid_t * list )
# else
int setgroups ( size_t size , const gid_t * list )
# endif
{
if ( ! uid_wrapper_enabled ( ) ) {
return libc_setgroups ( size , list ) ;
}
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_setgroups ( size , list ) ;
}
static int uwrap_getgroups ( int size , gid_t * list )
{
struct uwrap_thread * id = uwrap_tls_id ;
int ngroups ;
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
ngroups = id - > ngroups ;
2011-02-19 23:21:07 +01:00
if ( size > ngroups ) {
size = ngroups ;
2009-08-05 10:50:03 +10:00
}
if ( size = = 0 ) {
2014-01-17 14:43:01 +01:00
goto out ;
2009-08-05 10:50:03 +10:00
}
2011-02-19 23:21:07 +01:00
if ( size < ngroups ) {
2009-08-05 10:50:03 +10:00
errno = EINVAL ;
2014-01-17 14:43:01 +01:00
ngroups = - 1 ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
memcpy ( list , id - > groups , size * sizeof ( gid_t ) ) ;
out :
2015-01-23 14:00:49 +01:00
UWRAP_UNLOCK ( uwrap_id ) ;
2014-01-17 14:43:01 +01:00
2011-02-19 23:21:07 +01:00
return ngroups ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
int getgroups ( int size , gid_t * list )
2009-08-05 10:50:03 +10:00
{
2014-01-17 14:43:01 +01:00
if ( ! uid_wrapper_enabled ( ) ) {
return libc_getgroups ( size , list ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
return uwrap_getgroups ( size , list ) ;
2009-08-05 10:50:03 +10:00
}
2014-01-17 14:43:01 +01:00
# if (defined(HAVE_SYS_SYSCALL_H) || defined(HAVE_SYSCALL_H)) \
& & ( defined ( SYS_setreuid ) | | defined ( SYS_setreuid32 ) )
static long int uwrap_syscall ( long int sysno , va_list vp )
2009-08-05 10:50:03 +10:00
{
2014-01-17 14:43:01 +01:00
long int rc ;
switch ( sysno ) {
/* gid */
case SYS_getgid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_getgid32 :
# endif
{
rc = uwrap_getgid ( ) ;
}
break ;
# ifdef SYS_getegid
case SYS_getegid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_getegid32 :
# endif
{
rc = uwrap_getegid ( ) ;
}
break ;
# endif /* SYS_getegid */
case SYS_setgid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_setgid32 :
# endif
{
gid_t gid = ( gid_t ) va_arg ( vp , int ) ;
rc = uwrap_setresgid_thread ( gid , - 1 , - 1 ) ;
}
break ;
case SYS_setregid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_setregid32 :
# endif
{
uid_t rgid = ( uid_t ) va_arg ( vp , int ) ;
uid_t egid = ( uid_t ) va_arg ( vp , int ) ;
rc = uwrap_setresgid_thread ( rgid , egid , - 1 ) ;
}
break ;
# ifdef SYS_setresgid
case SYS_setresgid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_setresgid32 :
# endif
{
uid_t rgid = ( uid_t ) va_arg ( vp , int ) ;
uid_t egid = ( uid_t ) va_arg ( vp , int ) ;
uid_t sgid = ( uid_t ) va_arg ( vp , int ) ;
rc = uwrap_setresgid_thread ( rgid , egid , sgid ) ;
}
break ;
# endif /* SYS_setresgid */
/* uid */
case SYS_getuid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_getuid32 :
# endif
{
rc = uwrap_getuid ( ) ;
}
break ;
# ifdef SYS_geteuid
case SYS_geteuid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_geteuid32 :
# endif
{
rc = uwrap_geteuid ( ) ;
}
break ;
# endif /* SYS_geteuid */
case SYS_setuid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_setuid32 :
# endif
{
uid_t uid = ( uid_t ) va_arg ( vp , int ) ;
rc = uwrap_setresuid_thread ( uid , - 1 , - 1 ) ;
}
break ;
case SYS_setreuid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_setreuid32 :
# endif
{
uid_t ruid = ( uid_t ) va_arg ( vp , int ) ;
uid_t euid = ( uid_t ) va_arg ( vp , int ) ;
rc = uwrap_setresuid_thread ( ruid , euid , - 1 ) ;
}
break ;
# ifdef SYS_setresuid
case SYS_setresuid :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_setresuid32 :
# endif
{
uid_t ruid = ( uid_t ) va_arg ( vp , int ) ;
uid_t euid = ( uid_t ) va_arg ( vp , int ) ;
uid_t suid = ( uid_t ) va_arg ( vp , int ) ;
rc = uwrap_setresuid_thread ( ruid , euid , suid ) ;
}
break ;
# endif /* SYS_setresuid */
/* groups */
case SYS_setgroups :
# ifdef HAVE_LINUX_32BIT_SYSCALLS
case SYS_setgroups32 :
# endif
{
size_t size = ( size_t ) va_arg ( vp , size_t ) ;
gid_t * list = ( gid_t * ) va_arg ( vp , int * ) ;
rc = uwrap_setgroups_thread ( size , list ) ;
}
break ;
default :
2014-07-31 10:18:59 +02:00
UWRAP_LOG ( UWRAP_LOG_DEBUG ,
" UID_WRAPPER calling non-wrapped syscall %lu \n " ,
sysno ) ;
2014-01-17 14:43:01 +01:00
rc = libc_vsyscall ( sysno , vp ) ;
break ;
}
return rc ;
}
# ifdef HAVE_SYSCALL
# ifdef HAVE_SYSCALL_INT
int syscall ( int sysno , . . . )
# else
long int syscall ( long int sysno , . . . )
# endif
{
# ifdef HAVE_SYSCALL_INT
int rc ;
# else
long int rc ;
# endif
va_list va ;
va_start ( va , sysno ) ;
if ( ! uid_wrapper_enabled ( ) ) {
rc = libc_vsyscall ( sysno , va ) ;
va_end ( va ) ;
return rc ;
}
2015-01-23 15:15:04 +01:00
uwrap_init ( ) ;
2014-01-17 14:43:01 +01:00
rc = uwrap_syscall ( sysno , va ) ;
va_end ( va ) ;
return rc ;
}
# endif /* HAVE_SYSCALL */
# endif /* HAVE_SYS_SYSCALL_H || HAVE_SYSCALL_H */
2015-01-23 15:10:02 +01:00
/****************************
* CONSTRUCTOR
* * * * * * * * * * * * * * * * * * * * * * * * * * */
void uwrap_constructor ( void )
{
/*
* If we hold a lock and the application forks , then the child
* is not able to unlock the mutex and we are in a deadlock .
* This should prevent such deadlocks .
*/
pthread_atfork ( & uwrap_thread_prepare ,
& uwrap_thread_parent ,
& uwrap_thread_child ) ;
2015-01-23 15:15:04 +01:00
/* Here is safe place to call uwrap_init() and initialize data
* for main process .
*/
uwrap_init ( ) ;
2015-01-23 15:10:02 +01:00
}
2014-01-17 14:43:01 +01:00
/****************************
* DESTRUCTOR
* * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* This function is called when the library is unloaded and makes sure that
* resources are freed .
*/
void uwrap_destructor ( void )
{
struct uwrap_thread * u = uwrap . ids ;
2015-01-23 14:00:49 +01:00
UWRAP_LOCK ( uwrap_id ) ;
2015-01-23 15:12:02 +01:00
UWRAP_LOCK ( libc_symbol_binding ) ;
2014-01-17 14:43:01 +01:00
while ( u ! = NULL ) {
UWRAP_DLIST_REMOVE ( uwrap . ids , u ) ;
SAFE_FREE ( u - > groups ) ;
SAFE_FREE ( u ) ;
u = uwrap . ids ;
}
if ( uwrap . libc . handle ! = NULL ) {
dlclose ( uwrap . libc . handle ) ;
2009-08-05 10:50:03 +10:00
}
2015-01-23 15:12:02 +01:00
UWRAP_UNLOCK ( libc_symbol_binding ) ;
UWRAP_UNLOCK ( uwrap_id ) ;
2009-08-05 10:50:03 +10:00
}