DragonFlyBSD Kernel Audit
DF-3040 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer/hammer_undo.c
+++ b/sys/vfs/hammer/hammer_undo.c
@@ -62,6 +62,24 @@
 	hammer_off_t result_offset;
 
 	KKASSERT(hammer_is_zone_undo(zone3_off));
+
+	/*
+	 * DF-3040: the zone-3 offset indexes the fixed 128-entry
+	 * vol0_undo_array in the root volume header
+	 * (hammer_xlate_to_undo, hammer_disk.h).  Every bound currently
+	 * applied to zone-3 offsets (recover stage1, the KKASSERTs below)
+	 * is derived from the same attacker-controlled vol0_blockmap[3],
+	 * so a crafted header can push the array index far past the array
+	 * and past the 16KB header buffer (kernel heap OOB read).
+	 * Reject any offset outside the HAMMER_MAX_UNDO_BIGBLOCKS range
+	 * the on-disk format actually supports.
+	 */
+	if (zone3_off >= HAMMER_ENCODE_UNDO(
+				(hammer_off_t)HAMMER_MAX_UNDO_BIGBLOCKS *
+				HAMMER_BIGBLOCK_SIZE64)) {
+		*errorp = EIO;
+		return(0);
+	}
 	root_volume = hammer_get_root_volume(hmp, errorp);
 	if (*errorp)
 		return(0);