mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-11 01:06:01 +03:00
f08e91f67e
Coverage tools like LLVM's source-based coverage or GNU's --coverage need to be able to write out coverage files from any binary, regardless of its security posture. Not ignoring these pledges and veils means we can't get our coverage data out without playing some serious tricks. However this is pretty terrible for normal exeuction, so only skip these checks when we explicitly configured userspace for coverage.
94 lines
2.8 KiB
C++
94 lines
2.8 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <Kernel/Debug.h>
|
|
#include <Kernel/FileSystem/Custody.h>
|
|
#include <Kernel/FileSystem/VirtualFileSystem.h>
|
|
#include <Kernel/KLexicalPath.h>
|
|
#include <Kernel/Net/LocalSocket.h>
|
|
#include <Kernel/Process.h>
|
|
|
|
namespace Kernel {
|
|
|
|
ErrorOr<FlatPtr> Process::sys$open(Userspace<Syscall::SC_open_params const*> user_params)
|
|
{
|
|
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
|
|
auto params = TRY(copy_typed_from_user(user_params));
|
|
|
|
int dirfd = params.dirfd;
|
|
int options = params.options;
|
|
u16 mode = params.mode;
|
|
|
|
if (options & O_NOFOLLOW_NOERROR)
|
|
return EINVAL;
|
|
|
|
if (options & O_UNLINK_INTERNAL)
|
|
return EINVAL;
|
|
|
|
auto path = TRY(get_syscall_path_argument(params.path));
|
|
|
|
// Disable checking open pledges when building userspace with coverage
|
|
// so that all processes can write out coverage data even with pledges
|
|
bool skip_pledge_verification = false;
|
|
|
|
#ifdef SKIP_PATH_VALIDATION_FOR_COVERAGE_INSTRUMENTATION
|
|
if (KLexicalPath::basename(path->view()).ends_with(".profraw"sv))
|
|
skip_pledge_verification = true;
|
|
#endif
|
|
if (!skip_pledge_verification) {
|
|
if (options & O_WRONLY)
|
|
TRY(require_promise(Pledge::wpath));
|
|
else if (options & O_RDONLY)
|
|
TRY(require_promise(Pledge::rpath));
|
|
|
|
if (options & O_CREAT)
|
|
TRY(require_promise(Pledge::cpath));
|
|
}
|
|
|
|
// Ignore everything except permission bits.
|
|
mode &= 0777;
|
|
|
|
dbgln_if(IO_DEBUG, "sys$open(dirfd={}, path='{}', options={}, mode={})", dirfd, path->view(), options, mode);
|
|
|
|
auto fd_allocation = TRY(allocate_fd());
|
|
RefPtr<Custody> base;
|
|
if (dirfd == AT_FDCWD) {
|
|
base = current_directory();
|
|
} else {
|
|
auto base_description = TRY(open_file_description(dirfd));
|
|
if (!base_description->is_directory())
|
|
return ENOTDIR;
|
|
if (!base_description->custody())
|
|
return EINVAL;
|
|
base = base_description->custody();
|
|
}
|
|
|
|
auto description = TRY(VirtualFileSystem::the().open(path->view(), options, mode & ~umask(), *base));
|
|
|
|
if (description->inode() && description->inode()->bound_socket())
|
|
return ENXIO;
|
|
|
|
return m_fds.with_exclusive([&](auto& fds) -> ErrorOr<FlatPtr> {
|
|
u32 fd_flags = (options & O_CLOEXEC) ? FD_CLOEXEC : 0;
|
|
fds[fd_allocation.fd].set(move(description), fd_flags);
|
|
return fd_allocation.fd;
|
|
});
|
|
}
|
|
|
|
ErrorOr<FlatPtr> Process::sys$close(int fd)
|
|
{
|
|
VERIFY_NO_PROCESS_BIG_LOCK(this)
|
|
TRY(require_promise(Pledge::stdio));
|
|
auto description = TRY(open_file_description(fd));
|
|
auto result = description->close();
|
|
m_fds.with_exclusive([fd](auto& fds) { fds[fd] = {}; });
|
|
if (result.is_error())
|
|
return result.release_error();
|
|
return 0;
|
|
}
|
|
|
|
}
|