| OLD | NEW |
| 1 #include <unistd.h> | 1 #include <unistd.h> |
| 2 #include <fcntl.h> | 2 #include <fcntl.h> |
| 3 #include <errno.h> | 3 #include <errno.h> |
| 4 #include <sys/wait.h> | 4 #include <sys/wait.h> |
| 5 #include "syscall.h" | 5 #include "syscall.h" |
| 6 #include "pthread_impl.h" | 6 #include "pthread_impl.h" |
| 7 | 7 |
| 8 struct ctx { | 8 struct ctx { |
| 9 » int fd; | 9 int fd; |
| 10 » const char *filename; | 10 const char* filename; |
| 11 » int amode; | 11 int amode; |
| 12 }; | 12 }; |
| 13 | 13 |
| 14 static const int errors[] = { | 14 static const int errors[] = { |
| 15 » 0, -EACCES, -ELOOP, -ENAMETOOLONG, -ENOENT, -ENOTDIR, | 15 0, -EACCES, -ELOOP, -ENAMETOOLONG, -ENOENT, -ENOTDIR, -EROFS, |
| 16 » -EROFS, -EBADF, -EINVAL, -ETXTBSY, | 16 -EBADF, -EINVAL, -ETXTBSY, -EFAULT, -EIO, -ENOMEM, -EBUSY}; |
| 17 » -EFAULT, -EIO, -ENOMEM, | |
| 18 » -EBUSY | |
| 19 }; | |
| 20 | 17 |
| 21 static int checker(void *p) | 18 static int checker(void* p) { |
| 22 { | 19 struct ctx* c = p; |
| 23 » struct ctx *c = p; | 20 int ret; |
| 24 » int ret; | 21 int i; |
| 25 » int i; | 22 if (__syscall(SYS_setregid, __syscall(SYS_getegid), -1) || |
| 26 » if (__syscall(SYS_setregid, __syscall(SYS_getegid), -1) | 23 __syscall(SYS_setreuid, __syscall(SYS_geteuid), -1)) |
| 27 » || __syscall(SYS_setreuid, __syscall(SYS_geteuid), -1)) | 24 __syscall(SYS_exit, 1); |
| 28 » » __syscall(SYS_exit, 1); | 25 ret = __syscall(SYS_faccessat, c->fd, c->filename, c->amode, 0); |
| 29 » ret = __syscall(SYS_faccessat, c->fd, c->filename, c->amode, 0); | 26 for (i = 0; i < sizeof errors / sizeof *errors - 1 && ret != errors[i]; i++) |
| 30 » for (i=0; i < sizeof errors/sizeof *errors - 1 && ret!=errors[i]; i++); | 27 ; |
| 31 » return i; | 28 return i; |
| 32 } | 29 } |
| 33 | 30 |
| 34 int faccessat(int fd, const char *filename, int amode, int flag) | 31 int faccessat(int fd, const char* filename, int amode, int flag) { |
| 35 { | 32 if (!flag || |
| 36 » if (!flag || (flag==AT_EACCESS && getuid()==geteuid() && getgid()==geteg
id())) | 33 (flag == AT_EACCESS && getuid() == geteuid() && getgid() == getegid())) |
| 37 » » return syscall(SYS_faccessat, fd, filename, amode, flag); | 34 return syscall(SYS_faccessat, fd, filename, amode, flag); |
| 38 | 35 |
| 39 » if (flag != AT_EACCESS) | 36 if (flag != AT_EACCESS) |
| 40 » » return __syscall_ret(-EINVAL); | 37 return __syscall_ret(-EINVAL); |
| 41 | 38 |
| 42 » char stack[1024]; | 39 char stack[1024]; |
| 43 » sigset_t set; | 40 sigset_t set; |
| 44 » pid_t pid; | 41 pid_t pid; |
| 45 » int ret = -EBUSY; | 42 int ret = -EBUSY; |
| 46 » struct ctx c = { .fd = fd, .filename = filename, .amode = amode }; | 43 struct ctx c = {.fd = fd, .filename = filename, .amode = amode}; |
| 47 | 44 |
| 48 » __block_all_sigs(&set); | 45 __block_all_sigs(&set); |
| 49 » | |
| 50 » pid = __clone(checker, stack+sizeof stack, 0, &c); | |
| 51 » if (pid > 0) { | |
| 52 » » int status; | |
| 53 » » do { | |
| 54 » » » __syscall(SYS_wait4, pid, &status, __WCLONE, 0); | |
| 55 » » } while (!WIFEXITED(status) && !WIFSIGNALED(status)); | |
| 56 » » if (WIFEXITED(status)) | |
| 57 » » » ret = errors[WEXITSTATUS(status)]; | |
| 58 » } | |
| 59 | 46 |
| 60 » __restore_sigs(&set); | 47 pid = __clone(checker, stack + sizeof stack, 0, &c); |
| 48 if (pid > 0) { |
| 49 int status; |
| 50 do { |
| 51 __syscall(SYS_wait4, pid, &status, __WCLONE, 0); |
| 52 } while (!WIFEXITED(status) && !WIFSIGNALED(status)); |
| 53 if (WIFEXITED(status)) |
| 54 ret = errors[WEXITSTATUS(status)]; |
| 55 } |
| 61 | 56 |
| 62 » return __syscall_ret(ret); | 57 __restore_sigs(&set); |
| 58 |
| 59 return __syscall_ret(ret); |
| 63 } | 60 } |
| OLD | NEW |