diff --git a/Kernel/Process.h b/Kernel/Process.h index 0699511f8b..8a5c727aed 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -629,7 +629,7 @@ private: RefPtr m_alarm_timer; VeilState m_veil_state { VeilState::None }; - UnveilNode m_unveiled_paths { "/", { .full_path = "/", .unveil_inherited_from_root = true } }; + UnveilNode m_unveiled_paths { "/", { .full_path = "/" } }; OwnPtr m_perf_event_buffer; diff --git a/Kernel/Syscalls/unveil.cpp b/Kernel/Syscalls/unveil.cpp index 0d4d8d9b99..edfee6d6ca 100644 --- a/Kernel/Syscalls/unveil.cpp +++ b/Kernel/Syscalls/unveil.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2021, Max Wipfli * * SPDX-License-Identifier: BSD-2-Clause */ @@ -90,14 +91,12 @@ KResultOr Process::sys$unveil(Userspace u auto it = lexical_path.parts().begin(); auto& matching_node = m_unveiled_paths.traverse_until_last_accessible_node(it, lexical_path.parts().end()); if (it.is_end()) { - auto old_permissions = matching_node.permissions(); - // Allow "elevating" the permissions when the permissions are inherited from root (/), - // as that would be the first time this path is unveiled. - if (old_permissions != UnveilAccess::None || !matching_node.permissions_inherited_from_root()) { - if (new_permissions & ~old_permissions) + // If the path has already been explicitly unveiled, do not allow elevating its permissions. + if (matching_node.was_explicitly_unveiled()) { + if (new_permissions & ~matching_node.permissions()) return EPERM; } - matching_node.set_metadata({ matching_node.path(), (UnveilAccess)new_permissions, true, false }); + matching_node.set_metadata({ matching_node.path(), (UnveilAccess)new_permissions, true }); return 0; } @@ -107,8 +106,9 @@ KResultOr Process::sys$unveil(Userspace u { new_unveiled_path, (UnveilAccess)new_permissions, true }, [](auto& parent, auto& it) -> Optional { auto path = LexicalPath::join(parent.path(), *it).string(); - return UnveilMetadata { path, parent.permissions(), false, parent.permissions_inherited_from_root() }; + return UnveilMetadata { path, parent.permissions(), false }; }); + VERIFY(m_veil_state != VeilState::Locked); m_veil_state = VeilState::Dropped; return 0; diff --git a/Kernel/UnveilNode.h b/Kernel/UnveilNode.h index f1b8036d8c..7590d9c759 100644 --- a/Kernel/UnveilNode.h +++ b/Kernel/UnveilNode.h @@ -27,13 +27,11 @@ struct UnveilMetadata { String full_path; UnveilAccess permissions { None }; bool explicitly_unveiled { false }; - bool unveil_inherited_from_root { false }; // true if permissions are inherited from the tree root (/). }; struct UnveilNode final : public Trie, UnveilNode> { using Trie, UnveilNode>::Trie; - bool permissions_inherited_from_root() const { return this->metadata_value().unveil_inherited_from_root; } bool was_explicitly_unveiled() const { return this->metadata_value().explicitly_unveiled; } UnveilAccess permissions() const { return this->metadata_value().permissions; } const String& path() const { return this->metadata_value().full_path; }