https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=288263
Bug ID: 288263
Summary: with pf, link-local target address in icmp6 ADVERT can
cause NULL deref
Product: Base System
Version: CURRENT
Hardware: Any
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: [email protected]
Reporter: [email protected]
Attachment #262207 text/plain
mime type:
Created attachment 262207
--> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=262207&action=edit
demonstrate link-local address problem with ip6 and pf
I've attached a demo that sets up tun0 for ip6 and pf with
pass in on tap0 inet6 from any to any af-to inet from 192.168.3.1 keep state
The demo sends ip6 / icmp6 / ND_NEIGHBOR_ADVERT / target=ff a2 00 03...
on tap0, but with an illegal ip6_dst. Target "ff a2 00 03" is a
link-local address, and on my setup interface #3 is pflog0.
ip6_forward() rejects the packet and calls icmp6_error(), whose
ip6_output() calls pf_check6_out() / pf_test() / pf_test_state_icmp(),
which changes the error reply's ip6 destination to the target found
inside the original icmp6 packet, i.e. to the link-local address ff a2
00 03, in this code:
if (PF_ANEQ(pd2.src,
&nk->addr[pd2.sidx], pd2.af) ||
((virtual_type ==
htons(ICMP6_ECHO_REQUEST)) &&
nk->port[pd2.sidx] != iih->icmp6_id))
pf_change_icmp(pd2.src,
(virtual_type ==
htons(ICMP6_ECHO_REQUEST))
? &iih->icmp6_id : NULL,
daddr, &nk->addr[pd2.sidx],
(virtual_type ==
htons(ICMP6_ECHO_REQUEST))
? nk->port[iidx] : 0, NULL,
pd2.ip_sum, icmpsum,
pd->ip_sum, 0, AF_INET6);
Then ip6_output() continues, now with the link-local ip6_dst. If the
link specified in the address is not configured for ip6, then there's
a crash in this code in ip6_output():
if ((flags & IPV6_FORWARDING) == 0) {
/* XXX: the FORWARDING flag can be set for mrouting. */
in6_ifstat_inc(ifp, ifs6_out_request);
}
because in6_ifstat_inc() attempts to dereference ifp->if_afdata[AF_INET6],
which can be NULL for a non-ip6 interface.
The demo code I've attached supplies a link-local address with
interface #3, which on my setup is pflog0. You may need to adjust the
demo code if your pflog0 has a different index and you want to see the
crash.
# uname -a
FreeBSD xxx 15.0-CURRENT FreeBSD 15.0-CURRENT #30 main-n275522-551d428b5bdc:
Fri Jun 27 16:05:41 AST 2025
root@xxx:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64
# cc npf23b.c
# ./a.out
...
Fatal trap 12: page fault while in kernel mode
cpuid = 2; apic id = 02
fault virtual address = 0x0
fault code = supervisor read data, page not present
instruction pointer = 0x20:0xffffffff80e0a10f
stack pointer = 0x28:0xfffffe00d6de8610
frame pointer = 0x28:0xfffffe00d6de87c0
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 = 759 (a.out)
rdi: ffffffff81df7d80 rsi: fffff80066613800 rdx: fffffe00d6de8644
rcx: 5f1221280300a2ff r8: ffffffff81ad48a0 r9: 0000000000000000
rax: 0000000000000000 rbx: 0000000000000000 rbp: fffffe00d6de87c0
r10: 0000000000000000 r11: 0000000000000001 r12: 0000000000000000
r13: fffffe00d6de872c r14: fffff80066613800 r15: 0000000000000000
trap number = 12
panic: page fault
cpuid = 2
time = 1752681305
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00d6de8340
vpanic() at vpanic+0x136/frame 0xfffffe00d6de8470
panic() at panic+0x43/frame 0xfffffe00d6de84d0
trap_pfault() at trap_pfault+0x48d/frame 0xfffffe00d6de8540
calltrap() at calltrap+0x8/frame 0xfffffe00d6de8540
--- trap 0xc, rip = 0xffffffff80e0a10f, rsp = 0xfffffe00d6de8610, rbp =
0xfffffe00d6de87c0 ---
ip6_output() at ip6_output+0xeef/frame 0xfffffe00d6de87c0
icmp6_reflect() at icmp6_reflect+0x329/frame 0xfffffe00d6de8880
icmp6_error() at icmp6_error+0x3e4/frame 0xfffffe00d6de88f0
ip6_forward() at ip6_forward+0x835/frame 0xfffffe00d6de89f0
ip6_input() at ip6_input+0xd0b/frame 0xfffffe00d6de8ad0
netisr_dispatch_src() at netisr_dispatch_src+0xb4/frame 0xfffffe00d6de8b30
ether_demux() at ether_demux+0x16a/frame 0xfffffe00d6de8b60
ether_nh_input() at ether_nh_input+0x3ce/frame 0xfffffe00d6de8bb0
netisr_dispatch_src() at netisr_dispatch_src+0xb4/frame 0xfffffe00d6de8c10
ether_input() at ether_input+0xd5/frame 0xfffffe00d6de8c70
tunwrite() at tunwrite+0x57d/frame 0xfffffe00d6de8ce0
devfs_write_f() at devfs_write_f+0xf3/frame 0xfffffe00d6de8d40
dofilewrite() at dofilewrite+0x81/frame 0xfffffe00d6de8d90
sys_write() at sys_write+0xb7/frame 0xfffffe00d6de8e00
amd64_syscall() at amd64_syscall+0x169/frame 0xfffffe00d6de8f30
fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe00d6de8f30
--- syscall (4, FreeBSD ELF64, write), rip = 0x8234dfe9a, rsp = 0x820d911e8,
rbp = 0x820d91320 ---
--
You are receiving this mail because:
You are the assignee for the bug.