From 629501049fb2fd1a275e33a8194f861d0fce75d8 Mon Sep 17 00:00:00 2001 From: Sergey Bugaev Date: Wed, 12 Jun 2019 16:36:05 +0300 Subject: [PATCH] Kernel: Fix resolving symlinks in the middle of a path. If a symlink is not the last part of a path, the remaining part of the path has to be further resolved against the symlink target. With this, a path containing a symlink always resolves to the target of the first (leftmost) symlink in it, for example any path of form /proc/self/... resolves to the corresponding /proc/pid directory. --- Kernel/FileSystem/VirtualFileSystem.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index 14d315bb6f..5c68b50706 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -697,12 +697,28 @@ KResultOr> VFS::resolve_path(StringView path, Custody& base, R return KResult(-ENOENT); // FIXME: We should limit the recursion here and return -ELOOP if it goes to deep. - return resolve_path( + auto symlink_target = resolve_path( StringView(symlink_contents.pointer(), symlink_contents.size()), *current_parent, parent_custody, options); + + if (symlink_target.is_error()) + return symlink_target; + + bool have_more_parts = i + 1 < parts.size(); + if (i + 1 == parts.size() - 1 && parts[i + 1].is_empty()) + have_more_parts = false; + + if (!have_more_parts) + return symlink_target; + + const char* remaining_path_chars = parts[i + 1].characters(); + int remaining_path_length = path.length() - (remaining_path_chars - path.characters()); + StringView remaining_path { remaining_path_chars, remaining_path_length }; + + return resolve_path(remaining_path, *symlink_target.value(), parent_custody, options); } } return custody_chain.last();