git: dc761982793e - stable/14 - epoch: Fix use-after-free in epoch_trace_report()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 28 Oct 2026 20:41:26 UTC
The branch stable/14 has been updated by rcm:
URL: https://cgit.FreeBSD.org/src/commit/?id=dc761982793e0e4eb360a205f3e73eacc00fd185
commit dc761982793e0e4eb360a205f3e73eacc00fd185
Author: R. Christian McDonald <rcm@FreeBSD.org>
AuthorDate: 2026-09-30 13:41:53 +0000
Commit: R. Christian McDonald <rcm@FreeBSD.org>
CommitDate: 2026-10-28 20:38:03 +0000
epoch: Fix use-after-free in epoch_trace_report()
epoch_trace_report() assigned the return value of RB_INSERT() back to
the new element. When two threads report the same stack concurrently,
the loser's RB_INSERT() returns the element already in the tree, and
that element was freed while still linked, leaking the new allocation.
The next lookup touches freed memory; KASAN catches it as a
use-after-free.
Keep the return value separate and free the new element instead. The
thread that won the race prints the report, so return without printing
it a second time.
Reviewed by: markj
Fixes: 173c062a569b ("Improve EPOCH_TRACE")
MFC after: 1 week
Sponsored by: Rubicon Communications, LLC ("Netgate")
Differential Revision: https://reviews.freebsd.org/D60162
(cherry picked from commit dd5dc8f6e51c5132f2dc885f5c1b0492cdf3052c)
---
sys/kern/subr_epoch.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/sys/kern/subr_epoch.c b/sys/kern/subr_epoch.c
index 84ccce9f77b2..24147629186a 100644
--- a/sys/kern/subr_epoch.c
+++ b/sys/kern/subr_epoch.c
@@ -194,6 +194,7 @@ epoch_trace_report(const char *fmt, ...)
{
va_list ap;
struct stackentry se, *new;
+ bool dup;
stack_save(&se.se_stack);
@@ -206,10 +207,13 @@ epoch_trace_report(const char *fmt, ...)
bcopy(&se.se_stack, &new->se_stack, sizeof(struct stack));
mtx_lock(&epoch_stacks_lock);
- new = RB_INSERT(stacktree, &epoch_stacks, new);
+ dup = RB_INSERT(stacktree, &epoch_stacks, new) != NULL;
mtx_unlock(&epoch_stacks_lock);
- if (new != NULL)
+ if (dup) {
+ /* Lost a race; the other thread reports it. */
free(new, M_STACK);
+ return;
+ }
}
va_start(ap, fmt);