[Bug 266442] kernel page fault on packet with broken lengths if ipfilter is loaded
Date: Fri, 16 Sep 2022 10:10:59 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=266442
Bug ID: 266442
Summary: kernel page fault on packet with broken lengths if
ipfilter is loaded
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 #236590 text/plain
mime type:
Created attachment 236590
--> https://bugs.freebsd.org/bugzilla/attachment.cgi?id=236590&action=edit
Inject a packet that causes a kernel page fault if ipfilter is loaded.
If ipfilter is loaded, and a packet arrives with IP hlen = 20 bytes
(the default), IP packet len = 67 bytes, and TCP th_off = 48 bytes,
ipf_pullup() will call m_pullup(len=68), which fails and causes
ipf_pullup() to free the mbuf and zero out the mbuf pointer in
*fin->fin_mp. But the information that the packet was discarded is
lost because ipf_pr_ipv4hdr() does not return an error to
ipf_makefrip(). So the calling code thinks everything is OK,
ip_tryforward() sees PFIL_PASS and uses m = *fin->fin_mp, and it
crashes.
Error indications should probably be made to flow up from ipf_pullup()
through ipf_pr_ipv4hdr() to ipf_makefrip(), so that callers know not
to try to use the freed mbuf.
I've attached a demo:
# cc -o pf7a pf7a.c
# ./pf7a
...
panic: Fatal page fault at 0xffffffc000488f14: 0x0000000000001d
panic() at panic+0x2a
page_fault_handler() at page_fault_handler+0x1d6
do_trap_supervisor() at do_trap_supervisor+0x76
cpu_exception_handler_supervisor() at cpu_exception_handler_supervisor+0x70
--- exception 13, tval = 0x1d
ip_tryforward() at ip_tryforward+0x278
ip_input() at ip_input+0x356
netisr_dispatch_src() at netisr_dispatch_src+0xca
netisr_dispatch() at netisr_dispatch+0x10
tunwrite_l3() at tunwrite_l3+0x182
tunwrite() at tunwrite+0x128
devfs_write_f() at devfs_write_f+0xa6
fo_write() at fo_write+0xa
dofilewrite() at dofilewrite+0x66
kern_writev() at kern_writev+0x40
sys_write() at sys_write+0x54
syscallenter() at syscallenter+0xec
ecall_handler() at ecall_handler+0x18
do_trap_user() at do_trap_user+0xea
cpu_exception_handler_user() at cpu_exception_handler_user+0x72
Here's the call chain at the point where m_pullup() fails:
ipf_pullup() at ipf_pullup+0x182
ipf_pr_pullup() at ipf_pr_pullup+0x5c
ipf_pr_tcpcommon() at ipf_pr_tcpcommon+0x28e
ipf_pr_tcp() at ipf_pr_tcp+0x46
ipf_pr_ipv4hdr() at ipf_pr_ipv4hdr+0x220
ipf_makefrip() at ipf_makefrip+0x60
ipf_check() at ipf_check+0x142
ipf_check_wrapper() at ipf_check_wrapper+0x88
pfil_mbuf_in() at pfil_mbuf_in+0x58
ip_tryforward() at ip_tryforward+0x1c0
ip_input() at ip_input+0x356
--
You are receiving this mail because:
You are the assignee for the bug.