services: Fix use-after-free during shutdown.
Since rpc processes requests on a work queue, it might hold a referecen to the connection while the main thread is shutting down and freeing the database. When the work item completes, it will release the connection which in turn calls services.exe's rundown function which uses the freed database.
I don't know the trigger condition for this. Logging shows scmdatabase_destroy
isn't always reached (does wineserver kill services.exe?). I think terminating all db->processes
is supposed to cause all services to be destroyed? but in very rare circumstances, a RPCRT4_worker_thread
might be running and hold on to a service preventing it from being freed.
Here is a stack trace for it:
ASan: read of 8 bytes at 00007FFFFF35E660, caller 00006FFFFE40A756 (RtlEnterCriticalSection, ../dlls/ntdll/sync.c:354,13)
stacktrace:
00006FFFFE40A756 (RtlEnterCriticalSection, ../dlls/ntdll/sync.c:354,13)
00007FFFFE0158EA (service_lock, ../programs/services/services.c:750,1)
00007FFFFE002340 (SC_RPC_HANDLE_destroy, ../programs/services/rpc.c:316,13)
00007FFFFE002578 (SC_RPC_HANDLE_rundown, ../programs/services/rpc.c:2190,1)
00006FFFEDD4299F (RpcContextHandle_Destroy, ../dlls/rpcrt4/rpc_assoc.c:559,25)
00006FFFEDD3A9B9 (RpcAssoc_Release, ../dlls/rpcrt4/rpc_assoc.c:210,9)
00006FFFEDD2EA61 (RPCRT4_ReleaseBinding, ../dlls/rpcrt4/rpc_binding.c:244,15)
00006FFFEDD2EFF1 (RPCRT4_ReleaseConnection, ../dlls/rpcrt4/rpc_transport.c:3407,41)
00006FFFEDD376B0 (RPCRT4_worker_thread, ../dlls/rpcrt4/rpc_server.c:539,3)
00006FFFFE4EA2E3 (NtCurrentTeb, ../include/winnt.h:2484,5 <- GetProcessHeap, ../include/winbase.h:2686,24 <- process_rtl_work_item, ../dlls/ntdll/threadpool.c:414,5)
00006FFFFE5044AF (tp_object_execute, ../dlls/ntdll/threadpool.c:2234,13)
00006FFFFE501169 (threadpool_worker_proc, ../dlls/ntdll/threadpool.c:2366,13)
00006FFFFD074FC3 (BaseThreadInitThunk, ../dlls/kernel32/thread.c:61,5)
00006FFFFE3DFDB3 (RtlUserThreadStart)
info:
heap-use-after-free, addr 00007FFFFF35E660
allocated user region: [00007FFFFF35E610, 00007FFFFF35E668) 88
allocated by 7c0
00006FFFFE3F7962 (RtlAllocateHeap, ../dlls/ntdll/heap.c:2320,5)
00006FFFF794E8E3 (msvcrt_heap_alloc, ../dlls/msvcrt/heap.c:72,1)
00006FFFF7946070 (malloc, ../dlls/msvcrt/heap.c:436,15)
00007FFFFE013CBE (scmdatabase_create, ../programs/services/services.c:626,11)
00007FFFFE00E7B2 (main, ../programs/services/services.c:1310,11)
00007FFFFE00EB50 (mainCRTStartup, ../dlls/msvcrt/crt_main.c:60,11)
00006FFFFD074FC3 (BaseThreadInitThunk, ../dlls/kernel32/thread.c:61,5)
00006FFFFE3DFDB3 (RtlUserThreadStart)
freed by 1290
00006FFFFE4116BD (RtlFreeHeap, ../dlls/ntdll/heap.c:2429,13)
00006FFFF794E9AB (msvcrt_heap_free, ../dlls/msvcrt/heap.c:115,1)
00006FFFF7932DA0 (free, ../dlls/msvcrt/heap.c:415,1)
00007FFFFE013FD0 (scmdatabase_destroy, ../programs/services/services.c:652,1)
00007FFFFE00E91F (main, ../programs/services/services.c:1332,9)
00007FFFFE00EB50 (mainCRTStartup, ../dlls/msvcrt/crt_main.c:60,11)
00006FFFFD074FC3 (BaseThreadInitThunk, ../dlls/kernel32/thread.c:61,5)
00006FFFFE3DFDB3 (RtlUserThreadStart)
Solution here is very dumb, please let me know if there's a better way.