[Bug 283848] rtnl_handle_newroute() incomplete check of attrs.rta_table

From: <bugzilla-noreply_at_freebsd.org>
Date: Sat, 04 Jan 2025 20:13:16 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=283848

            Bug ID: 283848
           Summary: rtnl_handle_newroute() incomplete check of
                    attrs.rta_table
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: rtm@lcs.mit.edu
 Attachment #256427 text/plain
         mime type:

Created attachment 256427
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=256427&action=edit
pass a too-large rtm_table to RTM_NEWROUTE

The attached program passes an rtm_table that's too large to netlink
RTM_NEWROUTE. With INVARIANTS, this fails in rt_tables_get_rnh_ptr():

        KASSERT(table < V_rt_numfibs,
            ("%s: table out of bounds (%d < %d)", __func__, table,
             V_rt_numfibs));

Without INVARIANTS, the function returns junk from beyond the end of
V_rt_tables rather than a proper pointer.

Perhaps a contributing factor is that rtnl_handle_newroute() only
checks rta_table in one arm of the "if":

        if (attrs.rtm_table > 0 && attrs.rta_table == 0) {
                /* pre-2.6.19 Linux API compatibility */
                attrs.rta_table = attrs.rtm_table;
        } else if (attrs.rta_table >= V_rt_numfibs) {
                NLMSG_REPORT_ERR_MSG(npt, "invalid fib");
                return (EINVAL);
        }

I think also rtm_family ought to be checked against AF_MAX to avoid
tripping over the relevant KASSERT in rt_tables_get_rnh_ptr().

# uname -a
FreeBSD  15.0-CURRENT FreeBSD 15.0-CURRENT #345
main-n250995-3750873316a1-dirty: Sat Jan  4 13:51:03 EST 2025    
rtm@zika:/usr/obj/usr/rtm/symbsd/src/riscv.riscv64/sys/RTM riscv
# cc netlink12b.c
# ./a.out
panic: rt_tables_get_rnh_ptr: table out of bounds (1 < 1)
cpuid = 0
time = 1735920333
KDB: stack backtrace:
db_trace_self() at db_trace_self
db_trace_self_wrapper() at db_trace_self_wrapper+0x36
kdb_backtrace() at kdb_backtrace+0x2c
vpanic() at vpanic+0x16e
panic() at panic+0x26
rt_tables_get_rnh() at rt_tables_get_rnh+0x9a
nhop_get_nhop() at nhop_get_nhop+0x1e
finalize_nhop() at finalize_nhop+0xd4
rtnl_handle_newroute() at rtnl_handle_newroute+0x4a2
rtnl_handle_message() at rtnl_handle_message+0x12a
nl_taskqueue_handler() at nl_taskqueue_handler+0x49a
taskqueue_run_locked() at taskqueue_run_locked+0x158
taskqueue_thread_loop() at taskqueue_thread_loop+0xd4
fork_exit() at fork_exit+0x68
fork_trampoline() at fork_trampoline+0xa
KDB: enter: panic

-- 
You are receiving this mail because:
You are the assignee for the bug.