summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2022-08-18 01:03:00 +0200
committerAndreas Kling <kling@serenityos.org>2022-08-18 01:04:28 +0200
commit04c362b4dd130c1874ca7960d79f939d00f6a640 (patch)
tree5d338b8f55221365374448d714a9901d509d9af4
parentae3fa2025283687ed554f81690a81ba5e1ad9c8e (diff)
downloadserenity-04c362b4dd130c1874ca7960d79f939d00f6a640.zip
Kernel: Fix TOCTOU in sys$unveil()
Make sure we reject the unveil attempt with EPERM if the veil was locked by another thread while we were parsing argument (and not holding the veil state spinlock.) Thanks Brian for spotting this! :^) Amendment to #14907.
-rw-r--r--Kernel/Syscalls/unveil.cpp5
1 files changed, 5 insertions, 0 deletions
diff --git a/Kernel/Syscalls/unveil.cpp b/Kernel/Syscalls/unveil.cpp
index 699cbc8aa6..4ffb3cc73a 100644
--- a/Kernel/Syscalls/unveil.cpp
+++ b/Kernel/Syscalls/unveil.cpp
@@ -95,6 +95,11 @@ ErrorOr<FlatPtr> Process::sys$unveil(Userspace<Syscall::SC_unveil_params const*>
auto path_parts = KLexicalPath::parts(new_unveiled_path->view());
auto it = path_parts.begin();
return m_unveil_data.with([&](auto& unveil_data) -> ErrorOr<FlatPtr> {
+ // NOTE: We have to check again, since the veil may have been locked by another thread
+ // while we were parsing the arguments.
+ if (unveil_data.state == VeilState::Locked)
+ return EPERM;
+
auto& matching_node = unveil_data.paths.traverse_until_last_accessible_node(it, path_parts.end());
if (it.is_end()) {
// If the path has already been explicitly unveiled, do not allow elevating its permissions.