https://bugs.winehq.org/show_bug.cgi?id=53032
Kevin Puetz PuetzKevinA@JohnDeere.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |PuetzKevinA@JohnDeere.com
--- Comment #26 from Kevin Puetz PuetzKevinA@JohnDeere.com --- I'm seeing a similar crash-on-exit in our aarch64 builds of wine-7.0: winedevice.exe and rpcss.exe are both crashing on exit with a similar stack trace: This is gcc 9.2, on a yocto sysroot.
#0 0x0000ffff9428db34 in handle_syscall_fault (rec=0x67f9ed08, context=0x67f9ee20) at ../wine-7.0/dlls/ntdll/unix/unix_private.h:70#1 segv_handler (signal=<optimized out>, siginfo=<optimized out>, sigcontext=0x67f9ee20) at ../wine-7.0/dlls/ntdll/unix/signal_arm64.c:872 #2 <signal handler called> #3 ULongToHandle (ul=<optimized out>) at ../wine-7.0/include/basetsd.h:166 #4 RtlEnterCriticalSection (crit=crit@entry=0x7bcc44f0 <loader_section>) at ../wine-7.0/dlls/ntdll/sync.c:418 #5 0x000000007bc57364 in LdrUnloadDll (hModule=0xffff93c50000 <__wine_spec_pe_header+24768>) at ../wine-7.0/dlls/ntdll/loader.c:3738 #6 LdrUnloadDll (hModule=0xffff93c50000 <__wine_spec_pe_header+24768>) at ../wine-7.0/dlls/ntdll/loader.c:3729 #7 0x000000007b04ee4c in FreeLibrary (module=0xffff93c50000 <__wine_spec_pe_header+24768>) at ../wine-7.0/dlls/kernelbase/loader.c:265 #8 0x0000ffff93e6d8f0 in free_delay_imports () at ../wine-7.0/dlls/winecrt0/delay_load.c:78 #9 0x0000ffff944ce0b8 in _dl_fini () at dl-fini.c:138 #10 0x0000ffff9432e9ec in __run_exit_handlers (status=status@entry=0, listp=0xffff944585e8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:108 #11 0x0000ffff9432eb54 in __GI_exit (status=status@entry=0) at exit.c:139 #12 0x0000ffff9447aa48 in start_thread (arg=0xa3e4a6) at pthread_create.c:500 #13 0x0000ffff943c3f6c in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
The path from _dl_fini -> free_delay_imports -> FreeLibrary seems suspect - By the time pthreads is calling exit (in glibc), because the last thread has returned, we have long since unwound Win32 side of things, including destroying the Teb for that thread via BaseThreadInitThunk -> RtlExitUserThread -> NtTerminateThread -> exit_thread -> virtual_free_teb. So by the time we get to free_delay_imports -> FreeLibrary -> LdrUnloadDll -> RtlEnterCriticalSection( &loader_section ), which does `crit->OwningThread = ULongToHandle(GetCurrentThreadId())`, calling GetCurrentThreadId is a use-after-free if the already-destroyed Teb.
So it seems like free_delay_imports needed to happen earlier, back when when the Win32 aspect of this module was about to be freed (but still valid) (DLL_PROCESS_DETACH after the user's DllImport returned, or __wine_spec_exe_entry between the return from main and the call to ExitProcess()), not put off until libdl is cleaning up the ELF structures.
But referencing it from those places would no longer allow delay_load.c to just be discarded from libwinecrt0.a when __wine_spec_delay_load is unreferenced by the spec.o file. So I'm not quite sure how best to achieve this order of operations.