DF-0787 / panic.txt
=== DF-0787: kernel panic via unbounded attribute walk in ntfs_loadntnode ===
Trigger (as root, on default GENERIC 6.5-DEVELOPMENT #0):
vnconfig -c vn0 /root/ntfs_loop.img
mount_ntfs -o ro /dev/vn0 /mnt/ntfs
The mount syscall enters ntfs_mountfs() which VFS_VGET's NTFS_ROOTINO (ino 5),
the second system node loaded at mount time (sys/vfs/ntfs/ntfs_vfsops.c:396).
ntfs_vget -> ntfs_vgetex -> ntfs_loadntnode() runs the buggy walk at
sys/vfs/ntfs/ntfs_subr.c:305-320. Because the crafted ino-5 MFT record has an
attribute whose reclen is 0 (variant 'loop'), fr_attroff past the resident
attribute list (variant 'oob_a'), or reclen larger than the remaining record
space (variant 'oob_r'), the while() at line 310 never terminates: each
iteration calls ntfs_attrtontvattr(ap) which kmalloc's a fresh struct ntvattr
(+ a resident data buffer) and LIST_INSERT_HEAD's it into ip->i_valist. The
per-type slab allocator trips its memory ceiling and panics.
This is the cited bug, on the cited path. Panic signature (identical for all
three image variants — only cpuid differs):
panic: NTFS vattr: malloc limit exceeded
cpuid = 2
Trace beginning at frame 0xfffff8011803de30
_kmalloc() at _kmalloc+0xb09 0xffffffff806578c9
_kmalloc() at _kmalloc+0xb09 0xffffffff806578c9
ntfs_attrtontvattr() at ntfs_attrtontvattr+0x35 0xffffffff82602685
ntfs_loadntnode() at ntfs_loadntnode+0x178 0xffffffff82604278
ntfs_vgetex() at ntfs_vgetex+0x1ec 0xffffffff826010ac
ntfs_vget() at ntfs_vget+0x29 0xffffffff82601219
Debugger("panic")
CPU2 stopping CPUs: 0x0000003b
stopped
Stopped at Debugger+0x7c: movb $0,0xbdaf09(%rip)
db>
Reachability note (vs sibling DF-0786):
The DF-0786 lockmgr panic ("lockmgr: locking against itself") fires inside
ntfs_ntget() during a directory LOOKUP on an already-locked ntnode, i.e.
AFTER mount completes. DF-0787 fires BEFORE that — during the initial
mount-time loadntnode of the system MFT records (which use freshly
lockinit()'d ntnodes). So the lockmgr bug does NOT block this finding.