Page MenuHomeFreeBSD

routing: restore opt_route.h in route.c, fib_algo teardown was compiled out
ClosedPublic

Authored by olivier on Tue, Sep 29, 11:22 PM.
Tags
None
Referenced Files
F174091039: D60158.id.diff
Wed, Sep 30, 1:40 PM
F174041167: D60158.id188146.diff
Wed, Sep 30, 4:10 AM
F174038597: D60158.diff
Wed, Sep 30, 3:47 AM
F174035684: D60158.diff
Wed, Sep 30, 3:24 AM
Subscribers

Details

Summary

254b23eb1f5 removed "opt_route.h" from 29 files; route.c still uses FIB_ALGO, guarding fib_destroy_rib() in rt_table_destroy().
Without it a destroyed rib keeps its fib_algo instances linked, subscribed and with an armed fd_callout, then frees the rib_lock rmlock that callout uses as its lock: page fault in _rm_wlock() from softclock on a MTX_DESTROYED mutex,
plus one leaked fib_data per family on every vnet destroy.

Test Plan

Summary

sys/net/route.c lost #include "opt_route.h" in
254b23eb1f5
("routing: Retire ROUTE_MPATH compile option", 2026-03-27), which dropped that
include from 29 files. route.c is the only one of them that still uses
FIB_ALGO, guarding the fib_destroy_rib() call in rt_table_destroy():

c
#ifdef FIB_ALGO
        fib_destroy_rib(rh);    /* compiled out since 254b23eb1f5 */
#endif

So destroying a rib no longer stops the algo instances attached to it. It
leaves each struct fib_data linked, subscribed and with a live
fd_callout, then runs RIB_LOCK_DESTROY(rh); free(rh, M_RTABLE) on the
rh->rib_lock rmlock that callout_init_rm() gave that callout.

Detected using net/frr10 regression test.

main-n289139-372b94623ca4, amd64 GENERIC-NODEBUG (no INVARIANTS, so the
mtx_lock() of destroyed mutex assert does not fire). Reproducer: FRR
(bgpd/ospfd/pimd) in vnet jails, create and destroy the topology under route
churn.

Fatal trap 12: page fault while in kernel mode
fault virtual address   = 0x488
rsi: 0000000000000004
__mtx_lock_sleep() at __mtx_lock_sleep+0xd9
_rm_wlock() at _rm_wlock+0x44b
softclock_call_cc() at softclock_call_cc+0x13f
softclock_thread() at softclock_thread+0xc7

From the dump:

  • callout: c_func=handle_fd_callout, c_lock=&rh->rib_lock
  • fd: fd_dead=0 fd_linked=1 (never torn down), fd_rh freed
  • rib: rib_dying=true, rib_lock.rm_lock_mtx.mtx_lock == 0x4 (MTX_DESTROYED)
  • lv_mtx_owner(0x4) == NULL, so TD_IS_RUNNING(NULL) reads offsetof(struct thread, td_state) == 0x488
  • disassemble rt_table_destroy shows no call to fib_destroy_rib
  • teardown thread is in vnet_destroy -> vnet_sysuninit -> if_clone_detach, i.e. already past rtables_destroy

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable