mirror of
https://github.com/SerenityOS/serenity
synced 2026-04-25 17:15:42 +02:00
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.
This commit is contained in:
@@ -5,9 +5,8 @@
|
||||
"hostname": null,
|
||||
"layout": [
|
||||
{
|
||||
"type": "mount",
|
||||
"type": "root_mount",
|
||||
"source": null,
|
||||
"target": "/",
|
||||
"fs_type": "RAMFS"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -110,6 +110,7 @@ enum IOCtlNumber {
|
||||
KEYBOARD_IOCTL_SET_CAPS_LOCK,
|
||||
MOUNT_IOCTL_SET_MOUNT_SPECIFIC_FLAG,
|
||||
MOUNT_IOCTL_DELETE_MOUNT_SPECIFIC_FLAG,
|
||||
UNSHARE_IOCTL_ATTACH_ROOT_FILESYSTEM_AT_FD,
|
||||
SIOCATMARK,
|
||||
SIOCSIFADDR,
|
||||
SIOCGIFADDR,
|
||||
@@ -196,6 +197,7 @@ enum IOCtlNumber {
|
||||
#define FIONREAD FIONREAD
|
||||
#define MOUNT_IOCTL_SET_MOUNT_SPECIFIC_FLAG MOUNT_IOCTL_SET_MOUNT_SPECIFIC_FLAG
|
||||
#define MOUNT_IOCTL_DELETE_MOUNT_SPECIFIC_FLAG MOUNT_IOCTL_DELETE_MOUNT_SPECIFIC_FLAG
|
||||
#define UNSHARE_IOCTL_ATTACH_ROOT_FILESYSTEM_AT_FD UNSHARE_IOCTL_ATTACH_ROOT_FILESYSTEM_AT_FD
|
||||
#define SOUNDCARD_IOCTL_SET_SAMPLE_RATE SOUNDCARD_IOCTL_SET_SAMPLE_RATE
|
||||
#define SOUNDCARD_IOCTL_GET_SAMPLE_RATE SOUNDCARD_IOCTL_GET_SAMPLE_RATE
|
||||
#define STORAGE_DEVICE_GET_SIZE STORAGE_DEVICE_GET_SIZE
|
||||
|
||||
@@ -453,8 +453,6 @@ u32 StorageManagement::generate_controller_id()
|
||||
|
||||
ErrorOr<NonnullRefPtr<VFSRootContext>> StorageManagement::create_first_vfs_root_context() const
|
||||
{
|
||||
auto vfs_root_context = TRY(VFSRootContext::create_with_empty_ramfs(VFSRootContext::AddToGlobalContextList::Yes));
|
||||
|
||||
auto const* fs_type_initializer = TRY(VirtualFileSystem::find_filesystem_type_initializer("ext2"sv));
|
||||
VERIFY(fs_type_initializer);
|
||||
auto mount_file = TRY(MountFile::create(*fs_type_initializer, root_mount_flags));
|
||||
@@ -467,25 +465,7 @@ ErrorOr<NonnullRefPtr<VFSRootContext>> StorageManagement::create_first_vfs_root_
|
||||
auto description = TRY(OpenFileDescription::try_create(boot_device_description.release_nonnull()));
|
||||
|
||||
auto fs = TRY(FileBackedFileSystem::create_and_append_filesystems_list_from_mount_file_and_description(mount_file, description));
|
||||
|
||||
// NOTE: Fake a mounted count of 1 so the called VirtualFileSystem function in the
|
||||
// next pivot_root logic block thinks everything is OK.
|
||||
fs->mounted_count().with([](auto& mounted_count) {
|
||||
mounted_count++;
|
||||
});
|
||||
|
||||
// Adding filesystems to the all_file_systems_list usually happens in add_to_mounts_list_and_increment_fs_mounted_count(),
|
||||
// but that function isn't called for the root filesystem of the first VFSRootContext.
|
||||
FileSystem::all_file_systems_list().with([&fs](auto& fs_list) {
|
||||
fs_list.append(*fs);
|
||||
});
|
||||
|
||||
TRY(VirtualFileSystem::pivot_root_by_copying_mounted_fs_instance(*vfs_root_context, *fs, root_mount_flags));
|
||||
// NOTE: Return the mounted count to normal now we have it really mounted.
|
||||
fs->mounted_count().with([](auto& mounted_count) {
|
||||
mounted_count--;
|
||||
});
|
||||
return vfs_root_context;
|
||||
return TRY(VFSRootContext::create_with_filesystem(VFSRootContext::AddToGlobalContextList::Yes, fs));
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT void StorageManagement::initialize(bool poll)
|
||||
|
||||
@@ -39,8 +39,14 @@ ErrorOr<unsigned> UnsharedResourceFile::initialize_resource()
|
||||
return scoped_process_list->id().value();
|
||||
}
|
||||
case UnshareType::VFSRootContext: {
|
||||
auto vfs_root_context = TRY(VFSRootContext::create_with_empty_ramfs(VFSRootContext::AddToGlobalContextList::Yes));
|
||||
return vfs_root_context->id().value();
|
||||
return m_root_filesystem.with_exclusive([&](auto& root_filesystem) -> ErrorOr<unsigned> {
|
||||
if (root_filesystem) {
|
||||
auto vfs_root_context = TRY(VFSRootContext::create_with_filesystem(VFSRootContext::AddToGlobalContextList::Yes, *root_filesystem));
|
||||
return vfs_root_context->id().value();
|
||||
}
|
||||
auto vfs_root_context = TRY(VFSRootContext::create_with_empty_ramfs(VFSRootContext::AddToGlobalContextList::Yes));
|
||||
return vfs_root_context->id().value();
|
||||
});
|
||||
}
|
||||
case UnshareType::HostnameContext: {
|
||||
// NOTE: Technically, we create a new context, based on the
|
||||
@@ -64,9 +70,33 @@ ErrorOr<unsigned> UnsharedResourceFile::initialize_resource()
|
||||
|
||||
UnsharedResourceFile::~UnsharedResourceFile() = default;
|
||||
|
||||
ErrorOr<void> UnsharedResourceFile::ioctl(OpenFileDescription&, unsigned, Userspace<void*>)
|
||||
ErrorOr<void> UnsharedResourceFile::ioctl(OpenFileDescription&, unsigned request, Userspace<void*> arg)
|
||||
{
|
||||
return ENOTSUP;
|
||||
switch (request) {
|
||||
case UNSHARE_IOCTL_ATTACH_ROOT_FILESYSTEM_AT_FD: {
|
||||
auto current_vfs_root_context = Process::current().vfs_root_context();
|
||||
auto credentials = Process::current().credentials();
|
||||
auto fd = static_cast<int>(arg.ptr());
|
||||
auto description = TRY(Process::current().open_file_description_ignoring_negative(fd));
|
||||
return m_root_filesystem.with_exclusive([&credentials, ¤t_vfs_root_context, &description](auto& root_filesystem) -> ErrorOr<void> {
|
||||
if (!description) {
|
||||
root_filesystem = nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!description->is_directory())
|
||||
return ENOTDIR;
|
||||
if (!description->metadata().may_execute(credentials))
|
||||
return EACCES;
|
||||
VERIFY(description->custody());
|
||||
root_filesystem = TRY(current_vfs_root_context->mount_point_to_guest_filesystem(*description->custody()));
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorOr<NonnullOwnPtr<KString>> UnsharedResourceFile::pseudo_path(OpenFileDescription const&) const
|
||||
|
||||
@@ -32,6 +32,8 @@ private:
|
||||
|
||||
explicit UnsharedResourceFile(UnshareType);
|
||||
UnshareType const m_type;
|
||||
|
||||
MutexProtected<RefPtr<FileSystem>> m_root_filesystem;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -26,15 +26,20 @@ ErrorOr<NonnullRefPtr<VFSRootContext>> VFSRootContext::create_with_empty_ramfs(A
|
||||
|
||||
auto fs = TRY(RAMFS::try_create({}));
|
||||
TRY(fs->initialize());
|
||||
auto root_custody = TRY(Custody::try_create(nullptr, ""sv, fs->root_inode(), 0));
|
||||
return create_with_filesystem(add_to_global_context_list, fs);
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<VFSRootContext>> VFSRootContext::create_with_filesystem(AddToGlobalContextList add_to_global_context_list, FileSystem& fs)
|
||||
{
|
||||
auto root_custody = TRY(Custody::try_create(nullptr, ""sv, fs.root_inode(), 0));
|
||||
auto context = TRY(adopt_nonnull_ref_or_enomem(new (nothrow) VFSRootContext(root_custody)));
|
||||
auto new_mount = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Mount(fs->root_inode(), 0)));
|
||||
auto new_mount = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Mount(fs.root_inode(), 0)));
|
||||
TRY(context->m_details.with([&](auto& details) -> ErrorOr<void> {
|
||||
if (add_to_global_context_list == AddToGlobalContextList::Yes) {
|
||||
dbgln("VFSRootContext({}): Root (\"/\") FileSystemID {}, Mounting {} at inode {} with flags {}",
|
||||
context->id(),
|
||||
fs->fsid(),
|
||||
fs->class_name(),
|
||||
fs.fsid(),
|
||||
fs.class_name(),
|
||||
root_custody->inode().identifier(),
|
||||
0);
|
||||
}
|
||||
@@ -123,52 +128,6 @@ void VFSRootContext::add_to_mounts_list_and_increment_fs_mounted_count(DoBindMou
|
||||
mounts_list.append(*new_mount.leak_ptr());
|
||||
}
|
||||
|
||||
ErrorOr<void> VFSRootContext::pivot_root(FileBackedFileSystem::List& file_backed_file_systems_list, FileSystem& fs, NonnullOwnPtr<Mount> new_mount, NonnullRefPtr<Custody> root_mount_point, int root_mount_flags)
|
||||
{
|
||||
return m_details.with([&](auto& details) -> ErrorOr<void> {
|
||||
return fs.mounted_count().with([&](auto& mounted_count) -> ErrorOr<void> {
|
||||
// NOTE: If the mounted count is 0, then this filesystem is about to be
|
||||
// deleted, so this must be a kernel bug as we don't include such filesystem
|
||||
// in the VirtualFileSystem s_details->file_backed_file_systems_list list anymore.
|
||||
VERIFY(mounted_count > 0);
|
||||
|
||||
// NOTE: The mounts table should not be empty as it always need
|
||||
// to have at least one mount!
|
||||
VERIFY(!details.mounts.is_empty());
|
||||
|
||||
// NOTE: If we have many mounts in the table, then simply don't allow
|
||||
// userspace to override them but instead require to unmount everything except
|
||||
// the root mount first.
|
||||
if (details.mounts.size_slow() != 1)
|
||||
return EPERM;
|
||||
|
||||
auto& mount = *details.mounts.first();
|
||||
TRY(VirtualFileSystem::remove_mount(mount, file_backed_file_systems_list));
|
||||
VERIFY(details.mounts.is_empty());
|
||||
|
||||
dbgln("VFSRootContext({}): Root mount set to FileSystemID {}, Mounting {} at inode {} with flags {}",
|
||||
id(),
|
||||
new_mount->guest_fs().fsid(),
|
||||
new_mount->guest_fs().class_name(),
|
||||
root_mount_point->inode().identifier(),
|
||||
root_mount_flags);
|
||||
|
||||
// NOTE: Leak the mount pointer so it can be added to the mount list, but it won't be
|
||||
// deleted after being added.
|
||||
details.mounts.append(*new_mount.leak_ptr());
|
||||
|
||||
// NOTE: We essentially do the same thing like VFSRootContext::add_to_mounts_list_and_increment_fs_mounted_count function
|
||||
// but because we already locked the spinlock of the attach count, we can't call that function here.
|
||||
mounted_count++;
|
||||
// NOTE: Now fill the root custody with a valid custody for the new root mount.
|
||||
m_root_custody.with([&root_mount_point](auto& custody) {
|
||||
custody = move(root_mount_point);
|
||||
});
|
||||
return {};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<void> VFSRootContext::do_full_teardown(Badge<PowerStateSwitchTask>)
|
||||
{
|
||||
// NOTE: We are going to tear down the entire VFS root context from its mounts.
|
||||
@@ -313,6 +272,27 @@ ErrorOr<void> VFSRootContext::apply_to_mount_for_host_custody(Custody const& cur
|
||||
return do_on_mount_for_host_custody(ValidateImmutableFlag::Yes, current_custody, move(callback));
|
||||
}
|
||||
|
||||
ErrorOr<NonnullRefPtr<FileSystem>> VFSRootContext::mount_point_to_guest_filesystem(Custody const& custody)
|
||||
{
|
||||
return m_details.with([&](auto& details) -> ErrorOr<NonnullRefPtr<FileSystem>> {
|
||||
// NOTE: We either search for the root mount or for a mount that has a parent custody!
|
||||
if (!custody.parent()) {
|
||||
for (auto& mount : details.mounts) {
|
||||
if (!mount.host_custody())
|
||||
return mount.guest_fs();
|
||||
}
|
||||
// There must be a root mount entry, so fail if we don't find it.
|
||||
VERIFY_NOT_REACHED();
|
||||
} else {
|
||||
for (auto& mount : details.mounts) {
|
||||
if (mount.host_custody() && VirtualFileSystem::check_matching_absolute_path_hierarchy(*mount.host_custody(), custody))
|
||||
return mount.guest_fs();
|
||||
}
|
||||
}
|
||||
return ENODEV;
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<VFSRootContext::CurrentMountState> VFSRootContext::current_mount_state_for_host_custody(Custody const& current_custody) const
|
||||
{
|
||||
RefPtr<FileSystem> guest_fs;
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
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; }
|
||||
@@ -49,10 +50,11 @@ public:
|
||||
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> pivot_root(FileBackedFileSystem::List& file_backed_file_systems_list, FileSystem& fs, NonnullOwnPtr<Mount> new_mount, NonnullRefPtr<Custody> root_mount_point, int root_mount_flags);
|
||||
|
||||
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 };
|
||||
|
||||
@@ -242,13 +242,6 @@ ErrorOr<void> VirtualFileSystem::copy_mount(Custody& original_custody, VFSRootCo
|
||||
if (&original_custody.inode() != &original_custody.inode().fs().root_inode())
|
||||
return EINVAL;
|
||||
|
||||
// NOTE: If the user specified the root custody ("/") on the destination context
|
||||
// then try to `pivot_root` the destination context root mount with the desired
|
||||
// custody.
|
||||
auto destination_context_root_custody = destination_context.root_custody().with([](auto& custody) -> NonnullRefPtr<Custody> { return custody; });
|
||||
if (&new_mount_point == destination_context_root_custody.ptr())
|
||||
return pivot_root_by_copying_mounted_fs_instance(destination_context, original_custody.inode().fs(), flags);
|
||||
|
||||
TRY(destination_context.add_new_mount(VFSRootContext::DoBindMount::No, original_custody.inode(), new_mount_point, flags));
|
||||
return {};
|
||||
}
|
||||
@@ -315,16 +308,6 @@ ErrorOr<void> VirtualFileSystem::remove_mount(Mount& mount, FileBackedFileSystem
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> VirtualFileSystem::pivot_root_by_copying_mounted_fs_instance(VFSRootContext& context, FileSystem& fs, int root_mount_flags)
|
||||
{
|
||||
auto root_mount_point = TRY(Custody::try_create(nullptr, ""sv, fs.root_inode(), root_mount_flags));
|
||||
auto new_mount = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Mount(fs.root_inode(), root_mount_flags)));
|
||||
|
||||
return s_details->file_backed_file_systems_list.with_exclusive([&](auto& file_backed_file_systems_list) -> ErrorOr<void> {
|
||||
return context.pivot_root(file_backed_file_systems_list, fs, move(new_mount), move(root_mount_point), root_mount_flags);
|
||||
});
|
||||
}
|
||||
|
||||
ErrorOr<void> VirtualFileSystem::unmount(VFSRootContext& context, Inode& guest_inode, StringView custody_path)
|
||||
{
|
||||
return s_details->file_backed_file_systems_list.with_exclusive([&](auto& file_backed_file_systems_list) -> ErrorOr<void> {
|
||||
|
||||
@@ -59,7 +59,6 @@ ErrorOr<FileSystemInitializer const*> find_filesystem_type_initializer(StringVie
|
||||
ErrorOr<void> remove_mount(Mount& mount, FileBackedFileSystem::List& file_backed_fs_list);
|
||||
|
||||
ErrorOr<void> mount(VFSRootContext&, MountFile&, OpenFileDescription*, Custody& mount_point, int flags);
|
||||
ErrorOr<void> pivot_root_by_copying_mounted_fs_instance(VFSRootContext&, FileSystem& fs, int root_mount_flags);
|
||||
|
||||
ErrorOr<void> bind_mount(VFSRootContext&, Custody& source, Custody& mount_point, int flags);
|
||||
ErrorOr<void> copy_mount(Custody& source, VFSRootContext& destination, Custody& mount_point, int flags);
|
||||
|
||||
@@ -161,7 +161,36 @@ static ErrorOr<void> handle_property(VFSRootContextLayout& layout, JsonObject co
|
||||
}
|
||||
|
||||
auto type = object.get_byte_string("type"sv).value();
|
||||
dbgln("WARNING: Unknown object type - {}, it might affect layout creation severely", type);
|
||||
if (type != "root_mount"sv)
|
||||
dbgln("WARNING: Unknown object type - {}, it might affect layout creation severely", type);
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> create_root_mount_point(StringView preparation_environment_path, JsonArray const& layout_creation_sequence)
|
||||
{
|
||||
for (size_t index = 0; index < layout_creation_sequence.size(); index++) {
|
||||
auto& maybe_object = layout_creation_sequence[index];
|
||||
if (!maybe_object.is_object())
|
||||
return Error::from_string_view("Invalid layout JSON object"sv);
|
||||
if (!maybe_object.as_object().has_string("type"sv))
|
||||
return Error::from_string_view("Invalid layout JSON object - no type being specified"sv);
|
||||
|
||||
auto& object = maybe_object.as_object();
|
||||
|
||||
auto type = object.get_byte_string("type"sv).value();
|
||||
if (type != "root_mount"sv)
|
||||
continue;
|
||||
|
||||
if (!object.has_null("source"sv) && !object.has_string("source"sv))
|
||||
return Error::from_string_view("Object root_mount source property not found"sv);
|
||||
if (!object.has_string("fs_type"sv))
|
||||
return Error::from_string_view("Object root_mount fs_type property not found"sv);
|
||||
|
||||
auto fs_type = object.get_byte_string("fs_type"sv).value();
|
||||
auto source = object.get_byte_string("source"sv).value_or("none");
|
||||
auto source_fd = TRY(VFSRootContextLayout::get_source_fd(source));
|
||||
TRY(Core::System::mount({}, source_fd, preparation_environment_path, fs_type, 0));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
namespace LayoutParsing {
|
||||
|
||||
ErrorOr<void> handle_creation_sequence(VFSRootContextLayout&, JsonArray const& layout_creation_sequence);
|
||||
ErrorOr<void> create_root_mount_point(StringView preparation_environment_path, JsonArray const& layout_creation_sequence);
|
||||
|
||||
}
|
||||
|
||||
@@ -11,21 +11,6 @@
|
||||
|
||||
#include "VFSRootContextLayout.h"
|
||||
|
||||
static bool is_source_none(StringView source)
|
||||
{
|
||||
return source == "none"sv;
|
||||
}
|
||||
|
||||
static ErrorOr<int> get_source_fd(StringView source)
|
||||
{
|
||||
if (is_source_none(source))
|
||||
return -1;
|
||||
auto fd_or_error = Core::System::open(source, O_RDWR);
|
||||
if (fd_or_error.is_error())
|
||||
fd_or_error = Core::System::open(source, O_RDONLY);
|
||||
return fd_or_error;
|
||||
}
|
||||
|
||||
ErrorOr<void> VFSRootContextLayout::mount_new_filesystem(StringView fstype, StringView source, StringView target_path, int flags)
|
||||
{
|
||||
auto source_fd = TRY(get_source_fd(source));
|
||||
@@ -96,10 +81,21 @@ VFSRootContextLayout::VFSRootContextLayout(String preparation_environment_path,
|
||||
{
|
||||
}
|
||||
|
||||
ErrorOr<NonnullOwnPtr<VFSRootContextLayout>> VFSRootContextLayout::create(StringView preparation_environment_path, unsigned target_vfs_root_context_id)
|
||||
ErrorOr<NonnullOwnPtr<VFSRootContextLayout>> VFSRootContextLayout::create_with_root_mount_point(StringView preparation_environment_path)
|
||||
{
|
||||
auto vfs_root_context_fd = TRY(Core::System::unshare_open(Kernel::UnshareType::VFSRootContext));
|
||||
|
||||
// At this point we are expecting this path to be mounted with the actual "root" filesystem for this VFS root context
|
||||
auto preparation_environment_path_fd = TRY(Core::System::open(preparation_environment_path, O_DIRECTORY | O_RDONLY));
|
||||
TRY(Core::System::ioctl(vfs_root_context_fd, UNSHARE_IOCTL_ATTACH_ROOT_FILESYSTEM_AT_FD, preparation_environment_path_fd));
|
||||
close(preparation_environment_path_fd);
|
||||
|
||||
auto vfs_root_context_index = TRY(Core::System::unshare_create(vfs_root_context_fd));
|
||||
|
||||
close(vfs_root_context_fd);
|
||||
|
||||
auto path = TRY(String::from_utf8(preparation_environment_path));
|
||||
return adopt_nonnull_own_or_enomem(new (nothrow) VFSRootContextLayout(move(path), target_vfs_root_context_id));
|
||||
return adopt_nonnull_own_or_enomem(new (nothrow) VFSRootContextLayout(move(path), vfs_root_context_index));
|
||||
}
|
||||
|
||||
ErrorOr<void> VFSRootContextLayout::apply_mounts_on_vfs_root_context_id()
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <AK/StringView.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/Vector.h>
|
||||
#include <LibCore/System.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class VFSRootContextLayout {
|
||||
@@ -28,6 +29,21 @@ public:
|
||||
String fstype;
|
||||
};
|
||||
|
||||
static bool is_source_none(StringView source)
|
||||
{
|
||||
return source == "none"sv;
|
||||
}
|
||||
|
||||
static ErrorOr<int> get_source_fd(StringView source)
|
||||
{
|
||||
if (is_source_none(source))
|
||||
return -1;
|
||||
auto fd_or_error = Core::System::open(source, O_RDWR);
|
||||
if (fd_or_error.is_error())
|
||||
fd_or_error = Core::System::open(source, O_RDONLY);
|
||||
return fd_or_error;
|
||||
}
|
||||
|
||||
ErrorOr<void> mount_new_filesystem(StringView fstype, StringView source, StringView target_path, int flags);
|
||||
|
||||
ErrorOr<void> chown(StringView path, uid_t uid, gid_t gid);
|
||||
@@ -37,9 +53,13 @@ public:
|
||||
ErrorOr<void> copy_to_custom_location(StringView source_path, StringView target_path);
|
||||
ErrorOr<void> mkdir(StringView target_path);
|
||||
|
||||
static ErrorOr<NonnullOwnPtr<VFSRootContextLayout>> create(StringView preparation_environment_path, unsigned target_vfs_root_context_id);
|
||||
static ErrorOr<NonnullOwnPtr<VFSRootContextLayout>> create_with_root_mount_point(StringView preparation_environment_path);
|
||||
ErrorOr<void> apply_mounts_on_vfs_root_context_id();
|
||||
|
||||
static ErrorOr<void> mount_root_filesystem(StringView path, StringView fstype, StringView source, int flags);
|
||||
|
||||
unsigned id() const { return m_target_vfs_root_context_id; }
|
||||
|
||||
private:
|
||||
VFSRootContextLayout(String preparation_environment_path, unsigned target_vfs_root_context_id);
|
||||
|
||||
|
||||
@@ -20,19 +20,20 @@
|
||||
|
||||
static ErrorOr<void> create_custom_vfs_root_context_layout(JsonArray const& layout_creation_sequence)
|
||||
{
|
||||
auto vfs_root_context_fd = TRY(Core::System::unshare_open(Kernel::UnshareType::VFSRootContext));
|
||||
auto vfs_root_context_index = TRY(Core::System::unshare_create(vfs_root_context_fd));
|
||||
char pattern[] = "/tmp/container_root_XXXXXX";
|
||||
auto temp_directory_path = TRY(Core::System::mkdtemp(pattern));
|
||||
auto vfs_root_context_layout = TRY(VFSRootContextLayout::create(temp_directory_path.bytes_as_string_view(), vfs_root_context_index));
|
||||
TRY(LayoutParsing::create_root_mount_point(temp_directory_path, layout_creation_sequence));
|
||||
auto vfs_root_context_layout = TRY(VFSRootContextLayout::create_with_root_mount_point(temp_directory_path.bytes_as_string_view()));
|
||||
TRY(LayoutParsing::handle_creation_sequence(*vfs_root_context_layout, layout_creation_sequence));
|
||||
|
||||
TRY(vfs_root_context_layout->apply_mounts_on_vfs_root_context_id());
|
||||
|
||||
TRY(Core::System::umount({}, temp_directory_path.bytes_as_string_view()));
|
||||
|
||||
TRY(Core::System::rmdir(temp_directory_path));
|
||||
|
||||
TRY(Core::System::unshare_enter(Kernel::UnshareType::VFSRootContext,
|
||||
vfs_root_context_index,
|
||||
vfs_root_context_layout->id(),
|
||||
to_underlying(Kernel::UnshareEnterFlags::AfterExec)));
|
||||
|
||||
return {};
|
||||
|
||||
Reference in New Issue
Block a user