When debugging use-after-free(UAF) bugs, knowing when the object reaches 0 references and enters final release(final put) can significantly aid the debugging process.
This patch series adds a tracepoint, refcount_final_put, with compilation toggleable with CONFIG_REFCOUNT_TRACE_FINAL_PUT. refcount_final_put fires when a reference count reaches zero and the object enters its final release path. refcount_final_put records three fields: - caller: function that called the refcounting function(refcount_sub_and_test, percpu_ref_put_many) - ip: return address of trace wrapper macro call - obj: refcount object(struct percpu_ref, refcount_t) bloat-o-meter stats: CONFIG_REFCOUNT_TRACE_FINAL_PUT=n : Total: Before=24703933, After=24703933, chg +0.00% CONFIG_REFCOUNT_TRACE_FINAL_PUT=y : Total: Before=24703933, After=24764816, chg +0.25% Alternatives to obtain this information require live reproduction, and incur a significant performance cost, making them impractical to have enabled on fuzzers like syzbot. refcount functions performing final-puts are also inlined, further complicating alternative dynamic tracing possibilities. Debugging UAFs without final-put knowledge is possible but is often significantly harder and requires broad code reading and mapping, whereas knowing the final-put allows narrowing the scope, thus decreasing time and effort required. Local live reproduction and alternative tracing are time, hardware resource, and manual effort exhaustive. Time-sensitive UAFs which require many iterations to reproduce further worsen these requirements. Remote-fuzzer report based UAF debugging is an incredibly frequent occurence. Signed-off-by: Eugene Mavick <[email protected]> --- Changes in v5: -rename ref_trace to refcount -add CONFIG_REFCOUNT_TRACE_FINAL_PUT Kconfig option, due to high footprint -improve cover letter, add bloat-o-meter statistics v4: https://lore.kernel.org/r/[email protected] Changes in v4: ref-trace: -remove fn -add ip variable -change trace wrapper macro respectively, _THIS_IP_ is used for ip variable -change relevant code respect to fn removal and ip addition -fix style issues in include/linux/ref_trace.h -add new macro do_trace_ref_final_put_cond that only calls tracepoint if cond is true lib/refcount.c: -change from do_trace_ref_final_put to *_cond -remove if statement above since _cond already performs the check KUnit: -change relevant code respect to fn removal and ip addition -check if caller and ip are valid addresses -change timeout from 10 jiffies to 10 seconds -move didn't timeout assertion from before to after probe unregistration, to prevent it from impacting next test Changes in v3: include/trace/events/ref_trace.h kernel doc comments: -caller of refcount function -> return address of refcount function -ref_trace_final_put->do_ref_trace_final_put lib/ref_trace.c: add include trace/events/ref_trace.h kunit: -change Kconfig depends from FTRACE->TRACEPOINTS -EXPECT_FALSE->ASSERT_FALSE for calling percpu_ref_init -add tracepoint_synchronise_unregister to test_exit macro -added timeout to capture.count waiting -remove noinline and __always_inline from function attributes (added for testing, but accidentally submitted) -add period to the end of Kconfig help text v2 link: https://lore.kernel.org/all/[email protected]/ Changes in v2: -include/linux/ref_trace.h: change macro name, use direct tracepoint call in macro to avoid double check -add tracepoint to refcount_dec_if_one -kunit: make significant improvements to design, fix critical bug, add test case for refcount_dec_if_one() -Link to v1: https://lore.kernel.org/r/[email protected] --- Eugene Mavick (5): tracing: add refcount_final_put tracepoint refcount: add refcount_final_put tracepoint percpu-refcount: add refcount_final_put tracepoint kunit: add test for refcount_final_put MAINTAINERS: add entries for refcount_final_put trace MAINTAINERS | 3 + include/linux/percpu-refcount.h | 5 +- include/linux/refcount.h | 2 + include/linux/refcount_trace.h | 33 +++++++++ include/trace/events/refcount.h | 55 +++++++++++++++ lib/Kconfig | 18 +++++ lib/Makefile | 2 + lib/refcount.c | 6 +- lib/refcount_trace.c | 14 ++++ lib/tests/Makefile | 1 + lib/tests/refcount_trace_kunit.c | 141 +++++++++++++++++++++++++++++++++++++++ 11 files changed, 278 insertions(+), 2 deletions(-) --- base-commit: df685633c3dbc67441cc86f1c3fee58de4652ba2 change-id: 20260624-refcount-final-put-trace-49bd7c39bd5a Best regards, -- Eugene Mavick <[email protected]>
