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());
|
||||
|
||||
auto* mount = find_mount_for_host_custody(mount_point);
|
||||
if (!mount)
|
||||
return ENODEV;
|
||||
|
||||
mount->set_flags(new_flags);
|
||||
TRY(apply_to_mount_for_host_custody(mount_point, [new_flags](auto& mount) {
|
||||
mount.set_flags(new_flags);
|
||||
}));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -372,25 +370,28 @@ ErrorOr<void> VirtualFileSystem::mount_root(FileSystem& fs)
|
|||
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!
|
||||
if (!current_custody.parent()) {
|
||||
for (auto& mount : mounts) {
|
||||
if (!mount.host_custody())
|
||||
return &mount;
|
||||
if (!mount.host_custody()) {
|
||||
callback(mount);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
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
|
||||
// we would need to return the guest inode, not the host inode.
|
||||
if (auto mount = find_mount_for_host_custody(current_custody)) {
|
||||
child_inode = mount->guest();
|
||||
mount_flags_for_child = mount->flags();
|
||||
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();
|
||||
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));
|
||||
} else {
|
||||
custody = current_custody;
|
||||
|
|
|
@ -114,8 +114,7 @@ private:
|
|||
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: This function is totally unsafe as someone could unmount the returned Mount underneath us.
|
||||
Mount* find_mount_for_host_custody(Custody const& current_custody);
|
||||
ErrorOr<void> apply_to_mount_for_host_custody(Custody const& current_custody, Function<void(Mount&)>);
|
||||
|
||||
RefPtr<Inode> m_root_inode;
|
||||
|
||||
|
|
Loading…
Reference in a new issue