mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 01:20:25 +00:00
Kernel/VFS: Ensure Custodies' absolute path don't match before mounting
This ensures that the host mount point custody path is not the same like the new to-be-mounted custody. A scenario that could happen before adding this check is: ``` mkdir -p /tmp2 mount /dev/hda /tmp2/ mount /dev/hda /tmp2/ mount /dev/hda /tmp2/ # this will fail here ``` and after adding this check, the following scenario is now this: ``` mkdir -p /tmp2 mount /dev/hda /tmp2/ mount /dev/hda /tmp2/ # this will fail here mount /dev/hda /tmp2/ # this will fail here too ```
This commit is contained in:
parent
8da7d84512
commit
debbfe07fb
Notes:
sideshowbarker
2024-07-16 23:34:44 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/debbfe07fb Pull-request: https://github.com/SerenityOS/serenity/pull/20358 Reviewed-by: https://github.com/gmta ✅
2 changed files with 30 additions and 9 deletions
|
@ -100,11 +100,31 @@ InodeIdentifier VirtualFileSystem::root_inode_id() const
|
|||
return m_root_inode->identifier();
|
||||
}
|
||||
|
||||
bool VirtualFileSystem::mount_point_exists_at_inode(InodeIdentifier inode_identifier)
|
||||
bool VirtualFileSystem::check_matching_absolute_path_hierarchy(Custody const& first_custody, Custody const& second_custody)
|
||||
{
|
||||
// Are both custodies the root mount?
|
||||
if (!first_custody.parent() && !second_custody.parent())
|
||||
return true;
|
||||
if (first_custody.name() != second_custody.name())
|
||||
return false;
|
||||
auto const* custody1 = &first_custody;
|
||||
auto const* custody2 = &second_custody;
|
||||
while (custody1->parent()) {
|
||||
if (!custody2->parent())
|
||||
return false;
|
||||
if (custody1->parent().ptr() != custody2->parent().ptr())
|
||||
return false;
|
||||
custody1 = custody1->parent();
|
||||
custody2 = custody2->parent();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VirtualFileSystem::mount_point_exists_at_custody(Custody& mount_point)
|
||||
{
|
||||
return m_mounts.with([&](auto& mounts) -> bool {
|
||||
return any_of(mounts, [&inode_identifier](auto const& existing_mount) {
|
||||
return existing_mount.host() && existing_mount.host()->identifier() == inode_identifier;
|
||||
return any_of(mounts, [&mount_point](auto const& existing_mount) {
|
||||
return existing_mount.host_custody() && check_matching_absolute_path_hierarchy(*existing_mount.host_custody(), mount_point);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -113,14 +133,14 @@ ErrorOr<void> VirtualFileSystem::add_file_system_to_mount_table(FileSystem& file
|
|||
{
|
||||
auto new_mount = TRY(adopt_nonnull_own_or_enomem(new (nothrow) Mount(file_system, &mount_point, flags)));
|
||||
return m_mounts.with([&](auto& mounts) -> ErrorOr<void> {
|
||||
auto& inode = mount_point.inode();
|
||||
auto& mount_point_inode = mount_point.inode();
|
||||
dbgln("VirtualFileSystem: FileSystemID {}, Mounting {} at inode {} with flags {}",
|
||||
file_system.fsid(),
|
||||
file_system.class_name(),
|
||||
inode.identifier(),
|
||||
mount_point_inode.identifier(),
|
||||
flags);
|
||||
if (mount_point_exists_at_inode(inode.identifier())) {
|
||||
dbgln("VirtualFileSystem: Mounting unsuccessful - inode {} is already a mount-point.", inode.identifier());
|
||||
if (mount_point_exists_at_custody(mount_point)) {
|
||||
dbgln("VirtualFileSystem: Mounting unsuccessful - inode {} is already a mount-point.", mount_point_inode.identifier());
|
||||
return EBUSY;
|
||||
}
|
||||
// Note: Actually add a mount for the filesystem and increment the filesystem mounted count
|
||||
|
@ -211,7 +231,7 @@ ErrorOr<void> VirtualFileSystem::bind_mount(Custody& source, Custody& mount_poin
|
|||
return m_mounts.with([&](auto& mounts) -> ErrorOr<void> {
|
||||
auto& inode = mount_point.inode();
|
||||
dbgln("VirtualFileSystem: Bind-mounting inode {} at inode {}", source.inode().identifier(), inode.identifier());
|
||||
if (mount_point_exists_at_inode(inode.identifier())) {
|
||||
if (mount_point_exists_at_custody(mount_point)) {
|
||||
dbgln("VirtualFileSystem: Bind-mounting unsuccessful - inode {} is already a mount-point.",
|
||||
mount_point.inode().identifier());
|
||||
return EBUSY;
|
||||
|
|
|
@ -115,7 +115,8 @@ private:
|
|||
|
||||
ErrorOr<void> traverse_directory_inode(Inode&, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>);
|
||||
|
||||
bool mount_point_exists_at_inode(InodeIdentifier inode);
|
||||
static bool check_matching_absolute_path_hierarchy(Custody const& first_custody, Custody const& second_custody);
|
||||
bool mount_point_exists_at_custody(Custody& mount_point);
|
||||
|
||||
// FIXME: These functions are totally unsafe as someone could unmount the returned Mount underneath us.
|
||||
Mount* find_mount_for_host(InodeIdentifier);
|
||||
|
|
Loading…
Reference in a new issue