Restore ucontext on faulted paths - #781
Open
zhengyu123 wants to merge 6 commits into
Open
Conversation
Contributor
|
🔗 Commit SHA: 46443bf | Docs | View more details | Give us feedback! |
Contributor
Scan-Build Report
Bug Summary
Reports
|
||||||||||||||||||||||||||||||||||||
Contributor
CI Test ResultsRun: #33906137112 | Commit:
Status Overview
Legend: ✅ passed | ❌ failed | ⚪ skipped | 🚫 cancelled Summary: Total: 32 | Passed: 32 | Failed: 0 Updated: 2026-09-04 20:13:50 UTC |
Contributor
zhengyu123
marked this pull request as ready for review
September 4, 2026 20:38
Contributor
There was a problem hiding this comment.
More details
The recovery path restores pc, sp, and fp after a recoverable fault. It also keeps a valid partial trace and marks it as truncated.
🤖 Datadog Autotest · Commit 46443bf · What is Autotest? · @DataDog review to ask questions · Any feedback? Reach out in #autotest
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?:
Fixes a corrupted-ucontext bug on the async Java stack-walk path and adds regression coverage for it:
HotspotSupport::getJavaTraceAsync()mutates the real signalucontext's pc/sp/fp in place while it feeds them to HotSpot's ownAsyncGetCallTrace(viaframe.restore()/unwindStub()/unwindCompiled(), and thePROBE_SPretry loop). It restores them itself on every normal exit path, but aSIGSEGVthat strikes mid-mutation was caught byProfiler::checkFault()andsiglongjmp'd straight past those restores — leaving the actual ucontext the kernel uses to resume the sampled thread corrupted.HotspotSupport::withUcontextFaultRecovery(), a reusable sigsetjmp/siglongjmp crash-protection wrapper: it snapshots pc/sp/fp before running the protected work, chains aJmpCtxScopeon the currentProfiledThread, and restores the snapshot in the recovery branch ifcheckFault()recovers a fault.walkJavaStack()now dispatches through it instead of hand-rolling the same protocol inline.StackFrame::RegisterSnapshot, shared by bothgetJavaTraceAsync()'s own restore and the new recovery wrapper.getJavaTraceAsync()has already returned a valid frame count and filled the frame buffer (e.g. insidefillFrameTypes()or the virtual-thread continuation check) now reports that partial trace as truncated instead of discarding it as zero frames.hotspot_crash_protection_ut.cpp'sWalkJavaStackUcontextRestoreTestsuite to call the realHotspotSupport::withUcontextFaultRecovery()directly (driven through the actualProfiler::checkFault(), not a hand-simulatedsiglongjmp), and adds anINJECT_FAULT_ADDRESS_UNLIKELYsite on the unguarded anchor-derivedspdereference ingetJavaTraceAsync()so the recovery path is exercised for real rather than only in the unit test's simulated walk.Motivation:
A profiling signal can interrupt a sampled thread at any point, including mid-way through
getJavaTraceAsync()'s in-place mutation of that thread's own signalucontext. If the resultingSIGSEGVis recovered bycheckFault()without putting pc/sp/fp back the way they were, the signal handler returns and the kernel resumes the sampled thread with a corrupted register set instead of its real one — a crash indistinguishable from stack corruption in the profiled process itself (see branch name).Additional Notes:
withUcontextFaultRecovery()'s recovery branch takes atruncatedflag and an optionalpartial_resultout-parameter, mirroring howwalkJavaStack()already reported partial/truncated traces before this refactor — no behavior change there beyond fixing the "recovered fault discards an already-valid partial trace" bug described above.Profiler::checkFault()only recovers faults whose PC falls inside this library's own address range; a fault insidelibjvm.so(e.g.AsyncGetCallTraceitself dereferencing a poisoned sp/pc/fp) is deliberately not recovered here, and the new unit tests exercise both sides of that gate via theUNIT_TEST-onlyProfiler::setAddressRangeForTest().How to test the change?:
Covered by
hotspot_crash_protection_ut.cpp'sWalkJavaStackUcontextRestoreTestsuite:FaultInsideProfilerRangeRecoversAndRestoresUcontext— a fault inside this library's range is recovered and the ucontext's pc/sp/fp are restored to their pre-walk values.FaultOutsideProfilerRangeIsNotRecoveredAndLeavesUcontextCorrupted— a fault outside the range (standing in for a fault insidelibjvm.so) is not recovered, and the mutated ucontext is left as-is.NullUcontextSkipsRestoreWithoutCrashing— a null ucontext (e.g. malloc/socket hooks sampled outside any signal context) doesn't crash the recovery branch.These drive the real production
withUcontextFaultRecovery()through the realProfiler::checkFault(), so a regression to the actual recovery branch (e.g. dropping the ucontext restore) fails these tests too, not just a hand-rolled replica of the same logic.For Datadog employees:
credentials of any kind, I've requested a security review (run the
dd:platform-security-reviewskill, or file a request via the PSEC review form).
bewairealso runs automatically on every PR.Unsure? Have a question? Request a review!