@ -1,5 +1,6 @@
# include <unistd.h>
# include <fcntl.h>
# include <errno.h>
# include <sys/wait.h>
# include "syscall.h"
# include "pthread_impl.h"
@ -8,19 +9,26 @@ struct ctx {
int fd ;
const char * filename ;
int amode ;
int p ;
} ;
static const int errors [ ] = {
0 , - EACCES , - ELOOP , - ENAMETOOLONG , - ENOENT , - ENOTDIR ,
- EROFS , - EBADF , - EINVAL , - ETXTBSY ,
- EFAULT , - EIO , - ENOMEM ,
- EBUSY
} ;
static int checker ( void * p )
{
struct ctx * c = p ;
int ret ;
int i ;
if ( __syscall ( SYS_setregid , __syscall ( SYS_getegid ) , - 1 )
| | __syscall ( SYS_setreuid , __syscall ( SYS_geteuid ) , - 1 ) )
__syscall ( SYS_exit , 1 ) ;
ret = __syscall ( SYS_faccessat , c - > fd , c - > filename , c - > amode , 0 ) ;
__syscall ( SYS_write , c - > p , & ret , sizeof ret ) ;
return 0 ;
for ( i = 0 ; i < sizeof errors / sizeof * errors - 1 & & ret ! = errors [ i ] ; i + + ) ;
return i ;
}
int faccessat ( int fd , const char * filename , int amode , int flag )
@ -34,21 +42,20 @@ int faccessat(int fd, const char *filename, int amode, int flag)
char stack [ 1024 ] ;
sigset_t set ;
pid_t pid ;
int status ;
int ret , p [ 2 ] ;
if ( pipe2 ( p , O_CLOEXEC ) ) return __syscall_ret ( - EBUSY ) ;
struct ctx c = { . fd = fd , . filename = filename , . amode = amode , . p = p [ 1 ] } ;
int ret = - EBUSY ;
struct ctx c = { . fd = fd , . filename = filename , . amode = amode } ;
__block_all_sigs ( & set ) ;
pid = __clone ( checker , stack + sizeof stack , 0 , & c ) ;
__syscall ( SYS_close , p [ 1 ] ) ;
if ( pid < 0 | | __syscall ( SYS_read , p [ 0 ] , & ret , sizeof ret ) ! = sizeof ( ret ) )
ret = - EBUSY ;
__syscall ( SYS_close , p [ 0 ] ) ;
__syscall ( SYS_wait4 , pid , & status , __WCLONE , 0 ) ;
if ( pid > 0 ) {
int status ;
do {
__syscall ( SYS_wait4 , pid , & status , __WCLONE , 0 ) ;
} while ( ! WIFEXITED ( status ) & & ! WIFSIGNALED ( status ) ) ;
if ( WIFEXITED ( status ) )
ret = errors [ WEXITSTATUS ( status ) ] ;
}
__restore_sigs ( & set ) ;