mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-14 20:03:29 +00:00
Kernel/VFS: Check matching absolute path when jump to mount guest inode
We could easily encounter a case where we do the following: ``` mkdir -p /tmp2 mount /dev/hda /tmp2 ``` would produce a bug that doing `ls /tmp2/tmp2` will give the contents on `/dev/hda` ext2 root directory and also on `/tmp2/tmp2/tmp2` and so on. To prevent this, we must compare the current custody against each mount entry's custody to ensure their paths match.
This commit is contained in:
parent
80f400a150
commit
e5c7662638
|
@ -378,12 +378,23 @@ ErrorOr<void> VirtualFileSystem::mount_root(FileSystem& fs)
|
|||
return {};
|
||||
}
|
||||
|
||||
auto VirtualFileSystem::find_mount_for_host(InodeIdentifier id) -> Mount*
|
||||
auto VirtualFileSystem::find_mount_for_host_custody(Custody const& current_custody) -> Mount*
|
||||
{
|
||||
return m_mounts.with([&](auto& mounts) -> Mount* {
|
||||
for (auto& mount : mounts) {
|
||||
if (mount.host() && mount.host()->identifier() == id)
|
||||
return &mount;
|
||||
// NOTE: We either search for the root mount or for a mount that has a parent custody!
|
||||
if (!current_custody.parent()) {
|
||||
for (auto& mount : mounts) {
|
||||
if (!mount.host_custody())
|
||||
return &mount;
|
||||
}
|
||||
// NOTE: There must be a root mount entry, so fail if we don't find it.
|
||||
VERIFY_NOT_REACHED();
|
||||
} else {
|
||||
for (auto& mount : mounts) {
|
||||
if (mount.host_custody() && check_matching_absolute_path_hierarchy(*mount.host_custody(), current_custody)) {
|
||||
return &mount;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
|
@ -1232,15 +1243,18 @@ ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(Cre
|
|||
|
||||
int mount_flags_for_child = parent.mount_flags();
|
||||
|
||||
auto current_custody = TRY(Custody::try_create(&parent, part, *child_inode, mount_flags_for_child));
|
||||
|
||||
// See if there's something mounted on the child; in that case
|
||||
// we would need to return the guest inode, not the host inode.
|
||||
if (auto mount = find_mount_for_host(child_inode->identifier())) {
|
||||
if (auto mount = find_mount_for_host_custody(current_custody)) {
|
||||
child_inode = mount->guest();
|
||||
mount_flags_for_child = mount->flags();
|
||||
custody = TRY(Custody::try_create(&parent, part, *child_inode, mount_flags_for_child));
|
||||
} else {
|
||||
custody = current_custody;
|
||||
}
|
||||
|
||||
custody = TRY(Custody::try_create(&parent, part, *child_inode, mount_flags_for_child));
|
||||
|
||||
if (child_inode->metadata().is_symlink()) {
|
||||
if (!have_more_parts) {
|
||||
if (options & O_NOFOLLOW)
|
||||
|
|
|
@ -119,7 +119,7 @@ private:
|
|||
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);
|
||||
Mount* find_mount_for_host_custody(Custody const& current_custody);
|
||||
Mount* find_mount_for_guest(InodeIdentifier);
|
||||
|
||||
RefPtr<Inode> m_root_inode;
|
||||
|
|
Loading…
Reference in a new issue