diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index d4daeed10e0..ef5fd4d7e40 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -11,6 +11,7 @@ //#define VFS_DEBUG static VFS* s_the; +static constexpr int symlink_recursion_limit { 5 }; // FIXME: increase? VFS& VFS::the() { @@ -615,7 +616,6 @@ InodeIdentifier VFS::Mount::host() const return m_host_custody->inode().identifier(); } - void VFS::for_each_mount(Function callback) const { for (auto& mount : m_mounts) { @@ -635,10 +635,12 @@ Custody& VFS::root_custody() return *m_root_custody; } -KResultOr> VFS::resolve_path(StringView path, Custody& base, RefPtr* parent_custody, int options) +KResultOr> VFS::resolve_path(StringView path, Custody& base, RefPtr* parent_custody, int options, int symlink_recursion_level) { // FIXME: resolve_path currently doesn't deal with .. and . . If path is ../. and base is /home/anon, it returns // /home/anon/../. instead of /home . + if (symlink_recursion_level >= symlink_recursion_limit) + return KResult(-ELOOP); if (path.is_empty()) return KResult(-EINVAL); @@ -712,13 +714,8 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba if (!symlink_contents) return KResult(-ENOENT); - // FIXME: We should limit the recursion here and return -ELOOP if it goes to deep. - auto symlink_target = resolve_path( - StringView(symlink_contents.data(), - symlink_contents.size()), - current_parent, - parent_custody, - options); + auto symlink_path = StringView(symlink_contents.data(), symlink_contents.size()); + auto symlink_target = resolve_path(symlink_path, current_parent, parent_custody, options, symlink_recursion_level + 1); if (symlink_target.is_error()) return symlink_target; @@ -731,7 +728,7 @@ KResultOr> VFS::resolve_path(StringView path, Custody& ba return symlink_target; StringView remaining_path = path.substring_view_starting_from_substring(parts[i + 1]); - return resolve_path(remaining_path, *symlink_target.value(), parent_custody, options); + return resolve_path(remaining_path, *symlink_target.value(), parent_custody, options, symlink_recursion_level + 1); } } return custody_chain.last(); diff --git a/Kernel/FileSystem/VirtualFileSystem.h b/Kernel/FileSystem/VirtualFileSystem.h index cd1b919012d..626e844b49b 100644 --- a/Kernel/FileSystem/VirtualFileSystem.h +++ b/Kernel/FileSystem/VirtualFileSystem.h @@ -88,7 +88,7 @@ public: void sync(); Custody& root_custody(); - KResultOr> resolve_path(StringView path, Custody& base, RefPtr* parent = nullptr, int options = 0); + KResultOr> resolve_path(StringView path, Custody& base, RefPtr* parent = nullptr, int options = 0, int symlink_recursion_level = 0); private: friend class FileDescription;