Ver Fonte

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.
Andreas Kling há 3 anos atrás
pai
commit
04c362b4dd
1 ficheiros alterados com 5 adições e 0 exclusões
  1. 5 0
      Kernel/Syscalls/unveil.cpp

+ 5 - 0
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 path_parts = KLexicalPath::parts(new_unveiled_path->view());
     auto it = path_parts.begin();
     auto it = path_parts.begin();
     return m_unveil_data.with([&](auto& unveil_data) -> ErrorOr<FlatPtr> {
     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());
         auto& matching_node = unveil_data.paths.traverse_until_last_accessible_node(it, path_parts.end());
         if (it.is_end()) {
         if (it.is_end()) {
             // If the path has already been explicitly unveiled, do not allow elevating its permissions.
             // If the path has already been explicitly unveiled, do not allow elevating its permissions.