diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp index c67a38a6dc..be3993fcb1 100644 --- a/Kernel/FileSystem/VirtualFileSystem.cpp +++ b/Kernel/FileSystem/VirtualFileSystem.cpp @@ -361,7 +361,10 @@ KResult VFS::mknod(StringView path, mode_t mode, dev_t dev, Custody& base) KResultOr> VFS::create(StringView path, int options, mode_t mode, Custody& parent_custody, Optional owner) { auto basename = KLexicalPath::basename(path); - if (auto result = validate_path_against_process_veil(String::formatted("{}/{}", parent_custody.absolute_path(), basename), options); result.is_error()) + auto full_path = KLexicalPath::try_join(parent_custody.absolute_path(), basename); + if (!full_path) + return ENOMEM; + if (auto result = validate_path_against_process_veil(full_path->view(), options); result.is_error()) return result; if (!is_socket(mode) && !is_fifo(mode) && !is_block_device(mode) && !is_character_device(mode)) { diff --git a/Kernel/KLexicalPath.cpp b/Kernel/KLexicalPath.cpp index 8e9cc34c98..afc80a884b 100644 --- a/Kernel/KLexicalPath.cpp +++ b/Kernel/KLexicalPath.cpp @@ -55,4 +55,32 @@ Vector parts(StringView const& path) return path.split_view('/'); } +OwnPtr try_join(StringView const& first, StringView const& second) +{ + VERIFY(is_canonical(first)); + VERIFY(is_canonical(second)); + VERIFY(!is_absolute(second)); + + if (first == "/"sv) { + char* buffer; + auto string = KString::try_create_uninitialized(1 + second.length(), buffer); + if (!string) + return {}; + buffer[0] = '/'; + __builtin_memcpy(buffer + 1, second.characters_without_null_termination(), second.length()); + buffer[string->length()] = 0; + return string; + } else { + char* buffer; + auto string = KString::try_create_uninitialized(first.length() + 1 + second.length(), buffer); + if (!string) + return string; + __builtin_memcpy(buffer, first.characters_without_null_termination(), first.length()); + buffer[first.length()] = '/'; + __builtin_memcpy(buffer + first.length() + 1, second.characters_without_null_termination(), second.length()); + buffer[string->length()] = 0; + return string; + } +} + } diff --git a/Kernel/KLexicalPath.h b/Kernel/KLexicalPath.h index 87b7bea87a..b398e7ca81 100644 --- a/Kernel/KLexicalPath.h +++ b/Kernel/KLexicalPath.h @@ -7,6 +7,7 @@ #pragma once #include +#include namespace Kernel::KLexicalPath { @@ -16,4 +17,6 @@ StringView basename(StringView const&); StringView dirname(StringView const&); Vector parts(StringView const&); +OwnPtr try_join(StringView const&, StringView const&); + }