[PATCH] wineboot: Prevent infinite loops when restarting the 64-bit wineboot.

Francois Gouget fgouget at codeweavers.com
Wed Apr 14 09:11:43 CDT 2021


Sometimes, when the wineprefix is broken, trying to switch to the 64-bit
wineboot starts the 32-bit executable instead, resulting in a slow-burn
fork bomb. Fortunately this is rare but typically results in a session
crash and the loss of unsaved unrelated documents.
So detect and nip infinite restart loops in the bud.

Signed-off-by: Francois Gouget <fgouget at codeweavers.com>
---
The troublesome code has been present for the past 10 years so this 
issue is pretty rare. So an alternative would be to just ignore it.
But because of the potential for data loss in unrelated applications I'd 
still feel better if this fork-bomb had a safety pin.
---
 programs/wineboot/wineboot.c | 42 +++++++++++++++++++++++-------------
 1 file changed, 27 insertions(+), 15 deletions(-)

diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 9427448b612..9d87c26c207 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -1616,27 +1616,39 @@ int __cdecl main( int argc, char *argv[] )
 
     if (IsWow64Process( GetCurrentProcess(), &is_wow64 ) && is_wow64)
     {
-        STARTUPINFOW si;
-        PROCESS_INFORMATION pi;
         WCHAR filename[MAX_PATH];
-        void *redir;
-        DWORD exit_code;
 
-        memset( &si, 0, sizeof(si) );
-        si.cb = sizeof(si);
         GetModuleFileNameW( 0, filename, MAX_PATH );
-
-        Wow64DisableWow64FsRedirection( &redir );
-        if (CreateProcessW( filename, GetCommandLineW(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
+        if (GetEnvironmentVariableA("RESTARTING_64BIT_WINEBOOT", NULL, 0)
+            && GetLastError() != ERROR_ENVVAR_NOT_FOUND)
+        {
+            WINE_ERR( "got an infinite loop while starting the 64-bit %s\n", wine_dbgstr_w(filename) );
+        }
+        else
         {
-            WINE_TRACE( "restarting %s\n", wine_dbgstr_w(filename) );
-            WaitForSingleObject( pi.hProcess, INFINITE );
-            GetExitCodeProcess( pi.hProcess, &exit_code );
-            ExitProcess( exit_code );
+            STARTUPINFOW si;
+            PROCESS_INFORMATION pi;
+            void *redir;
+            DWORD exit_code;
+
+            Wow64DisableWow64FsRedirection( &redir );
+            SetEnvironmentVariableA("RESTARTING_64BIT_WINEBOOT", "1");
+
+            memset( &si, 0, sizeof(si) );
+            si.cb = sizeof(si);
+            if (CreateProcessW( filename, GetCommandLineW(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi ))
+            {
+                WINE_TRACE( "restarting %s\n", wine_dbgstr_w(filename) );
+                WaitForSingleObject( pi.hProcess, INFINITE );
+                GetExitCodeProcess( pi.hProcess, &exit_code );
+                ExitProcess( exit_code );
+            }
+            else WINE_ERR( "failed to restart 64-bit %s, err %d\n", wine_dbgstr_w(filename), GetLastError() );
+
+            Wow64RevertWow64FsRedirection( redir );
         }
-        else WINE_ERR( "failed to restart 64-bit %s, err %d\n", wine_dbgstr_w(filename), GetLastError() );
-        Wow64RevertWow64FsRedirection( redir );
     }
+    SetEnvironmentVariableA("RESTARTING_64BIT_WINEBOOT", NULL);
 
     for (i = 1; i < argc; i++)
     {
-- 
2.20.1




More information about the wine-devel mailing list