[Bug 291003] Fix panic in in6_selecthlim() while creating bridge interface
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.