mirror of
https://github.com/fergalmoran/ladybird.git
synced 2025-12-26 03:09:08 +00:00
Instead of getting credentials from Process::current(), we now require that they be provided as input to the various VFS functions. This ensures that an atomic set of credentials is used throughout an entire VFS operation.
62 lines
2.0 KiB
C++
62 lines
2.0 KiB
C++
/*
|
|
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/RefPtr.h>
|
|
#include <Kernel/FileSystem/Custody.h>
|
|
#include <Kernel/FileSystem/VirtualFileSystem.h>
|
|
#include <Kernel/Process.h>
|
|
|
|
namespace Kernel {
|
|
|
|
ErrorOr<FlatPtr> Process::sys$chdir(Userspace<char const*> user_path, size_t path_length)
|
|
{
|
|
VERIFY_NO_PROCESS_BIG_LOCK(this);
|
|
TRY(require_promise(Pledge::rpath));
|
|
auto path = TRY(get_syscall_path_argument(user_path, path_length));
|
|
auto current_directory = m_current_directory.with([](auto& current_directory) -> NonnullRefPtr<Custody> {
|
|
return *current_directory;
|
|
});
|
|
RefPtr<Custody> new_directory = TRY(VirtualFileSystem::the().open_directory(credentials(), path->view(), *current_directory));
|
|
m_current_directory.with([&](auto& current_directory) {
|
|
// NOTE: We use swap() here to avoid manipulating the ref counts while holding the lock.
|
|
swap(current_directory, new_directory);
|
|
});
|
|
return 0;
|
|
}
|
|
|
|
ErrorOr<FlatPtr> Process::sys$fchdir(int fd)
|
|
{
|
|
VERIFY_NO_PROCESS_BIG_LOCK(this);
|
|
TRY(require_promise(Pledge::stdio));
|
|
auto description = TRY(open_file_description(fd));
|
|
if (!description->is_directory())
|
|
return ENOTDIR;
|
|
if (!description->metadata().may_execute(credentials()))
|
|
return EACCES;
|
|
m_current_directory.with([&](auto& current_directory) {
|
|
current_directory = description->custody();
|
|
});
|
|
return 0;
|
|
}
|
|
|
|
ErrorOr<FlatPtr> Process::sys$getcwd(Userspace<char*> buffer, size_t size)
|
|
{
|
|
VERIFY_NO_PROCESS_BIG_LOCK(this);
|
|
TRY(require_promise(Pledge::rpath));
|
|
|
|
if (size > NumericLimits<ssize_t>::max())
|
|
return EINVAL;
|
|
|
|
auto path = TRY(current_directory()->try_serialize_absolute_path());
|
|
size_t ideal_size = path->length() + 1;
|
|
auto size_to_copy = min(ideal_size, size);
|
|
TRY(copy_to_user(buffer, path->characters(), size_to_copy));
|
|
// Note: we return the whole size here, not the copied size.
|
|
return ideal_size;
|
|
}
|
|
|
|
}
|