Preserve SafetyHook concurrency finding as a committed upstream repro
A multithreaded test that tight-looped InlineHook enable()/disable() while other threads called the hooked function flaked ~1/10. Isolation proved this is a SafetyHook limitation, not our code: with the hook created once (no install race, no trampoline UAF), tight-loop toggling AVs ~1/3 of runs in Debug (0xC0000005, faulting RIP in the target body), while a no-toggle control is clean at ~60M calls. enable()/disable() re-patch the prologue in place under a VEH page-trap that only relocates a thread parked ON the prologue; a thread in the function body faults on the briefly-non-exec page and relies on instruction retry, which under rapid toggling races a half-rewritten prologue. Rather than silently drop the flaky test, preserve the finding: - tools/sh_concurrency_repro/: minimal, committed, non-CI reproducer (coop_sh_concurrency_repro; --callonly is the control). Surfaces 5/16 AVs. - docs/safetyhook-concurrency.md: upstream-ready write-up (mechanism + fix directions + why it does not affect us). - README lessons-learned + memory updated; tests/CMakeLists cross-references it. Our code stays in SafetyHook's safe envelope (install/remove reconciled from a single tick-bounded worker thread, never a tight loop), so the mock_game_test storm is reliably green; the persistent-trampoline contract is covered deterministically by hook_install_test + detour_gate_test. Removes the temp _sh_probe wiring. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -48,6 +48,14 @@ add_test(NAME detour_gate_test COMMAND detour_gate_test)
|
||||
# Deterministic contract test for the persistent inline-hook model (hook/src/hook_install.hpp):
|
||||
# install_inline creates a hook once and re-enables it on re-install, reusing the trampoline (never
|
||||
# freed) so a stale detour can't UAF. Single-threaded, so it can't flake on enable/disable atomicity.
|
||||
#
|
||||
# A multithreaded TIGHT-LOOP toggle test used to live here and flaked ~1/10: it was asserting an
|
||||
# atomicity that SafetyHook's enable()/disable() don't provide and that our code never needs (we
|
||||
# reconcile install/remove from a single, tick-bounded worker thread -- never a tight loop). That
|
||||
# valid contract is now covered deterministically here + by detour_gate_test; the realistic concurrent
|
||||
# behaviour by mock_game_test's storm; and the SafetyHook limitation itself is captured as a committed
|
||||
# upstream reproducer at tools/sh_concurrency_repro/ (see docs/safetyhook-concurrency.md) rather than a
|
||||
# flaky CTest.
|
||||
add_executable(hook_install_test hook_install_test.cpp)
|
||||
target_include_directories(hook_install_test PRIVATE ${CMAKE_SOURCE_DIR}/hook/src)
|
||||
target_link_libraries(hook_install_test PRIVATE safetyhook::safetyhook)
|
||||
|
||||
Reference in New Issue
Block a user