Skip to content

Commit 218df16

Browse files
janvorlicarlossanlop
authored andcommitted
Prevent unwinding through stack bottom
When processing unhandled exception on the most recent Alpine 3.17, the libunwind doesn't stop at the bottom frame of the main thread (the caller of `main`) and tries to unwind further. The reason is that the method is missing dwarf unwind information, so the libunwind falls back to using RBP chain, but the RBP points to a garbage and so it ends up crashing with SIGSEGV. While the missing DWARF unwind info seems to be a bug in the Alpine 3.17 (older ones work fine), we can prevent issues like this by stopping at the hosting API boundary and not trying to unwind past that. This is what this PR does.
1 parent 5beb013 commit 218df16

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/coreclr/dlls/mscoree/exports.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@
2323

2424
#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS((expr))
2525

26+
#ifdef TARGET_UNIX
27+
#define NO_HOSTING_API_FRAME_ADDRESS ((void*)ULONG_PTR_MAX)
28+
void* g_hostingApiFrameAddress = NO_HOSTING_API_FRAME_ADDRESS;
29+
30+
class HostingApiFrameHolder
31+
{
32+
public:
33+
HostingApiFrameHolder(void* frameAddress)
34+
{
35+
g_hostingApiFrameAddress = frameAddress;
36+
}
37+
38+
~HostingApiFrameHolder()
39+
{
40+
g_hostingApiFrameAddress = NO_HOSTING_API_FRAME_ADDRESS;
41+
}
42+
};
43+
#endif // TARGET_UNIX
44+
2645
// Holder for const wide strings
2746
typedef NewArrayHolder<const WCHAR> ConstWStringHolder;
2847

@@ -212,6 +231,10 @@ int coreclr_initialize(
212231
bool hostPolicyEmbedded = false;
213232
PInvokeOverrideFn* pinvokeOverride = nullptr;
214233

234+
#ifdef TARGET_UNIX
235+
HostingApiFrameHolder apiFrameHolder(__builtin_frame_address(0));
236+
#endif
237+
215238
ConvertConfigPropertiesToUnicode(
216239
propertyKeys,
217240
propertyValues,
@@ -435,6 +458,10 @@ int coreclr_execute_assembly(
435458
}
436459
*exitCode = -1;
437460

461+
#ifdef TARGET_UNIX
462+
HostingApiFrameHolder apiFrameHolder(__builtin_frame_address(0));
463+
#endif
464+
438465
ICLRRuntimeHost4* host = reinterpret_cast<ICLRRuntimeHost4*>(hostHandle);
439466

440467
ConstWStringArrayHolder argvW;

src/coreclr/vm/exceptionhandling.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4523,6 +4523,8 @@ VOID UnwindManagedExceptionPass2(PAL_SEHException& ex, CONTEXT* unwindStartConte
45234523
EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
45244524
}
45254525

4526+
extern void* g_hostingApiFrameAddress;
4527+
45264528
//---------------------------------------------------------------------------------------
45274529
//
45284530
// This functions performs dispatching of a managed exception.
@@ -4724,7 +4726,8 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT
47244726

47254727
STRESS_LOG2(LF_EH, LL_INFO100, "Processing exception at native frame: IP = %p, SP = %p \n", controlPc, sp);
47264728

4727-
if (controlPc == 0)
4729+
// Consider the exception unhandled if the unwinding cannot proceed further or if it went past the coreclr_initialize or coreclr_execute_assembly
4730+
if ((controlPc == 0) || (sp > (UINT_PTR)g_hostingApiFrameAddress))
47284731
{
47294732
if (!GetThread()->HasThreadStateNC(Thread::TSNC_ProcessedUnhandledException))
47304733
{

0 commit comments

Comments
 (0)