1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 00:27:45 +00:00

Kernel+LibC+LibCore+UserspaceEmulator: Implement faccessat(2)

Co-Authored-By: Daniel Bertalan <dani@danielbertalan.dev>
This commit is contained in:
sin-ack 2022-10-01 12:24:56 +00:00 committed by Andrew Kaster
parent fa692e13f9
commit 2a502fe232
13 changed files with 89 additions and 39 deletions

View file

@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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 {};

View file

@ -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);

View file

@ -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);

View file

@ -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;
}
}

View 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;
}
}