From ff04b320d004884395ddcc1091d08294654f56f0 Mon Sep 17 00:00:00 2001 From: JustVugg Date: Wed, 15 Jul 2026 08:16:20 +0200 Subject: [PATCH] security(win): load coli_cuda.dll by absolute path, never from the CWD (DLL hijack) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit coli_cuda_load did LoadLibraryA("coli_cuda.dll") with a bare name. Windows' default search order includes the current working directory (and, without SafeDllSearchMode, other writable locations), so an attacker who plants a coli_cuda.dll where the user launches glm.exe — or inside a downloaded model directory the user cd's into — gets their DllMain executed at load time: DLL hijacking -> arbitrary code execution. Now the loader resolves the path next to glm.exe via GetModuleFileNameA and loads that exact file with LOAD_WITH_ALTERED_SEARCH_PATH, so both the DLL and its dependency search are anchored to the trusted install directory. Fallback (if GetModuleFileNameA ever fails) uses LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32 — which also excludes the CWD. Cross-compiles clean under mingw-w64; the CPU path is unaffected (this file is _WIN32-only). Note: grammar.h gr__rule memcpy was reviewed in the same pass and is safe (len is clamped to 63 into a name[64] buffer). Co-Authored-By: Claude Opus 4.8 --- c/backend_loader.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/c/backend_loader.c b/c/backend_loader.c index 0635e08..b743d1b 100644 --- a/c/backend_loader.c +++ b/c/backend_loader.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "backend_cuda.h" @@ -136,9 +137,30 @@ static int coli_cuda_load(void){ if(g_cuda.loaded) return g_cuda.available; g_cuda.loaded = 1; - /* Search the model directory first (so a DLL shipped next to the model - * wins), then the engine directory, then the default DLL search path. */ - g_cuda.dll = LoadLibraryA("coli_cuda.dll"); + /* Load coli_cuda.dll from the engine's OWN directory, by absolute path — + * never a bare name. LoadLibraryA("coli_cuda.dll") searches the current + * working directory (and, without SafeDllSearchMode, other writable dirs): + * an attacker who drops a coli_cuda.dll where the user launches glm.exe (or + * inside a downloaded model directory the user cd's into) would get their + * DllMain run at load — classic DLL hijacking -> arbitrary code execution. + * Resolving the path next to glm.exe and loading THAT specific file with + * LOAD_WITH_ALTERED_SEARCH_PATH anchors both the DLL and its dependency + * search to the trusted install directory instead of the CWD. */ + char dllpath[MAX_PATH]; + DWORD mn = GetModuleFileNameA(NULL, dllpath, (DWORD)sizeof(dllpath)); + if(mn > 0 && mn < sizeof(dllpath)){ + char *slash = strrchr(dllpath, '\\'); + if(slash && (size_t)(slash + 1 - dllpath) + sizeof("coli_cuda.dll") <= sizeof(dllpath)){ + strcpy(slash + 1, "coli_cuda.dll"); + g_cuda.dll = LoadLibraryExA(dllpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + } + } + if(!g_cuda.dll){ + /* fallback (GetModuleFileNameA praticamente non fallisce): cerca solo + * nella dir dell'applicazione e in System32, MAI la CWD. */ + g_cuda.dll = LoadLibraryExA("coli_cuda.dll", NULL, + LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); + } if(!g_cuda.dll){ fprintf(stderr, "[CUDA] coli_cuda.dll not found; GPU tier disabled " "(CPU path remains active).\n");