⬢ DragonFlyBSD Kernel Audit
DF-3150 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer/hammer_mirror.c
+++ b/sys/vfs/hammer/hammer_mirror.c
@@ -426,7 +426,9 @@
 			break;
 		}
 
-		switch(mrec.head.type & HAMMER_MRECF_TYPE_MASK) {
+		/* DF-3150: include NODATA so REC_NODATA is dispatchable */
+		switch(mrec.head.type &
+		       (HAMMER_MRECF_TYPE_MASK | HAMMER_MRECF_NODATA)) {
 		case HAMMER_MREC_TYPE_SKIP:
 			if (mrec.head.rec_size != sizeof(mrec.skip))
 				error = EINVAL;
@@ -579,6 +581,13 @@
 	}
 
 	/*
+	 * DF-3148: the wire leaf is stored verbatim in the B-Tree; its
+	 * element type must be a record element.
+	 */
+	if (mrec->leaf.base.btype != HAMMER_BTREE_TYPE_RECORD)
+		return(EINVAL);
+
+	/*
 	 * Re-localize for target.  relocalization of data is handled
 	 * by hammer_create_at_cursor().
 	 */
@@ -823,6 +832,14 @@
 		return(0);
 
 	/*
+	 * DF-3149: a record cannot be deleted at or before its own
+	 * create_tid (hammer_delete_at_cursor KKASSERTs delete_tid !=
+	 * create_tid; earlier deletes produce a bogus on-disk state).
+	 */
+	if (mrec->leaf.base.delete_tid <= cursor->leaf->base.create_tid)
+		return(EINVAL);
+
+	/*
 	 * Mark the record deleted on the mirror target.
 	 */
 	error = hammer_delete_at_cursor(cursor, HAMMER_DELETE_ADJUST,