github.com/afumu/libc@v0.0.6/musl/src/unistd/faccessat.c (about) 1 #include <unistd.h> 2 #include <fcntl.h> 3 #include <sys/wait.h> 4 #include "syscall.h" 5 #include "pthread_impl.h" 6 7 struct ctx { 8 int fd; 9 const char *filename; 10 int amode; 11 int p; 12 }; 13 14 static int checker(void *p) 15 { 16 struct ctx *c = p; 17 int ret; 18 if (__syscall(SYS_setregid, __syscall(SYS_getegid), -1) 19 || __syscall(SYS_setreuid, __syscall(SYS_geteuid), -1)) 20 __syscall(SYS_exit, 1); 21 ret = __syscall(SYS_faccessat, c->fd, c->filename, c->amode, 0); 22 __syscall(SYS_write, c->p, &ret, sizeof ret); 23 return 0; 24 } 25 26 int faccessat(int fd, const char *filename, int amode, int flag) 27 { 28 if (!flag || (flag==AT_EACCESS && getuid()==geteuid() && getgid()==getegid())) 29 return syscall(SYS_faccessat, fd, filename, amode, flag); 30 31 if (flag != AT_EACCESS) 32 return __syscall_ret(-EINVAL); 33 34 char stack[1024]; 35 sigset_t set; 36 pid_t pid; 37 int status; 38 int ret, p[2]; 39 40 if (pipe2(p, O_CLOEXEC)) return __syscall_ret(-EBUSY); 41 struct ctx c = { .fd = fd, .filename = filename, .amode = amode, .p = p[1] }; 42 43 __block_all_sigs(&set); 44 45 pid = __clone(checker, stack+sizeof stack, 0, &c); 46 __syscall(SYS_close, p[1]); 47 48 if (pid<0 || __syscall(SYS_read, p[0], &ret, sizeof ret) != sizeof(ret)) 49 ret = -EBUSY; 50 __syscall(SYS_close, p[0]); 51 __syscall(SYS_wait4, pid, &status, __WCLONE, 0); 52 53 __restore_sigs(&set); 54 55 return __syscall_ret(ret); 56 }