mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
Kernel: Simplify mount syscall flow for regular calls
We do this by putting a distinction between two types of filesystems - the first type is backed in RAM, and includes TmpFS, ProcFS, SysFS, DevPtsFS and DevTmpFS. Because these filesystems are backed in RAM, trying to mount them doesn't require source open file description. The second type is filesystems that are backed by a file, therefore the userspace program has to open them (hence it has a open file description on them) and provide the appropriate source open file description. By putting this distinction, we can early check if the user tried to mount the second type of filesystems without a valid file description, and fail with EBADF then. Otherwise, we can proceed to either mount either type of filesystem, provided that the fs_type is valid.
This commit is contained in:
parent
be3fec7c9e
commit
4c588441e3
Notes:
sideshowbarker
2024-07-17 10:35:42 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/4c588441e3 Pull-request: https://github.com/SerenityOS/serenity/pull/14123 Issue: https://github.com/SerenityOS/serenity/issues/11283 Reviewed-by: https://github.com/linusg
1 changed files with 74 additions and 49 deletions
|
@ -18,6 +18,63 @@
|
|||
|
||||
namespace Kernel {
|
||||
|
||||
static ErrorOr<NonnullRefPtr<FileSystem>> create_ram_backed_filesystem_instance(StringView fs_type)
|
||||
{
|
||||
RefPtr<FileSystem> fs;
|
||||
if (fs_type == "proc"sv || fs_type == "ProcFS"sv) {
|
||||
fs = TRY(ProcFS::try_create());
|
||||
} else if (fs_type == "devpts"sv || fs_type == "DevPtsFS"sv) {
|
||||
fs = TRY(DevPtsFS::try_create());
|
||||
} else if (fs_type == "dev"sv || fs_type == "DevTmpFS"sv) {
|
||||
fs = TRY(DevTmpFS::try_create());
|
||||
} else if (fs_type == "sys"sv || fs_type == "SysFS"sv) {
|
||||
fs = TRY(SysFS::try_create());
|
||||
} else if (fs_type == "tmp"sv || fs_type == "TmpFS"sv) {
|
||||
fs = TRY(TmpFS::try_create());
|
||||
}
|
||||
if (!fs)
|
||||
return ENODEV;
|
||||
return fs.release_nonnull();
|
||||
}
|
||||
|
||||
static bool filesystem_mount_require_open_file_description(StringView fs_type)
|
||||
{
|
||||
if (fs_type == "ext2"sv || fs_type == "Ext2FS"sv) {
|
||||
return true;
|
||||
} else if (fs_type == "9p"sv || fs_type == "Plan9FS"sv) {
|
||||
return true;
|
||||
} else if (fs_type == "iso9660"sv || fs_type == "ISO9660FS"sv) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static ErrorOr<NonnullRefPtr<FileSystem>> create_open_file_description_backed_filesystem_instance(StringView fs_type, OpenFileDescription& description)
|
||||
{
|
||||
RefPtr<FileSystem> fs;
|
||||
|
||||
if (fs_type == "ext2"sv || fs_type == "Ext2FS"sv) {
|
||||
if (!description.file().is_block_device())
|
||||
return ENOTBLK;
|
||||
if (!description.file().is_seekable()) {
|
||||
dbgln("mount: this is not a seekable file");
|
||||
return ENODEV;
|
||||
}
|
||||
fs = TRY(Ext2FS::try_create(description));
|
||||
} else if (fs_type == "9p"sv || fs_type == "Plan9FS"sv) {
|
||||
fs = TRY(Plan9FS::try_create(description));
|
||||
} else if (fs_type == "iso9660"sv || fs_type == "ISO9660FS"sv) {
|
||||
if (!description.file().is_seekable()) {
|
||||
dbgln("mount: this is not a seekable file");
|
||||
return ENODEV;
|
||||
}
|
||||
fs = TRY(ISO9660FS::try_create(description));
|
||||
}
|
||||
if (!fs)
|
||||
return ENODEV;
|
||||
return fs.release_nonnull();
|
||||
}
|
||||
|
||||
ErrorOr<FlatPtr> Process::sys$mount(Userspace<Syscall::SC_mount_params const*> user_params)
|
||||
{
|
||||
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this)
|
||||
|
@ -59,58 +116,26 @@ ErrorOr<FlatPtr> Process::sys$mount(Userspace<Syscall::SC_mount_params const*> u
|
|||
return 0;
|
||||
}
|
||||
|
||||
RefPtr<FileSystem> fs;
|
||||
|
||||
if (fs_type == "ext2"sv || fs_type == "Ext2FS"sv) {
|
||||
if (description_or_error.is_error())
|
||||
return EBADF;
|
||||
auto description = description_or_error.release_value();
|
||||
if (!description->file().is_block_device())
|
||||
return ENOTBLK;
|
||||
if (!description->file().is_seekable()) {
|
||||
dbgln("mount: this is not a seekable file");
|
||||
return ENODEV;
|
||||
}
|
||||
|
||||
auto source_pseudo_path = TRY(description->pseudo_path());
|
||||
dbgln("mount: attempting to mount {} on {}", source_pseudo_path, target);
|
||||
|
||||
fs = TRY(Ext2FS::try_create(*description));
|
||||
} else if (fs_type == "9p"sv || fs_type == "Plan9FS"sv) {
|
||||
if (description_or_error.is_error())
|
||||
return EBADF;
|
||||
auto description = description_or_error.release_value();
|
||||
fs = TRY(Plan9FS::try_create(*description));
|
||||
} else if (fs_type == "proc"sv || fs_type == "ProcFS"sv) {
|
||||
fs = TRY(ProcFS::try_create());
|
||||
} else if (fs_type == "devpts"sv || fs_type == "DevPtsFS"sv) {
|
||||
fs = TRY(DevPtsFS::try_create());
|
||||
} else if (fs_type == "dev"sv || fs_type == "DevTmpFS"sv) {
|
||||
fs = TRY(DevTmpFS::try_create());
|
||||
} else if (fs_type == "sys"sv || fs_type == "SysFS"sv) {
|
||||
fs = TRY(SysFS::try_create());
|
||||
} else if (fs_type == "tmp"sv || fs_type == "TmpFS"sv) {
|
||||
fs = TRY(TmpFS::try_create());
|
||||
} else if (fs_type == "iso9660"sv || fs_type == "ISO9660FS"sv) {
|
||||
if (description_or_error.is_error())
|
||||
return EBADF;
|
||||
auto description = description_or_error.release_value();
|
||||
if (!description->file().is_seekable()) {
|
||||
dbgln("mount: this is not a seekable file");
|
||||
return ENODEV;
|
||||
}
|
||||
auto source_pseudo_path = TRY(description->pseudo_path());
|
||||
dbgln("mount: attempting to mount {} on {}", source_pseudo_path, target);
|
||||
fs = TRY(ISO9660FS::try_create(*description));
|
||||
} else {
|
||||
return ENODEV;
|
||||
// Note: Try to determine as early as possible if we deal with a filesystem type
|
||||
// that must be backed by a open file description, so if there's no such valid
|
||||
// description, we can fail with EBADF now.
|
||||
if (filesystem_mount_require_open_file_description(fs_type) && description_or_error.is_error()) {
|
||||
return EBADF;
|
||||
}
|
||||
|
||||
if (!fs)
|
||||
return ENOMEM;
|
||||
if (description_or_error.is_error()) {
|
||||
auto synthetic_filesystem = TRY(create_ram_backed_filesystem_instance(fs_type));
|
||||
TRY(synthetic_filesystem->initialize());
|
||||
TRY(VirtualFileSystem::the().mount(*synthetic_filesystem, target_custody, params.flags));
|
||||
return 0;
|
||||
}
|
||||
auto description = description_or_error.release_value();
|
||||
auto open_file_description_backed_filesystem = TRY(create_open_file_description_backed_filesystem_instance(fs_type, description));
|
||||
auto source_pseudo_path = TRY(description->pseudo_path());
|
||||
dbgln("mount: attempting to mount {} on {}", source_pseudo_path, target);
|
||||
TRY(open_file_description_backed_filesystem->initialize());
|
||||
TRY(VirtualFileSystem::the().mount(*open_file_description_backed_filesystem, target_custody, params.flags));
|
||||
|
||||
TRY(fs->initialize());
|
||||
TRY(VirtualFileSystem::the().mount(fs.release_nonnull(), target_custody, params.flags));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue