git: 139fa2c12ddc - main - routing: fix rtentry use-after-free in multipath route append
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 07 Oct 2026 04:24:43 UTC
The branch main has been updated by olivier:
URL: https://cgit.FreeBSD.org/src/commit/?id=139fa2c12ddc028048efe3946f2663dcfba9b122
commit 139fa2c12ddc028048efe3946f2663dcfba9b122
Author: Olivier Cochard <olivier@FreeBSD.org>
AuthorDate: 2026-10-07 04:16:33 +0000
Commit: Olivier Cochard <olivier@FreeBSD.org>
CommitDate: 2026-10-07 04:16:33 +0000
routing: fix rtentry use-after-free in multipath route append
add_route_flags() drops the RIB lock and passes the existing entry,
rt_orig, to add_route_flags_mpath(). If a concurrent delete removes
the prefix in that window, the retry re-inserts rt_orig, which is
then freed while still linked, crashing later in rn_match().
Pass the new rt instead, return ENOENT when the prefix is gone and
RTM_F_CREATE is not set, and fix the rnd_orig NULL check.
Approved by: pouria
Fixes: c24a8f19c5d5 ("routing: fix rib_add_route_px()")
Differential Revision: https://reviews.freebsd.org/D60353
---
sys/net/route/route_ctl.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/sys/net/route/route_ctl.c b/sys/net/route/route_ctl.c
index fa0f41a0a559..ef58a2845424 100644
--- a/sys/net/route/route_ctl.c
+++ b/sys/net/route/route_ctl.c
@@ -818,8 +818,13 @@ add_route_flags(struct rib_head *rnh, struct rtentry *rt, struct route_nhop_data
nhop_can_multipath(rnd_add->rnd_nhop) &&
nhop_can_multipath(rnd_orig.rnd_nhop)) {
+ /*
+ * @rt_orig may be freed once unlocked. Pass @rt if any: it
+ * is what gets inserted if the prefix vanishes.
+ */
for (int i = 0; i < RIB_MAX_RETRIES; i++) {
- error = add_route_flags_mpath(rnh, rt_orig, rnd_add, &rnd_orig,
+ error = add_route_flags_mpath(rnh,
+ rt != NULL ? rt : rt_orig, rnd_add, &rnd_orig,
op_flags, rc);
if (error != EAGAIN)
break;
@@ -855,6 +860,10 @@ add_route_flags_mpath(struct rib_head *rnh, struct rtentry *rt,
struct route_nhop_data rnd_new;
int error = 0;
+ /* Prefix vanished: nothing to append to, @rt may be deleted. */
+ if (rnd_orig->rnd_nhop == NULL && !(op_flags & RTM_F_CREATE))
+ return (ENOENT);
+
if (!NH_IS_NHGRP(rnd_add->rnd_nhop))
error = nhgrp_get_addition_group(rnh, rnd_orig, rnd_add, &rnd_new);
else
@@ -869,7 +878,8 @@ add_route_flags_mpath(struct rib_head *rnh, struct rtentry *rt,
RIB_RLOCK(rnh);
lookup_prefix_rt(rnh, rt, rnd_orig);
RIB_RUNLOCK(rnh);
- if (rnd_orig == NULL && !(op_flags & RTM_F_CREATE)) {
+ if (rnd_orig->rnd_nhop == NULL &&
+ !(op_flags & RTM_F_CREATE)) {
/* In this iteration route doesn't exist */
error = ENOENT;
}