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 |