Bug 258504 - smbfs doesn't validate msg fields -> potential kernel page fault
Summary: smbfs doesn't validate msg fields -> potential kernel page fault
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-bugs (Nobody)
Keywords: panic
Depends on:
Reported: 2021-09-14 17:32 UTC by Robert Morris
Modified: 2021-09-15 06:06 UTC (History)
0 users

See Also:

demo to produce kernel page fault in smbfs code (4.96 KB, text/plain)
2021-09-14 17:32 UTC, Robert Morris
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Robert Morris 2021-09-14 17:32:43 UTC
Created attachment 227902 [details]
demo to produce kernel page fault in smbfs code

If the smbfs kernel code receives a message from the server
that has too-large values for the parameter offset/length
or data offset/length, the kernel can page fault. The problem
is that smb_t2_reply() reads fields out of reply messages
and uses them to adjust mbuf fields without validating. Adding
these lines to the start of smb_t2_placedata() is one way to
improve this situation:

    u_int ml = m_length(mtop, (struct mbuf **) 0);
    if(offset + count > ml)
      return 1;

I'm able to cause this crash in FreeBSD-RELEASE-p4 and last month's
CURRENT, on amd64.

I've attached a demonstration program. It expects samba to
be running on localhost, proxies a connection between smbfs
and samba, and sets the high bit of the parameter count field
of the 4th server message as it passes by. Here's the backtrace:

Fatal trap 12: page fault while in kernel mode
cpuid = 1; apic id = 01
fault virtual address   = 0x18
fault code              = supervisor write data, page not present
instruction pointer     = 0x20:0xffffffff8271afcd
stack pointer           = 0x0:0xfffffe00a41ad5c0
frame pointer           = 0x0:0xfffffe00a41ad6d0
code segment            = base rx0, limit 0xfffff, type 0x1b
                        = DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags        = interrupt enabled, resume, IOPL = 0
current process         = 743 (mount_smbfs)
trap number             = 12
panic: page fault
cpuid = 1
time = 1631627929
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe00a41ad260
vpanic() at vpanic+0x187/frame 0xfffffe00a41ad2c0
panic() at panic+0x43/frame 0xfffffe00a41ad320
trap_fatal() at trap_fatal+0x387/frame 0xfffffe00a41ad380
trap_pfault() at trap_pfault+0x99/frame 0xfffffe00a41ad3e0
trap() at trap+0x2a7/frame 0xfffffe00a41ad4f0
calltrap() at calltrap+0x8/frame 0xfffffe00a41ad4f0
--- trap 0xc, rip = 0xffffffff8271afcd, rsp = 0xfffffe00a41ad5c0, rbp = 0xfffffe00a41ad6d0 ---
smb_t2_request() at smb_t2_request+0x83d/frame 0xfffffe00a41ad6d0
smbfs_smb_statfs() at smbfs_smb_statfs+0x76/frame 0xfffffe00a41ad740
smbfs_statfs() at smbfs_statfs+0x61/frame 0xfffffe00a41ad770
vfs_domount() at vfs_domount+0xa53/frame 0xfffffe00a41ad9e0
vfs_donmount() at vfs_donmount+0x880/frame 0xfffffe00a41ada80
sys_nmount() at sys_nmount+0x69/frame 0xfffffe00a41adac0
amd64_syscall() at amd64_syscall+0x12e/frame 0xfffffe00a41adbf0
fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe00a41adbf0
--- syscall (378, FreeBSD ELF64, sys_nmount), rip = 0x8011b7afa, rsp = 0x7fffffffe388, rbp = 0x7fffffffe9d0 ---
KDB: enter: panic
[ thread pid 743 tid 100111 ]
Stopped at      kdb_enter+0x37: movq    $0,0x127ae9e(%rip)

This is on FreeBSD xxx 14.0-CURRENT FreeBSD 14.0-CURRENT #0 main-n248636-d20e9e02db3: Thu Aug 12 05:47:18 UTC 2021     root@releng1.nyi.freebsd.org:/usr/obj/usr/src/amd64.amd64/sys/GENERIC  amd64