From 88d1da59e863386b492d9e330fbaa7d632093991 Mon Sep 17 00:00:00 2001 From: apio Date: Sat, 27 May 2023 12:04:27 +0200 Subject: [PATCH] kernel+libc: Add access() --- kernel/src/sys/stat.cpp | 31 +++++++++++++++++++++++++++++++ libc/include/bits/access.h | 12 ++++++++++++ libc/include/bits/atfile.h | 2 ++ libc/include/unistd.h | 10 ++++++++++ libc/src/unistd.cpp | 18 ++++++++++++++++++ libluna/include/luna/Syscall.h | 2 +- 6 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 libc/include/bits/access.h diff --git a/kernel/src/sys/stat.cpp b/kernel/src/sys/stat.cpp index 5d878d3f..85c534cd 100644 --- a/kernel/src/sys/stat.cpp +++ b/kernel/src/sys/stat.cpp @@ -1,6 +1,7 @@ #include "memory/MemoryManager.h" #include "sys/Syscall.h" #include "thread/Scheduler.h" +#include #include #include #include @@ -49,3 +50,33 @@ Result sys_fstatat(Registers*, SyscallArgs args) return 0; } + +Result sys_faccessat(Registers*, SyscallArgs args) +{ + int dirfd = (int)args[0]; + auto path = TRY(MemoryManager::strdup_from_user(args[1])); + int amode = (int)args[2]; + int flags = (int)args[3]; + + Credentials creds; + + auto* current = Scheduler::current(); + + if (flags & AT_EACCESS) creds = current->auth; + else + { + auto auth = current->auth; + creds.euid = auth.uid; + creds.egid = auth.gid; + } + + auto inode = TRY(current->resolve_atfile(dirfd, path, false, true)); + + if ((amode & R_OK) && !VFS::can_read(inode, creds)) return err(EACCES); + if ((amode & W_OK) && !VFS::can_write(inode, creds)) return err(EACCES); + if ((amode & X_OK) && !VFS::can_execute(inode, creds)) return err(EACCES); + + // Either all checks succeeded, or amode == F_OK and the file exists, since resolve_atfile() would have failed + // otherwise. + return 0; +} diff --git a/libc/include/bits/access.h b/libc/include/bits/access.h new file mode 100644 index 00000000..58000087 --- /dev/null +++ b/libc/include/bits/access.h @@ -0,0 +1,12 @@ +/* bits/access.h: Definitions for the access() function. */ + +#ifndef _BITS_ACCESS_H +#define _BITS_ACCESS_H + +#define R_OK 1 +#define W_OK 2 +#define X_OK 4 + +#define F_OK 0 + +#endif diff --git a/libc/include/bits/atfile.h b/libc/include/bits/atfile.h index 4511299e..92c1de62 100644 --- a/libc/include/bits/atfile.h +++ b/libc/include/bits/atfile.h @@ -10,4 +10,6 @@ #define AT_REMOVEDIR 1 +#define AT_EACCESS 1 + #endif diff --git a/libc/include/unistd.h b/libc/include/unistd.h index fd1be7f2..7dac09b3 100644 --- a/libc/include/unistd.h +++ b/libc/include/unistd.h @@ -6,6 +6,7 @@ #define __need_NULL #include +#include #include #include #include @@ -151,6 +152,15 @@ extern "C" /* Create a hard link relative to a file descriptor. */ int linkat(int olddirfd, const char* oldpath, int newdirfd, const char* newpath, int flags); + /* Check for a file's accessibility. */ + int access(const char* path, int amode); + + /* Check for a file's accessibility using the effective user and group IDs. */ + int eaccess(const char* path, int amode); + + /* Check for a file's accessibility relative to a file descriptor. */ + int faccessat(int dirfd, const char* path, int amode, int flags); + #ifdef __cplusplus } #endif diff --git a/libc/src/unistd.cpp b/libc/src/unistd.cpp index 14898410..9b871136 100644 --- a/libc/src/unistd.cpp +++ b/libc/src/unistd.cpp @@ -442,4 +442,22 @@ extern "C" long rc = syscall(SYS_linkat, olddirfd, oldpath, newdirfd, newpath, flags); __errno_return(rc, int); } + + int access(const char* path, int amode) + { + long rc = syscall(SYS_faccessat, AT_FDCWD, path, amode, 0); + __errno_return(rc, int); + } + + int eaccess(const char* path, int amode) + { + long rc = syscall(SYS_faccessat, AT_FDCWD, path, amode, AT_EACCESS); + __errno_return(rc, int); + } + + int faccessat(int dirfd, const char* path, int amode, int flags) + { + long rc = syscall(SYS_faccessat, dirfd, path, amode, flags); + __errno_return(rc, int); + } } diff --git a/libluna/include/luna/Syscall.h b/libluna/include/luna/Syscall.h index f9928f15..9f7f4284 100644 --- a/libluna/include/luna/Syscall.h +++ b/libluna/include/luna/Syscall.h @@ -5,7 +5,7 @@ _e(lseek) _e(mkdir) _e(execve) _e(fork) _e(waitpid) _e(getppid) _e(fcntl) _e(getdents) _e(getuid) _e(geteuid) \ _e(getgid) _e(getegid) _e(setuid) _e(setgid) _e(seteuid) _e(setegid) _e(fchmodat) _e(fchownat) _e(ioctl) \ _e(fstatat) _e(chdir) _e(getcwd) _e(unlinkat) _e(uname) _e(sethostname) _e(dup2) _e(pipe) _e(mount) \ - _e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) + _e(umount) _e(pstat) _e(getrusage) _e(symlinkat) _e(readlinkat) _e(umask) _e(linkat) _e(faccessat) enum Syscalls {