security(win): load coli_cuda.dll by absolute path, never from the CWD (DLL hijack)
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 <noreply@anthropic.com>
This commit is contained in:
+25
-3
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <windows.h>
|
||||
|
||||
#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");
|
||||
|
||||
Reference in New Issue
Block a user