Skip to content

Commit 215839e

Browse files
authored
Prevent unwinding through stack bottom (#81770)
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 59dddfd commit 215839e

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
@@ -25,6 +25,25 @@
2525

2626
#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS((expr))
2727

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

@@ -236,6 +255,10 @@ int coreclr_initialize(
236255
PInvokeOverrideFn* pinvokeOverride = nullptr;
237256
host_runtime_contract* hostContract = nullptr;
238257

258+
#ifdef TARGET_UNIX
259+
HostingApiFrameHolder apiFrameHolder(__builtin_frame_address(0));
260+
#endif
261+
239262
ConvertConfigPropertiesToUnicode(
240263
propertyKeys,
241264
propertyValues,
@@ -465,6 +488,10 @@ int coreclr_execute_assembly(
465488
}
466489
*exitCode = -1;
467490

491+
#ifdef TARGET_UNIX
492+
HostingApiFrameHolder apiFrameHolder(__builtin_frame_address(0));
493+
#endif
494+
468495
ICLRRuntimeHost4* host = reinterpret_cast<ICLRRuntimeHost4*>(hostHandle);
469496

470497
ConstWStringArrayHolder argvW;

src/coreclr/vm/exceptionhandling.cpp

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

4540+
extern void* g_hostingApiFrameAddress;
4541+
45404542
//---------------------------------------------------------------------------------------
45414543
//
45424544
// This functions performs dispatching of a managed exception.
@@ -4738,7 +4740,8 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT
47384740

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

4741-
if (controlPc == 0)
4743+
// Consider the exception unhandled if the unwinding cannot proceed further or if it went past the coreclr_initialize or coreclr_execute_assembly
4744+
if ((controlPc == 0) || (sp > (UINT_PTR)g_hostingApiFrameAddress))
47424745
{
47434746
if (!GetThread()->HasThreadStateNC(Thread::TSNC_ProcessedUnhandledException))
47444747
{

0 commit comments

Comments
 (0)