Files
serenity/Kernel/FileSystem/VFSRootContext.h
Liav A. f6db24dba4 Kernel+runc: Remove the pivot_root functionality in copy_mount syscall
That functionality seems to be too much complicated.
We shouldn't overengineer how the copy_mount syscall works, so instead
of allowing replacement of the root filesystem, let's make the unshare
file descriptor to be configured via a special ioctl call before we
initialize a new VFSRootContext object.

The special ioctl can either set a new root filesystem for the upcoming
VFSRootContext object, or remove it (by passing fd of -1).
If there's no specified root filesystem, a new RAMFS instance will be
created automatically when invoking the unshare_create syscall.

This also simplifies the code in the boot process, hence making it much
more readable.

It should be noted, that we assumed during pivot_root that the first
mountpoint in a context is the root mountpoint, which is probably a fair
assumption, but we don't assume this anywhere else in the VFSRootContext
code.
If this functionality ever comes back, we should ensure that we make
some effort to not assume this again.
2026-03-14 11:45:37 +01:00

117 lines
4.1 KiB
C++

/*
* Copyright (c) 2024, Liav A. <liavalb@hotmail.co.il>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/IntrusiveList.h>
#include <AK/Noncopyable.h>
#include <AK/RefPtr.h>
#include <AK/SetOnce.h>
#include <Kernel/FileSystem/Custody.h>
#include <Kernel/FileSystem/FileBackedFileSystem.h>
#include <Kernel/FileSystem/FileSystem.h>
#include <Kernel/FileSystem/Mount.h>
#include <Kernel/Forward.h>
#include <Kernel/Locking/SpinlockProtected.h>
namespace Kernel {
class VFSRootContext : public AtomicRefCounted<VFSRootContext> {
AK_MAKE_NONCOPYABLE(VFSRootContext);
AK_MAKE_NONMOVABLE(VFSRootContext);
public:
AK_TYPEDEF_DISTINCT_ORDERED_ID(u64, IndexID);
static VFSRootContext const& empty_context_for_kernel_processes();
static Custody const& empty_context_custody_for_kernel_processes();
static void initialize_empty_ramfs_root_context_for_kernel_processes();
enum class AddToGlobalContextList {
Yes,
No,
};
static ErrorOr<NonnullRefPtr<VFSRootContext>> create_with_empty_ramfs(AddToGlobalContextList);
static ErrorOr<NonnullRefPtr<VFSRootContext>> create_with_filesystem(AddToGlobalContextList, FileSystem&);
static ErrorOr<NonnullRefPtr<VFSRootContext>> create_empty();
SpinlockProtected<NonnullRefPtr<Custody>, LockRank::None>& root_custody() { return m_root_custody; }
SpinlockProtected<NonnullRefPtr<Custody>, LockRank::None> const& root_custody() const { return m_root_custody; }
enum class DoBindMount {
Yes,
No,
};
ErrorOr<void> add_new_mount(DoBindMount, Inode& source, Custody& mount_point, int flags);
ErrorOr<void> do_full_teardown(Badge<PowerStateSwitchTask>);
ErrorOr<void> unmount(FileBackedFileSystem::List& file_backed_file_systems_list, Inode& guest_inode, StringView custody_path);
ErrorOr<void> apply_to_mount_for_host_custody(Custody const& current_custody, Function<void(Mount&)>);
ErrorOr<NonnullRefPtr<FileSystem>> mount_point_to_guest_filesystem(Custody const& custody);
struct CurrentMountState {
Mount::Details details;
int flags { 0 };
};
ErrorOr<CurrentMountState> current_mount_state_for_host_custody(Custody const& current_custody) const;
IndexID id() const { return m_id; }
void attach(Badge<Process>);
void detach(Badge<Process>);
ErrorOr<void> for_each_mount(Function<ErrorOr<void>(Mount const&)>) const;
private:
VFSRootContext(NonnullRefPtr<Custody> custody);
enum class ValidateImmutableFlag {
Yes,
No,
};
ErrorOr<void> do_on_mount_for_host_custody(ValidateImmutableFlag validate_immutable_flag, Custody const& current_custody, Function<void(Mount&)> callback) const;
static void add_to_mounts_list_and_increment_fs_mounted_count(DoBindMount do_bind_mount, IntrusiveList<&Mount::m_vfs_list_node>&, NonnullOwnPtr<Mount>);
struct Details {
SetOnce attached_by_process;
size_t attach_count { 0 };
IntrusiveList<&Mount::m_vfs_list_node> mounts;
};
bool mount_point_exists_at_custody(Custody& mount_point, Details& details);
static inline ErrorOr<void> validate_mount_not_immutable_while_being_used(Details& details, Mount& mount)
{
if (mount.is_immutable() && details.attach_count > 0)
return Error::from_errno(EPERM);
return {};
}
mutable SpinlockProtected<Details, LockRank::None> m_details {};
SpinlockProtected<NonnullRefPtr<Custody>, LockRank::None> m_root_custody;
IntrusiveListNode<VFSRootContext, NonnullRefPtr<VFSRootContext>> m_list_node;
IndexID m_id;
// NOTE: This method is implemented in Kernel/FileSystem/VirtualFileSystem.cpp
static SpinlockProtected<IntrusiveList<&VFSRootContext::m_list_node>, LockRank::FileSystem>& all_root_contexts_list();
public:
using List = IntrusiveList<&VFSRootContext::m_list_node>;
// NOTE: These methods are implemented in Kernel/FileSystem/VirtualFileSystem.cpp
static SpinlockProtected<VFSRootContext::List, LockRank::FileSystem>& all_root_contexts_list(Badge<PowerStateSwitchTask>);
static SpinlockProtected<VFSRootContext::List, LockRank::FileSystem>& all_root_contexts_list(Badge<Process>);
};
}