[Bug 291003] Fix panic in in6_selecthlim() while creating bridge interface

From: <bugzilla-noreply_at_freebsd.org>
Date: Thu, 13 Nov 2025 19:40:59 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=291003

            Bug ID: 291003
           Summary: Fix panic in in6_selecthlim() while creating bridge
                    interface
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Some People
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: olivier@freebsd.org

Created attachment 265401
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=265401&action=edit
patch fully generated by claude-code

Running a  FreeBSD 16.0-CURRENT #2 main-n281790-abd53b16c03f is easy to crash,
100% reproducible on my setup (here using a USB ethernet adapter):

```
sudo sysrc cloned_interfaces="bridge0 tap0"
sudo sysrc ifconfig_ue0="up"
sudo sysrc ifconfig_bridge0="up addm ue0 addm tap0"
sudo service netif restart && sudo service routing restart
```

It will generate this panic:
```
 Fatal trap 12: page fault while in kernel mode
cpuid = 6; apic id = 00
fault virtual address   = 0x10
fault code              = supervisor read data, page not present
instruction pointer     = 0x20:0xffffffff80da6435
stack pointer           = 0x28:0xfffffe016020f940
frame pointer           = 0x28:0xfffffe016020f970
code segment            = base 0x0, limit 0xfffff, type 0x1b
                        = DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags        = interrupt enabled, resume, IOPL = 0
current process         = 7689 (sshd-session)
rdi: fffff800225d3800 rsi: 000000000000001c rdx: fffff8000184ec78
rcx: fffff800225d3800  r8: 00000000ffffffbd  r9: 0000000000000000
rax: 0000000000000000 rbx: 0000000000000000 rbp: fffffe016020f970
r10: fffffe016020f8f0 r11: 0000000000000008 r12: 0000000000010300
r13: 0000000000000000 r14: fffffe016020f94c r15: fffff80041ea9400
trap number             = 12
panic: page fault
cpuid = 6
time = 1763050117
KDB: stack backtrace:
#0  __curthread () at /usr/src/sys/amd64/include/pcpu_aux.h:57
#1  doadump (textdump=textdump@entry=0) at
/usr/src/sys/kern/kern_shutdown.c:399
#2  0xffffffff804a414a in db_dump (dummy=<optimized out>, dummy2=<optimized
out>, dummy3=<optimized out>,
    dummy4=<optimized out>) at /usr/src/sys/ddb/db_command.c:596
#3  0xffffffff804a3f3d in db_command (last_cmdp=<optimized out>,
cmd_table=<optimized out>, dopager=true)
    at /usr/src/sys/ddb/db_command.c:508
#4  0xffffffff804a3bfd in db_command_loop () at
/usr/src/sys/ddb/db_command.c:555
#5  0xffffffff804a7526 in db_trap (type=<optimized out>, code=<optimized out>)
at /usr/src/sys/ddb/db_main.c:267
#6  0xffffffff80bd1a95 in kdb_trap (type=type@entry=3, code=code@entry=0,
tf=tf@entry=0xfffffe016020f5d0)
    at /usr/src/sys/kern/subr_kdb.c:790
#7  0xffffffff81099ffc in trap (frame=<optimized out>) at
/usr/src/sys/amd64/amd64/trap.c:614
#8  <signal handler called>
#9  kdb_enter (why=<optimized out>, msg=<optimized out>) at
/usr/src/sys/kern/subr_kdb.c:556
#10 0xffffffff80b838ab in vpanic (fmt=0xffffffff811f2708 "%s",
ap=ap@entry=0xfffffe016020f800)
    at /usr/src/sys/kern/kern_shutdown.c:962
#11 0xffffffff80b83713 in panic (fmt=0xffffffff818a42f8 <vt_conswindow+16>
"\262\302$\201\377\377\377\377")
    at /usr/src/sys/kern/kern_shutdown.c:887
#12 0xffffffff8109aa1f in trap_fatal (frame=<optimized out>, eva=<optimized
out>)
    at /usr/src/sys/amd64/amd64/trap.c:969
#13 0xffffffff8109aa1f in trap_pfault (frame=0xfffffe016020f880,
usermode=false, signo=<optimized out>,
    ucode=<optimized out>)
#14 <signal handler called>
#15 0xffffffff80da6435 in in6_selecthlim (inp=inp@entry=0xfffff800711a5000,
ifp=ifp@entry=0x0)
    at /usr/src/sys/netinet6/in6_src.c:872
#16 0xffffffff80d7107e in tcp_default_output (tp=0xfffff800711a5000) at
/usr/src/sys/netinet/tcp_output.c:1447
#17 0xffffffff80d82afa in tcp_output_nodrop (tp=0xfffff800711a5000) at
/usr/src/sys/netinet/tcp_var.h:720
#18 tcp_usr_send (so=0xfffff80022879000, flags=0, m=0x0, nam=<optimized out>,
control=<optimized out>,
    td=<optimized out>) at /usr/src/sys/netinet/tcp_usrreq.c:1127
#19 0xffffffff80c30c5f in sosend_generic_locked
(so=so@entry=0xfffff80022879000, addr=addr@entry=0x0,
    uio=uio@entry=0xfffffe016020fda8, top=0xfffff80041ea9400, top@entry=0x0,
control=control@entry=0x0,
    flags=flags@entry=0, td=0xfffff8000c3e2780) at
/usr/src/sys/kern/uipc_socket.c:2537
#20 0xffffffff80c30541 in sosend_generic (so=0xfffff80022879000, addr=0x0,
uio=0xfffffe016020fda8, top=0x0,
    control=0x0, flags=0, td=0xfffff8000c3e2780) at
/usr/src/sys/kern/uipc_socket.c:2586
#21 0xffffffff80c311bf in sousrsend (so=0xfffff800225d3800, addr=0x1c,
uio=0xfffff8000184ec78,
    control=0xffffffbd, flags=0, userproc=0x0) at
/usr/src/sys/kern/uipc_socket.c:2626
#22 0xffffffff80bf5c01 in fo_write (fp=0xfffff8000e9a2c30,
uio=0xfffffe016020fda8,
    active_cred=0xfffff8000184ec78, td=0xfffff8000c3e2780, flags=<optimized
out>) at /usr/src/sys/sys/file.h:370
#23 dofilewrite (td=td@entry=0xfffff8000c3e2780, fd=fd@entry=7,
fp=0xfffff8000e9a2c30,
    auio=auio@entry=0xfffffe016020fda8, offset=offset@entry=-1,
flags=flags@entry=0)
    at /usr/src/sys/kern/sys_generic.c:565
#24 0xffffffff80bf5607 in kern_writev (td=0xfffff8000c3e2780, fd=7,
auio=0xfffffe016020fda8)
    at /usr/src/sys/kern/sys_generic.c:492    
```

So I’ve requested claude code (AI agent) to study this problem and to wrote a
patch (attached).
Once applied, I wasn’t able to reproduce the panic.

Here is the explanation that claude code generated:
```
  Root Cause

  The kernel panics were caused by NULL pointer dereferences in IPv6 code
during network interface
  reconfiguration. The fundamental issue was that several IPv6 macros and
functions assumed that
  ifp->if_afdata[AF_INET6] (IPv6 interface data) would always be available when
ifp (network interface)
  exists.

  Technical Details:

  - When it happens: During bridge setup, interface configuration changes, or
network reconfiguration
  - Why it happens: IPv6 data structures (struct in6_ifextra) can be
temporarily unavailable while the base
  interface (struct ifnet) still exists
  - Where it manifests: Multiple locations in the IPv6 stack that use macros
like ND_IFINFO(),
  in6_ifstat_inc(), LLTABLE6(), and DAD_FAILURES()

  Specific Crash Locations:

  1. First crash: in6_selecthlim() at line 872 in
/usr/src/sys/netinet6/in6_src.c
  2. Second crash: ip6_output() at line 805 via in6_ifstat_inc() macro
  3. Potential crashes: Multiple other locations using similar unsafe patterns

  Solution

  Implemented defensive programming throughout the IPv6 stack by adding NULL
checks before accessing
  IPv6-specific data structures.

  Files Modified:

  1. /usr/src/sys/netinet6/in6_src.c

  // BEFORE (unsafe):
  return (ND_IFINFO(ifp)->chlim);

  // AFTER (safe):
  ext = (struct in6_ifextra *)if_getafdata(ifp, AF_INET6);
  if (ext != NULL)
      return (ext->nd_ifinfo->chlim);

  2. /usr/src/sys/netinet6/in6_var.h

  // BEFORE (unsafe):
  #define in6_ifstat_inc(ifp, tag) \
  do { \
      if (ifp) \
          counter_u64_add(((struct in6_ifextra *) \
              ((ifp)->if_afdata[AF_INET6]))->in6_ifstat[...], 1); \
  } while (0)
  // AFTER (safe):
  #define in6_ifstat_inc(ifp, tag) \
  do { \
      if ((ifp) && (ifp)->if_afdata[AF_INET6]) \
          counter_u64_add(((struct in6_ifextra *) \
              ((ifp)->if_afdata[AF_INET6]))->in6_ifstat[...], 1); \
  } while (0)

  3. Multiple usage sites for DAD_FAILURES:

  - in6_ifattach.c: Added conditional check before atomic_load_int()
  - nd6_rtr.c: Added NULL check in conditional expression
  - nd6_nbr.c: Added checks before all atomic operations

  Key Changes:

  1. in6_selecthlim(): Replaced ND_IFINFO() macro with explicit NULL-safe code
  2. in6_ifstat_inc macro: Added (ifp)->if_afdata[AF_INET6] NULL check
  3. LLTABLE6 macro: Made it return NULL when IPv6 data unavailable
  4. DAD_FAILURES usage: Added NULL checks at all call sites to prevent atomic
operations on NULL pointers

  Impact

  - Stability: Eliminates kernel panics during network reconfiguration
  - Compatibility: Maintains all existing functionality when IPv6 structures
are properly initialized
  - Performance: Minimal overhead (just NULL pointer checks)
  - Scope: Comprehensive fix covering the entire IPv6 stack's vulnerable
patterns
```

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