mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-29 16:21:29 +00:00
Kernel+LibC+LibCore+UserspaceEmulator: Implement faccessat(2)
Co-Authored-By: Daniel Bertalan <dani@danielbertalan.dev>
This commit is contained in:
parent
fa692e13f9
commit
2a502fe232
Notes:
sideshowbarker
2024-07-17 06:09:44 +09:00
Author: https://github.com/sin-ack Commit: https://github.com/SerenityOS/serenity/commit/2a502fe232 Pull-request: https://github.com/SerenityOS/serenity/pull/15428 Reviewed-by: https://github.com/ADKaster ✅ Reviewed-by: https://github.com/AtkinsSJ Reviewed-by: https://github.com/BertalanD Reviewed-by: https://github.com/linusg Reviewed-by: https://github.com/timschumi
|
@ -48,6 +48,7 @@ extern "C" {
|
|||
#define AT_FDCWD -100
|
||||
#define AT_SYMLINK_NOFOLLOW 0x100
|
||||
#define AT_REMOVEDIR 0x200
|
||||
#define AT_EACCESS 0x400
|
||||
|
||||
struct flock {
|
||||
short l_type;
|
||||
|
|
|
@ -41,7 +41,6 @@ enum class NeedsBigProcessLock {
|
|||
//
|
||||
#define ENUMERATE_SYSCALLS(S) \
|
||||
S(accept4, NeedsBigProcessLock::No) \
|
||||
S(access, NeedsBigProcessLock::Yes) \
|
||||
S(adjtime, NeedsBigProcessLock::No) \
|
||||
S(alarm, NeedsBigProcessLock::Yes) \
|
||||
S(allocate_tls, NeedsBigProcessLock::Yes) \
|
||||
|
@ -68,6 +67,7 @@ enum class NeedsBigProcessLock {
|
|||
S(execve, NeedsBigProcessLock::Yes) \
|
||||
S(exit, NeedsBigProcessLock::Yes) \
|
||||
S(exit_thread, NeedsBigProcessLock::Yes) \
|
||||
S(faccessat, NeedsBigProcessLock::Yes) \
|
||||
S(fchdir, NeedsBigProcessLock::No) \
|
||||
S(fchmod, NeedsBigProcessLock::No) \
|
||||
S(fchown, NeedsBigProcessLock::No) \
|
||||
|
@ -508,6 +508,13 @@ struct SC_scheduler_parameters_params {
|
|||
struct sched_param parameters;
|
||||
};
|
||||
|
||||
struct SC_faccessat_params {
|
||||
int dirfd;
|
||||
StringArgument pathname;
|
||||
int mode;
|
||||
int flags;
|
||||
};
|
||||
|
||||
void initialize();
|
||||
int sync();
|
||||
|
||||
|
|
|
@ -264,7 +264,6 @@ set(KERNEL_SOURCES
|
|||
Scheduler.cpp
|
||||
StdLib.cpp
|
||||
Syscalls/anon_create.cpp
|
||||
Syscalls/access.cpp
|
||||
Syscalls/alarm.cpp
|
||||
Syscalls/beep.cpp
|
||||
Syscalls/chdir.cpp
|
||||
|
@ -276,6 +275,7 @@ set(KERNEL_SOURCES
|
|||
Syscalls/dup2.cpp
|
||||
Syscalls/emuctl.cpp
|
||||
Syscalls/exit.cpp
|
||||
Syscalls/faccessat.cpp
|
||||
Syscalls/fallocate.cpp
|
||||
Syscalls/fcntl.cpp
|
||||
Syscalls/fsync.cpp
|
||||
|
|
|
@ -523,24 +523,26 @@ ErrorOr<void> VirtualFileSystem::mkdir(Credentials const& credentials, StringVie
|
|||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> VirtualFileSystem::access(Credentials const& credentials, StringView path, int mode, Custody& base)
|
||||
ErrorOr<void> VirtualFileSystem::access(Credentials const& credentials, StringView path, int mode, Custody& base, AccessFlags access_flags)
|
||||
{
|
||||
auto custody = TRY(resolve_path(credentials, path, base));
|
||||
auto should_follow_symlinks = !has_flag(access_flags, AccessFlags::DoNotFollowSymlinks);
|
||||
auto custody = TRY(resolve_path(credentials, path, base, nullptr, should_follow_symlinks ? 0 : O_NOFOLLOW_NOERROR));
|
||||
|
||||
auto& inode = custody->inode();
|
||||
auto metadata = inode.metadata();
|
||||
auto use_effective_ids = has_flag(access_flags, AccessFlags::EffectiveAccess) ? UseEffectiveIDs::Yes : UseEffectiveIDs::No;
|
||||
if (mode & R_OK) {
|
||||
if (!metadata.may_read(credentials, UseEffectiveIDs::No))
|
||||
if (!metadata.may_read(credentials, use_effective_ids))
|
||||
return EACCES;
|
||||
}
|
||||
if (mode & W_OK) {
|
||||
if (!metadata.may_write(credentials, UseEffectiveIDs::No))
|
||||
if (!metadata.may_write(credentials, use_effective_ids))
|
||||
return EACCES;
|
||||
if (custody->is_readonly())
|
||||
return EROFS;
|
||||
}
|
||||
if (mode & X_OK) {
|
||||
if (!metadata.may_execute(credentials, UseEffectiveIDs::No))
|
||||
if (!metadata.may_execute(credentials, use_effective_ids))
|
||||
return EACCES;
|
||||
}
|
||||
return {};
|
||||
|
|
|
@ -34,6 +34,14 @@ struct UidAndGid {
|
|||
GroupID gid;
|
||||
};
|
||||
|
||||
enum class AccessFlags {
|
||||
None = 0,
|
||||
EffectiveAccess = 1 << 0,
|
||||
DoNotFollowSymlinks = 1 << 1,
|
||||
};
|
||||
|
||||
AK_ENUM_BITWISE_OPERATORS(AccessFlags);
|
||||
|
||||
class VirtualFileSystem {
|
||||
public:
|
||||
// Required to be at least 8 by POSIX
|
||||
|
@ -63,7 +71,7 @@ public:
|
|||
ErrorOr<void> chmod(Credentials const&, Custody&, mode_t);
|
||||
ErrorOr<void> chown(Credentials const&, StringView path, UserID, GroupID, Custody& base, int options);
|
||||
ErrorOr<void> chown(Credentials const&, Custody&, UserID, GroupID);
|
||||
ErrorOr<void> access(Credentials const&, StringView path, int mode, Custody& base);
|
||||
ErrorOr<void> access(Credentials const&, StringView path, int mode, Custody& base, AccessFlags);
|
||||
ErrorOr<InodeMetadata> lookup_metadata(Credentials const&, StringView path, Custody& base, int options = 0);
|
||||
ErrorOr<void> utime(Credentials const&, StringView path, Custody& base, time_t atime, time_t mtime);
|
||||
ErrorOr<void> utimensat(Credentials const&, StringView path, Custody& base, timespec const& atime, timespec const& mtime, int options = 0);
|
||||
|
|
|
@ -371,7 +371,7 @@ public:
|
|||
ErrorOr<FlatPtr> sys$setresuid(UserID, UserID, UserID);
|
||||
ErrorOr<FlatPtr> sys$setresgid(GroupID, GroupID, GroupID);
|
||||
ErrorOr<FlatPtr> sys$alarm(unsigned seconds);
|
||||
ErrorOr<FlatPtr> sys$access(Userspace<char const*> pathname, size_t path_length, int mode);
|
||||
ErrorOr<FlatPtr> sys$faccessat(Userspace<Syscall::SC_faccessat_params const*>);
|
||||
ErrorOr<FlatPtr> sys$fcntl(int fd, int cmd, uintptr_t extra_arg);
|
||||
ErrorOr<FlatPtr> sys$ioctl(int fd, unsigned request, FlatPtr arg);
|
||||
ErrorOr<FlatPtr> sys$mkdir(int dirfd, Userspace<char const*> pathname, size_t path_length, mode_t mode);
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/StringView.h>
|
||||
#include <Kernel/FileSystem/VirtualFileSystem.h>
|
||||
#include <Kernel/Process.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<FlatPtr> Process::sys$access(Userspace<char const*> user_path, size_t path_length, int mode)
|
||||
{
|
||||
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
|
||||
TRY(require_promise(Pledge::rpath));
|
||||
auto path = TRY(get_syscall_path_argument(user_path, path_length));
|
||||
TRY(VirtualFileSystem::the().access(credentials(), path->view(), mode, current_directory()));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
33
Kernel/Syscalls/faccessat.cpp
Normal file
33
Kernel/Syscalls/faccessat.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/StringView.h>
|
||||
#include <Kernel/FileSystem/VirtualFileSystem.h>
|
||||
#include <Kernel/Process.h>
|
||||
|
||||
namespace Kernel {
|
||||
|
||||
ErrorOr<FlatPtr> Process::sys$faccessat(Userspace<Syscall::SC_faccessat_params const*> user_params)
|
||||
{
|
||||
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
|
||||
TRY(require_promise(Pledge::rpath));
|
||||
auto params = TRY(copy_typed_from_user(user_params));
|
||||
auto pathname = TRY(get_syscall_path_argument(params.pathname));
|
||||
|
||||
if ((params.flags & ~(AT_SYMLINK_NOFOLLOW | AT_EACCESS)) != 0)
|
||||
return EINVAL;
|
||||
|
||||
auto flags = AccessFlags::None;
|
||||
if (params.flags & AT_SYMLINK_NOFOLLOW)
|
||||
flags |= AccessFlags::DoNotFollowSymlinks;
|
||||
if (params.flags & AT_EACCESS)
|
||||
flags |= AccessFlags::EffectiveAccess;
|
||||
|
||||
TRY(VirtualFileSystem::the().access(credentials(), pathname->view(), params.mode, TRY(custody_for_dirfd(params.dirfd)), flags));
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
|
@ -144,7 +144,6 @@ private:
|
|||
void emit_profile_event(AK::OutputStream&, StringView event_name, DeprecatedString const& contents);
|
||||
|
||||
int virt$accept4(FlatPtr);
|
||||
int virt$access(FlatPtr, size_t, int);
|
||||
u32 virt$allocate_tls(FlatPtr, size_t);
|
||||
int virt$anon_create(size_t, int);
|
||||
int virt$beep();
|
||||
|
@ -164,6 +163,7 @@ private:
|
|||
int virt$emuctl(FlatPtr, FlatPtr, FlatPtr);
|
||||
int virt$execve(FlatPtr);
|
||||
void virt$exit(int);
|
||||
int virt$faccessat(FlatPtr);
|
||||
int virt$fchmod(int, mode_t);
|
||||
int virt$fchown(int, uid_t, gid_t);
|
||||
u32 virt$fcntl(int fd, int, u32);
|
||||
|
|
|
@ -42,8 +42,6 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
|
|||
switch (function) {
|
||||
case SC_accept4:
|
||||
return virt$accept4(arg1);
|
||||
case SC_access:
|
||||
return virt$access(arg1, arg2, arg3);
|
||||
case SC_allocate_tls:
|
||||
return virt$allocate_tls(arg1, arg2);
|
||||
case SC_anon_create:
|
||||
|
@ -83,6 +81,8 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3)
|
|||
case SC_exit:
|
||||
virt$exit((int)arg1);
|
||||
return 0;
|
||||
case SC_faccessat:
|
||||
return virt$faccessat(arg1);
|
||||
case SC_fchmod:
|
||||
return virt$fchmod(arg1, arg2);
|
||||
case SC_fchown:
|
||||
|
@ -1462,10 +1462,16 @@ int Emulator::virt$getsid(pid_t pid)
|
|||
return syscall(SC_getsid, pid);
|
||||
}
|
||||
|
||||
int Emulator::virt$access(FlatPtr path, size_t path_length, int type)
|
||||
int Emulator::virt$faccessat(FlatPtr params_addr)
|
||||
{
|
||||
auto host_path = mmu().copy_buffer_from_vm(path, path_length);
|
||||
return syscall(SC_access, host_path.data(), host_path.size(), type);
|
||||
Syscall::SC_faccessat_params params;
|
||||
mmu().copy_from_vm(¶ms, params_addr, sizeof(params));
|
||||
|
||||
auto host_path = mmu().copy_buffer_from_vm(reinterpret_cast<FlatPtr>(params.pathname.characters), params.pathname.length);
|
||||
Syscall::SC_faccessat_params host_params = params;
|
||||
host_params.pathname = { reinterpret_cast<char const*>(host_path.data()), host_path.size() };
|
||||
|
||||
return syscall(SC_faccessat, &host_params);
|
||||
}
|
||||
|
||||
int Emulator::virt$waitid(FlatPtr params_addr)
|
||||
|
|
|
@ -798,12 +798,20 @@ int setresgid(gid_t rgid, gid_t egid, gid_t sgid)
|
|||
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/access.html
|
||||
int access(char const* pathname, int mode)
|
||||
{
|
||||
return faccessat(AT_FDCWD, pathname, mode, 0);
|
||||
}
|
||||
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/faccessat.html
|
||||
int faccessat(int dirfd, char const* pathname, int mode, int flags)
|
||||
{
|
||||
if (!pathname) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
int rc = syscall(SC_access, pathname, strlen(pathname), mode);
|
||||
|
||||
Syscall::SC_faccessat_params params { dirfd, { pathname, strlen(pathname) }, mode, flags };
|
||||
int rc = syscall(SC_faccessat, ¶ms);
|
||||
__RETURN_WITH_ERRNO(rc, rc, -1);
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ int pipe(int pipefd[2]);
|
|||
int pipe2(int pipefd[2], int flags);
|
||||
unsigned int alarm(unsigned int seconds);
|
||||
int access(char const* pathname, int mode);
|
||||
int faccessat(int dirfd, char const* pathname, int mode, int flags);
|
||||
int isatty(int fd);
|
||||
int mknod(char const* pathname, mode_t, dev_t);
|
||||
long fpathconf(int fd, int name);
|
||||
|
|
|
@ -1372,7 +1372,13 @@ ErrorOr<void> access(StringView pathname, int mode)
|
|||
return Error::from_syscall("access"sv, -EFAULT);
|
||||
|
||||
#ifdef AK_OS_SERENITY
|
||||
int rc = ::syscall(Syscall::SC_access, pathname.characters_without_null_termination(), pathname.length(), mode);
|
||||
Syscall::SC_faccessat_params params {
|
||||
.dirfd = AT_FDCWD,
|
||||
.pathname = { pathname.characters_without_null_termination(), pathname.length() },
|
||||
.mode = mode,
|
||||
.flags = 0,
|
||||
};
|
||||
int rc = ::syscall(Syscall::SC_faccessat, ¶ms);
|
||||
HANDLE_SYSCALL_RETURN_VALUE("access", rc, {});
|
||||
#else
|
||||
DeprecatedString path_string = pathname;
|
||||
|
|
Loading…
Reference in a new issue