summaryrefslogtreecommitdiffstats
path: root/libc-top-half/musl/src/unistd/faccessat.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 13:54:38 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 13:54:38 +0000
commit8c1ab65c0f548d20b7f177bdb736daaf603340e1 (patch)
treedf55b7e75bf43f2bf500845b105afe3ac3a5157e /libc-top-half/musl/src/unistd/faccessat.c
parentInitial commit. (diff)
downloadwasi-libc-8c1ab65c0f548d20b7f177bdb736daaf603340e1.tar.xz
wasi-libc-8c1ab65c0f548d20b7f177bdb736daaf603340e1.zip
Adding upstream version 0.0~git20221206.8b7148f.upstream/0.0_git20221206.8b7148f
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'libc-top-half/musl/src/unistd/faccessat.c')
-rw-r--r--libc-top-half/musl/src/unistd/faccessat.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/unistd/faccessat.c b/libc-top-half/musl/src/unistd/faccessat.c
new file mode 100644
index 0000000..557503e
--- /dev/null
+++ b/libc-top-half/musl/src/unistd/faccessat.c
@@ -0,0 +1,61 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include "syscall.h"
+#include "pthread_impl.h"
+
+struct ctx {
+ int fd;
+ const char *filename;
+ int amode;
+ int p;
+};
+
+static int checker(void *p)
+{
+ struct ctx *c = p;
+ int ret;
+ 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;
+}
+
+int faccessat(int fd, const char *filename, int amode, int flag)
+{
+ if (flag) {
+ int ret = __syscall(SYS_faccessat2, fd, filename, amode, flag);
+ if (ret != -ENOSYS) return __syscall_ret(ret);
+ }
+
+ if (flag & ~AT_EACCESS)
+ return __syscall_ret(-EINVAL);
+
+ if (!flag || (getuid()==geteuid() && getgid()==getegid()))
+ return syscall(SYS_faccessat, fd, filename, amode);
+
+ 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] };
+
+ __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);
+
+ __restore_sigs(&set);
+
+ return __syscall_ret(ret);
+}