From 4f61d2ea04da8d5e37e0f51911594be3b3de29ce Mon Sep 17 00:00:00 2001 From: Mohammed al-Ramadany Date: Tue, 12 Aug 2025 02:17:29 +0300 Subject: [PATCH] [KERNEL32] Fix use-after-free in GetStartupInfoA (#8282) - Set StartupInfo to point to the global BaseAnsiStartupInfo only after the local data has been freed. --- dll/win32/kernel32/client/proc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dll/win32/kernel32/client/proc.c b/dll/win32/kernel32/client/proc.c index 669ede0e2f9..fa46a892132 100644 --- a/dll/win32/kernel32/client/proc.c +++ b/dll/win32/kernel32/client/proc.c @@ -1397,8 +1397,7 @@ GetStartupInfoA(IN LPSTARTUPINFOA lpStartupInfo) break; } - /* Someone beat us to it, use their data instead */ - StartupInfo = BaseAnsiStartupInfo; + /* Someone beat us to it, we will use their data instead */ Status = STATUS_SUCCESS; /* We're going to free our own stuff, but not raise */ @@ -1409,6 +1408,9 @@ GetStartupInfoA(IN LPSTARTUPINFOA lpStartupInfo) RtlFreeAnsiString(&ShellString); } RtlFreeHeap(RtlGetProcessHeap(), 0, StartupInfo); + + /* Get the cached information again: either still NULL or set by another thread */ + StartupInfo = BaseAnsiStartupInfo; } else { @@ -1417,7 +1419,7 @@ GetStartupInfoA(IN LPSTARTUPINFOA lpStartupInfo) } /* Raise an error unless we got here due to the race condition */ - if (!NT_SUCCESS(Status)) RtlRaiseStatus(Status); + if (!StartupInfo) RtlRaiseStatus(Status); } /* Now copy from the cached ANSI version */