CVE-2024-33904: Insufficient Information (NVD-CWE-noinfo)
value: In plugins/HookSystem.cpp in Hyprland through 0.39.1 (before 28c8561), through a race condition, a local attacker can cause execution of arbitrary assembly code by writing to a predictable temporary file.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
Published: 2024-04-29T06:15Z
Repository: https://github.com/hyprwm/Hyprland
Language: C++
Files changed: src/plugins/HookSystem.cpp
Commit date: 2024-04-28 18:28:19 +0100
Commit message: hooksystem: use a random 700 directory for assembler

Diff: diff --git a/src/plugins/HookSystem.cpp b/src/plugins/HookSystem.cpp
index 59654816..5082f54c 100644
--- a/src/plugins/HookSystem.cpp
+++ b/src/plugins/HookSystem.cpp
@@ -1,8 +1,9 @@
 #include "HookSystem.hpp"
 #include "../debug/Log.hpp"
 #include "../helpers/VarList.hpp"
+#include "../managers/TokenManager.hpp"
 
 #define register
 #include <udis86.h>
 #undef register
 #include <sys/mman.h>
@@ -133,28 +134,34 @@ CFunctionHook::SAssembly CFunctionHook::fixInstructionProbeRIPCalls(const SInstr
 
         lastAsmNewline = probe.assembly.find("\n", lastAsmNewline) + 1;
         currentAddress += len;
     }
 
-    std::ofstream ofs("/tmp/hypr/.hookcode.asm", std::ios::trunc);
+    const auto RANDOMDIR = "/tmp/hypr/" + g_pTokenManager->getRandomUUID();
+
+    if (!std::filesystem::create_directory(RANDOMDIR))
+        return {};
+
+    std::filesystem::permissions(RANDOMDIR, std::filesystem::perms::owner_all, std::filesystem::perm_options::replace);
+
+    std::ofstream ofs(RANDOMDIR + "/.hookcode.asm", std::ios::trunc);
     ofs << assemblyBuilder;
     ofs.close();
-    std::string ret = execAndGet(
-        "cc -x assembler -c /tmp/hypr/.hookcode.asm -o /tmp/hypr/.hookbinary.o 2>&1 && objcopy -O binary -j .text /tmp/hypr/.hookbinary.o /tmp/hypr/.hookbinary2.o 2>&1");
+    std::string ret = execAndGet(std::string{"cc -x assembler -c " + RANDOMDIR + "/.hookcode.asm -o " + RANDOMDIR + "/.hookbinary.o 2>&1 && objcopy -O binary -j .text " +
+                                             RANDOMDIR + "/.hookbinary.o " + RANDOMDIR + "/.hookbinary2.o 2>&1"}
+                                     .c_str());
     Debug::log(LOG, "[functionhook] assembler returned:\n{}", ret);
-    if (!std::filesystem::exists("/tmp/hypr/.hookbinary2.o")) {
-        std::filesystem::remove("/tmp/hypr/.hookcode.asm");
-        std::filesystem::remove("/tmp/hypr/.hookbinary.asm");
+    if (!std::filesystem::exists(RANDOMDIR + "/.hookbinary2.o")) {
+        std::filesystem::remove(RANDOMDIR + "/.hookcode.asm");
+        std::filesystem::remove(RANDOMDIR + "/.hookbinary.asm");
         return {};
     }
 
-    std::ifstream ifs("/tmp/hypr/.hookbinary2.o", std::ios::binary);
+    std::ifstream ifs(RANDOMDIR + "/.hookbinary2.o", std::ios::binary);
     returns = {std::vector<char>(std::istreambuf_iterator<char>(ifs), {})};
     ifs.close();
-    std::filesystem::remove("/tmp/hypr/.hookcode.asm");
-    std::filesystem::remove("/tmp/hypr/.hookbinary.o");
-    std::filesystem::remove("/tmp/hypr/.hookbinary2.o");
+    std::filesystem::remove_all(RANDOMDIR);
 
     return returns;
 }
 
 bool CFunctionHook::hook() {

Vulnerable code:     std::ofstream ofs("/tmp/hypr/.hookcode.asm", std::ios::trunc);
    std::string ret = execAndGet(
        "cc -x assembler -c /tmp/hypr/.hookcode.asm -o /tmp/hypr/.hookbinary.o 2>&1 && objcopy -O binary -j .text /tmp/hypr/.hookbinary.o /tmp/hypr/.hookbinary2.o 2>&1");
    if (!std::filesystem::exists("/tmp/hypr/.hookbinary2.o")) {
        std::filesystem::remove("/tmp/hypr/.hookcode.asm");
        std::filesystem::remove("/tmp/hypr/.hookbinary.asm");
    std::ifstream ifs("/tmp/hypr/.hookbinary2.o", std::ios::binary);
    std::filesystem::remove("/tmp/hypr/.hookcode.asm");
    std::filesystem::remove("/tmp/hypr/.hookbinary.o");
    std::filesystem::remove("/tmp/hypr/.hookbinary2.o");
Fixed code: #include "../managers/TokenManager.hpp"
    const auto RANDOMDIR = "/tmp/hypr/" + g_pTokenManager->getRandomUUID();

    if (!std::filesystem::create_directory(RANDOMDIR))
        return {};

    std::filesystem::permissions(RANDOMDIR, std::filesystem::perms::owner_all, std::filesystem::perm_options::replace);

    std::ofstream ofs(RANDOMDIR + "/.hookcode.asm", std::ios::trunc);
    std::string ret = execAndGet(std::string{"cc -x assembler -c " + RANDOMDIR + "/.hookcode.asm -o " + RANDOMDIR + "/.hookbinary.o 2>&1 && objcopy -O binary -j .text " +
                                             RANDOMDIR + "/.hookbinary.o " + RANDOMDIR + "/.hookbinary2.o 2>&1"}
                                     .c_str());
    if (!std::filesystem::exists(RANDOMDIR + "/.hookbinary2.o")) {
        std::filesystem::remove(RANDOMDIR + "/.hookcode.asm");
        std::filesystem::remove(RANDOMDIR + "/.hookbinary.asm");
    std::ifstream ifs(RANDOMDIR + "/.hookbinary2.o", std::ios::binary);
    std::filesystem::remove_all(RANDOMDIR);