DF-0850 / panic.txt
=== DF-0850 PANIC SIGNATURE (unpatched #0 kernel) ===
Trigger: mount crafted ext2 image (DIRHASHINDEX + inode IN_E3INDEX +
interior htree node with count=limit=0xFFFF) then stat a file in the dir.
panic: lockmgr: locking against myself
cpuid = 5
Trace beginning at frame 0xfffff80117abb138
lockmgr_exclusive() at lockmgr_exclusive+0x3e0 0xffffffff80647f30
lockmgr_exclusive() at lockmgr_exclusive+0x3e0 0xffffffff80647f30
getblk() at getblk+0xe1 0xffffffff806d6f91
breadnx() at breadnx+0x284 0xffffffff806d7714
ext2_blkatoff() at ext2_blkatoff+0x58 0xffffffff8260a1e8
ext2_htree_find_leaf() at ext2_htree_find_leaf+0x1e5 0xffffffff82605ac5
Debugger("panic")
=== Root Cause ===
ext2_htree_find_leaf (ext2_htree.c:312-342) walks the htree. At the root
(lines 308-310) the limit is validated against ext2_htree_root_limit().
After descending into an interior node (lines 335-339, entp = node->h_entries),
the NEXT iteration's limit check (line 314: cnt > get_limit(entp)) reads the
limit from the attacker-controlled on-disk interior node header โ NOT validated
against ext2_htree_node_limit(). With count=limit=0xFFFF, the binary search
(line 321: get_hash(middle)) reads OOB past the bp->b_data buffer. The OOB
data feeds get_block(found) โ ext2_blkatoff with a garbage block number โ
getblk tries to re-lock an already-held buffer โ lockmgr panic.