[Bug 292023] ipfw_nat64: kernel panic when combining nat64lsn + nat64clat over a bridge

From: <bugzilla-noreply_at_freebsd.org>
Date: Mon, 29 Dec 2025 19:53:53 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=292023

            Bug ID: 292023
           Summary: ipfw_nat64: kernel panic when combining nat64lsn +
                    nat64clat over a bridge
           Product: Base System
           Version: 16.0-CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs@FreeBSD.org
          Reporter: p.mousavizadeh@protonmail.com

Created attachment 266626
  --> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=266626&action=edit
simplified ipfw.rules that cause the panic

I simplified the ipfw.rules file from 500 rules to 22 rules to make it easier
to reproduce this bug. apply configuration below to a VM and set the default to
accept variable. then simply ping an IPv4 address that you want to be routed.
from a client:
route -n4 add -host 10.1.1.1 -gateway 100.64.1.2
ping -c1 100.64.1.2

then the VM crashes:

Fatal trap 9: general protection fault while in kernel mode
cpuid = 4; apic id = 04
instruction pointer     = 0x20:0xffffffff80e29773
stack pointer           = 0x28:0xfffffe00689885d0
frame pointer           = 0x28:0xfffffe0068988670
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         = 12 (irq43: virtio_pci1)
rdi: fffffe00086c6600 rsi: fffffe0086b16d20 rdx: fffffe0069965000
rcx: 0000000000000006  r8: ffffffff82e14090  r9: ffffffff82e14090
rax: 0000000000000004 rbx: fffffe0068988900 rbp: fffffe0068988670
r10: 0000000000000001 r11: fffffe00086c65d0 r12: fffffe00086c65d0
r13: 00000000e0000016 r14: ff0f120040e1012a r15: fffff80030e7ec00
trap number             = 9
panic: general protection fault
cpuid = 4
time = 1767038003
KDB: stack backtrace:
#0 0xffffffff80bbdf4d at kdb_backtrace+0x5d
#1 0xffffffff80b6f93e at vpanic+0x16e
#2 0xffffffff80b6f7c3 at panic+0x43
#3 0xffffffff810e0bf8 at trap_fatal+0x68
#4 0xffffffff810b13e8 at calltrap+0x8
#5 0xffffffff80e0776a at ipfw_chk+0x2aca
#6 0xffffffff80e13886 at ipfw_check_packet+0x106
#7 0xffffffff80cd4718 at pfil_mbuf_in+0x58
#8 0xffffffff80d570b3 at ip_input+0x3e3
#9 0xffffffff80cd0ac4 at netisr_dispatch_src+0xb4
#10 0xffffffff80cb32b9 at ether_demux+0x169
#11 0xffffffff80cb4675 at ether_nh_input+0x325
#12 0xffffffff80cd0ac4 at netisr_dispatch_src+0xb4
#13 0xffffffff80cb36f5 at ether_input+0xe5
#14 0xffffffff832121b0 at bridge_input+0x340
#15 0xffffffff80cb45a8 at ether_nh_input+0x258
#16 0xffffffff80cd0ac4 at netisr_dispatch_src+0xb4
#17 0xffffffff80cb36f5 at ether_input+0xe5
KDB: enter: panic

version:
# freebsd-version -rku
16.0-CURRENT
16.0-CURRENT
16.0-CURRENT

rc.conf:
ifconfig_vtnet0="up"
ipv6_cpe_wanif="bridge0"
defaultrouter="100.64.1.254"
ipv6_gateway_enable="YES"
gateway_enable="YES"
cloned_interfaces="bridge0"
create_args_bridge0="up addm vtnet0"
ifconfig_bridge0="inet 100.64.1.2/24"
ifconfig_bridge0_ipv6="inet6 fdb5:c59b:114e::a accept_rtadv"
firewall_enable="YES"
firewall_script="/etc/ipfw.rules"
firewall_logging="YES"

ipfw -at list:
Firewall rules loaded.
Firewall logging enabled.
00005   0     0                          allow ipv6-icmp from 2000::/3 to {
ff02::/16 or fe80::/10 } icmp6types 135,136
00006   0     0                          skipto 500 ip from any to any out
00040   0     0                          skipto 300 ip4 from 100.64.1.2 to any
tagged 64 record-state :nat64
00041   0     0                          skipto 300 ip6 from
2001:db8:10:10::/64 to 2001:db8:a:ff::/96 in
00042   0     0                          check-state :nat64
00042   0     0                          check-state :clat
00043   0     0                          skipto 350 ip4 from 100.64.1.0/24 to
not me tagged 464 record-state :clat
00044   0     0                          skipto 350 ip6 from
2001:db8:12:ff::/96 to 2001:db8:12:fff::/96 in
00050   0     0                          allow ip6 from me6 to me6 in
00060   0     0                          allow ip4 from me to me in
00061   0     0                          check-state :me4
00099   0     0                          reass ip from any to any in
00200   0     0                          check-state :default
00300   0     0                          nat64lsn NAT64 tag 64 ip4 from any to
100.64.1.2 in recv bridge0 in
00301   0     0                          nat64lsn NAT64 tag 64 ip6 from
2001:db8:10:10::/64 to 2001:db8:a:ff::/96 in
00349   0     0                          allow ip4 from 100.64.1.2 to any
tagged 64 in
00350   0     0                          nat64lsn (null) tag 464 ip6 from
2001:db8:12:ff::/96 to 2001:db8:12:fff::/96 in recv bridge0 in
00351   0     0                          nat64lsn (null) tag 464 ip4 from
100.64.1.0/24 to not me in recv bridge0 in
00399   0     0                          allow ip6 from 2001:db8:12:fff::/96 to
2001:db8:12:ff::/96 tagged 464 in
00501   0     0                          allow ip6 from me6 to any out
record-state :default
00521   0     0                          allow ip4 from me to any out
record-state :me4
00700   0     0                          check-state :default
65535   0     0                          count ip from any to any not //
orphaned dynamic states counter
65535 184 31560 Mon Dec 29 23:05:49 2025 allow ip from any to any

modified ipfw.rules file that will cause the panic is attached. 

kgdb output:
```
Thread 273 "irq43: virtio_pci1" received signal SIGTRAP, Trace/breakpoint trap.
[Switching to Thread 100079]
kdb_enter (why=<optimized out>, msg=<optimized out>) at
/usr/src/sys/kern/subr_kdb.c:556
556                     kdb_why = KDB_WHY_UNSET;
(kgdb) bt
#0  kdb_enter (why=<optimized out>, msg=<optimized out>) at
/usr/src/sys/kern/subr_kdb.c:556
#1  0xffffffff80b6f96f in vpanic (fmt=0xffffffff81261a39 "%s",
ap=ap@entry=0xfffffe00689834c0) at /usr/src/sys/kern/kern_shutdown.c:962
#2  0xffffffff80b6f7c3 in panic (fmt=0x0) at
/usr/src/sys/kern/kern_shutdown.c:887
#3  0xffffffff810e0bf8 in trap_fatal (frame=0xfffffe0068983510, eva=<optimized
out>) at /usr/src/sys/amd64/amd64/trap.c:969
#4  <signal handler called>
#5  nat64lsn_translate4 (cfg=0xff0f120040e1012a, mp=0xfffffe0068983950,
f_id=<optimized out>) at /usr/src/sys/netpfil/ipfw/nat64/nat64lsn.c:616
#6  ipfw_nat64lsn (ch=0xfffffe00086c65d0, args=0xfffffe0068983900,
cmd=<optimized out>, done=<optimized out>) at
/usr/src/sys/netpfil/ipfw/nat64/nat64lsn.c:1741
#7  0xffffffff80e0776a in ipfw_chk (args=args@entry=0xfffffe0068983900) at
/usr/src/sys/netpfil/ipfw/ip_fw2.c:3446
#8  0xffffffff80e13886 in ipfw_check_packet (m0=0xfffffe0068983a18,
ifp=0xfffff8000323a400, flags=65536, ruleset=<optimized out>, inp=0x0) at
/usr/src/sys/netpfil/ipfw/ip_fw_pfil.c:149
#9  0xffffffff80cd4718 in pfil_mbuf_common (pch=<optimized out>,
m=0xfffffe0068983a18, m@entry=0xfffffe00689839c8,
ifp=ifp@entry=0xfffff8000323a400, flags=65536, inp=inp@entry=0x0) at
/usr/src/sys/net/pfil.c:212
#10 pfil_mbuf_in (head=<optimized out>, m=m@entry=0xfffffe0068983a18,
ifp=ifp@entry=0xfffff8000323a400, inp=inp@entry=0x0) at
/usr/src/sys/net/pfil.c:230
#11 0xffffffff80d570b3 in ip_input (m=0xfffff80034222300) at
/usr/src/sys/netinet/ip_input.c:624
#12 0xffffffff80cd0ac4 in netisr_dispatch_src (proto=proto@entry=1,
source=source@entry=0, m=0xfffff80034222300) at /usr/src/sys/net/netisr.c:1151
#13 0xffffffff80cd0e4f in netisr_dispatch (proto=141321728, proto@entry=1,
m=0xfffffe0069965000) at /usr/src/sys/net/netisr.c:1242
#14 0xffffffff80cb32b9 in ether_demux (ifp=ifp@entry=0xfffff8000323a400,
m=0xfffff80034222300) at /usr/src/sys/net/if_ethersubr.c:936
#15 0xffffffff80cb4675 in ether_input_internal (ifp=0xfffff8000323a400,
m=0xfffff80034222300) at /usr/src/sys/net/if_ethersubr.c:700
#16 ether_nh_input (m=<optimized out>) at /usr/src/sys/net/if_ethersubr.c:730
#17 0xffffffff80cd0ac4 in netisr_dispatch_src (proto=proto@entry=5,
source=source@entry=0, m=0xfffff80034222300) at /usr/src/sys/net/netisr.c:1151
#18 0xffffffff80cd0e4f in netisr_dispatch (proto=141321728, proto@entry=5,
m=0xfffffe0069965000) at /usr/src/sys/net/netisr.c:1242
#19 0xffffffff80cb36f5 in ether_input (ifp=0xfffff8000323a400,
m=0xfffffe0086b16d20) at /usr/src/sys/net/if_ethersubr.c:841
#20 0xffffffff832121b0 in bridge_span (sc=0xfffff8000323a800,
m=0xfffff8003422c300) at /usr/src/sys/net/if_bridge.c:3279
#21 bridge_input (ifp=0xfffff8000380cc00, m=0xfffffe0068983c10) at
/usr/src/sys/net/if_bridge.c:2942
#22 0xffffffff80cb45a8 in ether_input_internal (ifp=0xfffff8000380cc00,
m=0xfffff8003422c300) at /usr/src/sys/net/if_ethersubr.c:664
#23 ether_nh_input (m=<optimized out>) at /usr/src/sys/net/if_ethersubr.c:730
#24 0xffffffff80cd0ac4 in netisr_dispatch_src (proto=proto@entry=5,
source=source@entry=0, m=0xfffff8003422c300) at /usr/src/sys/net/netisr.c:1151
#25 0xffffffff80cd0e4f in netisr_dispatch (proto=141321728, proto@entry=5,
m=0xfffffe0069965000) at /usr/src/sys/net/netisr.c:1242
#26 0xffffffff80cb36f5 in ether_input (ifp=0xfffff8000380cc00,
m=0xfffffe0086b16d20) at /usr/src/sys/net/if_ethersubr.c:841
#27 0xffffffff809900d1 in vtnet_rxq_input (rxq=0xfffff80003803d80,
m=0xfffff8003422c300, hdr=<optimized out>) at
/usr/src/sys/dev/virtio/network/if_vtnet.c:2099
#28 vtnet_rxq_eof (rxq=rxq@entry=0xfffff80003803d80) at
/usr/src/sys/dev/virtio/network/if_vtnet.c:2203
#29 0xffffffff8098f78c in vtnet_rx_vq_process (rxq=0xfffff80003803d80,
tries=<optimized out>) at /usr/src/sys/dev/virtio/network/if_vtnet.c:2269
#30 0xffffffff80b23cf4 in intr_event_execute_handlers (ie=0xfffff800037a5600,
p=<optimized out>) at /usr/src/sys/kern/kern_intr.c:1191
#31 ithread_execute_handlers (ie=0xfffff800037a5600, p=<optimized out>) at
/usr/src/sys/kern/kern_intr.c:1204
#32 ithread_loop (arg=arg@entry=0xfffff80003820fa0) at
/usr/src/sys/kern/kern_intr.c:1297
#33 0xffffffff80b201c2 in fork_exit (callout=0xffffffff80b23a90 <ithread_loop>,
arg=0xfffff80003820fa0, frame=0xfffffe0068983f40) at
/usr/src/sys/kern/kern_fork.c:1155
#34 <signal handler called>
(kgdb) select 5
(kgdb) info locals
loghdr = {length = 1 '\001', af = 0 '\000', action = 0 '\000', reason = 0
'\000', ifname = "\000\000\000\000@6\230h\000\376\377\377\223\021\264\200",
ruleset = "\377\377\377\377", '\000' <repeats 11 times>, rulenr = 0, subrulenr
= 1, uid = 0, pid = 1, rule_uid = 0, rule_pid = 1148380143, dir = 0 '\000',
pad1 = 0 '\000', naf = 0 '\000', pad = "", ridentifier = 464, reserve = 0
'\000', pad2 = "\000\000"}
src6 = {__u6_addr = {__u6_addr8 =
"\001\000\000\000\000\000\000\000\001\000\000\000\000\000\000", __u6_addr16 =
{1, 0, 0, 0, 1, 0, 0, 0}, __u6_addr32 = {1, 0, 1, 0}}}
addr = 3758096406
port = <optimized out>
proto = <optimized out>
ret = <optimized out>
alias = <optimized out>
state = <optimized out>
ts = <optimized out>
flags = <optimized out>
logdata = <optimized out>
(kgdb) info args
cfg = 0xff0f120040e1012a
mp = 0xfffffe0068983950
f_id = <optimized out>
(kgdb) p cfg
$1 = (struct nat64lsn_cfg *) 0xff0f120040e1012a
(kgdb) p *cfg
Cannot access memory at address 0xff0f120040e1012a
(kgdb) select 6
(kgdb) info locals
icmd = <optimized out>
i = 0xfffff80005fd9a80
ret = <optimized out>
(kgdb) info args
ch = 0xfffffe00086c65d0
args = 0xfffffe0068983900
cmd = <optimized out>
done = <optimized out>
(kgdb) p *i
$2 = {no = {nn_next = {tqe_next = 0x0, tqe_prev = 0xfffff800030dd800}, nv_next
= {tqe_next = 0x0, tqe_prev = 0xfffff80003c3bad8}, name = 0xfffff80005fd9ba0
"CLAT", etlv = 1003, subtype = 0 '\000', set = 0 '\000', kidx = 6, ocnt = 0,
refcnt = 2}, cfg = 0xff0f120040e1012a, name =
"\000\000\000\000\000\000\000\000*\001\341@\000\022\000\377\000\000\000\000\000\000\000\000\000\000\006\000``\000\000XZ;\204\000\376\377\377PZ;\204\000\376\377\377HZ;\204\000\376\377\377@Z;\204\000\376\377\377"}
(kgdb) p *args
$3 = {flags = 20971520, rule = {slot = 4294966784, rulenum = 2161901058,
rule_id = 4294967295, chain_id = 1754806684, info = 4294966784, pkt_mark = 0,
spare = {4294966784, 1754806704}}, ifp = 0xfffff8000323a400, inp = 0x0,
{next_hop = 0xfffff8000323a400, next_hop6 = 0xfffff8000323a400, hopstore =
{sin_len = 0 '\000', sin_family = 164 '\244', sin_port = 803, sin_addr =
{s_addr = 4294965248}, sin_zero = "\000pU\000\001\370\377\377"}, hopstore6 =
{sin6_addr = {__u6_addr = {__u6_addr8 =
"\000\244#\003\000\370\377\377\000pU\000\001\370\377\377", __u6_addr16 =
{41984, 803, 63488, 65535, 28672, 85, 63489, 65535}, __u6_addr32 = {52667392,
4294965248, 5599232, 4294965249}}}, sin6_scope_id = 1, sin6_port = 0}}, {m =
0xfffff80034222300, mem = 0xfffff80034222300}, f_id = {dst_ip = 3758096406,
src_ip = 1681916319, dst_port = 0, src_port = 0, fib = 0 '\000', proto = 2
'\002', _flags = 0 '\000', addr_type = 4 '\004', dst_ip6 = {__u6_addr =
{__u6_addr8 = "\000\000\000\000\000\000\000\000\000#\"4\000\370\377\377",
__u6_addr16 = {0, 0, 0, 0, 8960, 13346, 63488, 65535}, __u6_addr32 = {0, 0,
874652416, 4294965248}}}, src_ip6 = {__u6_addr = {__u6_addr8 =
"\000\000\000\000\000\000\000\000\3209\230h\000\376\377\377", __u6_addr16 = {0,
0, 0, 0, 14800, 26776, 65024, 65535}, __u6_addr32 = {0, 0, 1754806736,
4294966784}}}, flow_id6 = 874652416, extra = 4294965248}}
(kgdb) p *ch
$4 = {map = 0xfffff8000382ab00, id = 24, n_rules = 24, tablestate =
0xfffff80003c32000, valuestate = 0xfffff80003c2d000, idxmap =
0xfffffe00699af000, srvstate = 0xfffffe0069965000, rwmtx = {lock_object =
{lo_name = 0xffffffff811d5954 "IPFW static rules", lo_flags = 51052544, lo_data
= 0, lo_witness = 0xfffff800bfd9ab80}, rm_writecpus = {__bits = {46, 0 <repeats
15 times>}}, rm_activeReaders = {lh_first = 0x0}, _rm_lock = {_rm_wlock_object
= {lo_name = 0xffffffff811d5954 "IPFW static rules", lo_flags = 16842752,
lo_data = 0, lo_witness = 0x0}, _rm_lock_mtx = {lock_object = {lo_name =
0xffffffff811d5954 "IPFW static rules", lo_flags = 16842752, lo_data = 0,
lo_witness = 0x0}, mtx_lock = 0}, _rm_lock_sx = {lock_object = {lo_name =
0xffffffff811d5954 "IPFW static rules", lo_flags = 16842752, lo_data = 0,
lo_witness = 0x0}, sx_lock = 0}}}, gencnt = 0, nat = {lh_first = 0x0},
default_rule = 0xfffff80003b1ef80, tblcfg = 0xfffff80003c34000, ifcfg = 0x0,
idxmap_back = 0xfffffe006996f000, srvmap = 0xfffff80003c3b800, uh_lock =
{lock_object = {lo_name = 0xffffffff812f270d "IPFW UH lock", lo_flags =
86179840, lo_data = 0, lo_witness = 0xfffff800bfd9ac00}, rw_lock = 1}}
```


I think the problem is the `i->cfg`, because whenever code calls it crashes.
P.S: I could NOT reproduce this bug without using a bridge.

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