mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
Kernel/VFS: Ensure working with mount entry per a custody is safe
Previously we could get a raw pointer to a Mount object which might be invalid when actually dereferencing it. To ensure this could not happen, we should just use a callback that will be used immediately after finding the appropriate Mount entry, while holding the mount table lock.
This commit is contained in:
parent
d216f780a4
commit
5efb91ec06
Notes:
sideshowbarker
2024-07-16 23:38:54 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/5efb91ec06 Pull-request: https://github.com/SerenityOS/serenity/pull/20358 Reviewed-by: https://github.com/gmta ✅
2 changed files with 18 additions and 16 deletions
|
@ -245,11 +245,9 @@ ErrorOr<void> VirtualFileSystem::remount(Custody& mount_point, int new_flags)
|
||||||
{
|
{
|
||||||
dbgln("VirtualFileSystem: Remounting inode {}", mount_point.inode().identifier());
|
dbgln("VirtualFileSystem: Remounting inode {}", mount_point.inode().identifier());
|
||||||
|
|
||||||
auto* mount = find_mount_for_host_custody(mount_point);
|
TRY(apply_to_mount_for_host_custody(mount_point, [new_flags](auto& mount) {
|
||||||
if (!mount)
|
mount.set_flags(new_flags);
|
||||||
return ENODEV;
|
}));
|
||||||
|
|
||||||
mount->set_flags(new_flags);
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,25 +370,28 @@ ErrorOr<void> VirtualFileSystem::mount_root(FileSystem& fs)
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto VirtualFileSystem::find_mount_for_host_custody(Custody const& current_custody) -> Mount*
|
ErrorOr<void> VirtualFileSystem::apply_to_mount_for_host_custody(Custody const& current_custody, Function<void(Mount&)> callback)
|
||||||
{
|
{
|
||||||
return m_mounts.with([&](auto& mounts) -> Mount* {
|
return m_mounts.with([&](auto& mounts) -> ErrorOr<void> {
|
||||||
// NOTE: We either search for the root mount or for a mount that has a parent custody!
|
// NOTE: We either search for the root mount or for a mount that has a parent custody!
|
||||||
if (!current_custody.parent()) {
|
if (!current_custody.parent()) {
|
||||||
for (auto& mount : mounts) {
|
for (auto& mount : mounts) {
|
||||||
if (!mount.host_custody())
|
if (!mount.host_custody()) {
|
||||||
return &mount;
|
callback(mount);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// NOTE: There must be a root mount entry, so fail if we don't find it.
|
// NOTE: There must be a root mount entry, so fail if we don't find it.
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
} else {
|
} else {
|
||||||
for (auto& mount : mounts) {
|
for (auto& mount : mounts) {
|
||||||
if (mount.host_custody() && check_matching_absolute_path_hierarchy(*mount.host_custody(), current_custody)) {
|
if (mount.host_custody() && check_matching_absolute_path_hierarchy(*mount.host_custody(), current_custody)) {
|
||||||
return &mount;
|
callback(mount);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return Error::from_errno(ENODEV);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1225,9 +1226,11 @@ ErrorOr<NonnullRefPtr<Custody>> VirtualFileSystem::resolve_path_without_veil(Cre
|
||||||
|
|
||||||
// See if there's something mounted on the child; in that case
|
// See if there's something mounted on the child; in that case
|
||||||
// we would need to return the guest inode, not the host inode.
|
// we would need to return the guest inode, not the host inode.
|
||||||
if (auto mount = find_mount_for_host_custody(current_custody)) {
|
auto found_mount_or_error = apply_to_mount_for_host_custody(current_custody, [&child_inode, &mount_flags_for_child](auto& mount) {
|
||||||
child_inode = mount->guest();
|
child_inode = mount.guest();
|
||||||
mount_flags_for_child = mount->flags();
|
mount_flags_for_child = mount.flags();
|
||||||
|
});
|
||||||
|
if (!found_mount_or_error.is_error()) {
|
||||||
custody = TRY(Custody::try_create(&parent, part, *child_inode, mount_flags_for_child));
|
custody = TRY(Custody::try_create(&parent, part, *child_inode, mount_flags_for_child));
|
||||||
} else {
|
} else {
|
||||||
custody = current_custody;
|
custody = current_custody;
|
||||||
|
|
|
@ -114,8 +114,7 @@ private:
|
||||||
static bool check_matching_absolute_path_hierarchy(Custody const& first_custody, Custody const& second_custody);
|
static bool check_matching_absolute_path_hierarchy(Custody const& first_custody, Custody const& second_custody);
|
||||||
bool mount_point_exists_at_custody(Custody& mount_point);
|
bool mount_point_exists_at_custody(Custody& mount_point);
|
||||||
|
|
||||||
// FIXME: This function is totally unsafe as someone could unmount the returned Mount underneath us.
|
ErrorOr<void> apply_to_mount_for_host_custody(Custody const& current_custody, Function<void(Mount&)>);
|
||||||
Mount* find_mount_for_host_custody(Custody const& current_custody);
|
|
||||||
|
|
||||||
RefPtr<Inode> m_root_inode;
|
RefPtr<Inode> m_root_inode;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue