DragonFlyBSD Kernel Audit
DF-0812 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/hammer/hammer_recover.c b/sys/vfs/hammer/hammer_recover.c
--- a/sys/vfs/hammer/hammer_recover.c
+++ b/sys/vfs/hammer/hammer_recover.c
@@ -1321,6 +1321,26 @@
 
 	switch(redo->redo_flags) {
 	case HAMMER_REDO_WRITE:
+		/*
+		 * Validate redo_data_bytes against the record capacity,
+		 * mirroring the UNDO path validation above
+		 * (hammer_recover.c:1053-1060).  redo_data_bytes is an
+		 * attacker-controllable int32 from disk; without this
+		 * check vn_rdwr() copies past the record into adjacent
+		 * kernel heap (info leak) or unmapped pages (panic).
+		 */
+		{
+			int redo_cap = redo->head.hdr_size -
+				(int)sizeof(struct hammer_fifo_redo) -
+				(int)sizeof(struct hammer_fifo_tail);
+			if (redo_cap < 0 || redo->redo_data_bytes < 0 ||
+			    redo->redo_data_bytes > redo_cap) {
+				hkprintf("Corrupt REDO record, "
+					 "redo_data_bytes %d/%d\n",
+					 redo->redo_data_bytes, redo_cap);
+				break;
+			}
+		}
 		error = VOP_OPEN(vp, FREAD|FWRITE, proc0.p_ucred, NULL);
 		if (error) {
 			hkprintf("vn_rdwr open %016jx:%08x returned %d\n",