⬢ DragonFlyBSD Kernel Audit
DF-3187 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer/hammer_btree.c	2026-09-08 03:14:36.652256326 +0000
+++ b/sys/vfs/hammer/hammer_btree.c	2026-09-08 04:02:12.442889107 +0000
@@ -732,8 +732,28 @@
 
 	/*
 	 * Load the data
+	 *
+	 * The on-disk data_offset/data_len are attacker controllable (a
+	 * corrupted or forged filesystem image).  Reject out-of-range
+	 * lengths, non-data zones, and extents that are not contained
+	 * within the referenced 16K data buffer before touching the
+	 * buffer cache or the CRC engine.
 	 */
-	KKASSERT(data_len >= 0 && data_len <= HAMMER_XBUFSIZE);
+	{
+		int zone = (int)((data_off >> 60) & 15);
+
+		if (data_len <= 0 || data_len > HAMMER_BUFSIZE ||
+		    (zone != HAMMER_ZONE_META_INDEX &&
+		     zone != HAMMER_ZONE_LARGE_DATA_INDEX &&
+		     zone != HAMMER_ZONE_SMALL_DATA_INDEX) ||
+		    (int)(data_off & HAMMER_BUFMASK) + data_len >
+							HAMMER_BUFSIZE) {
+			hdkprintf("bad record data %d @ %016jx\n",
+				  data_len, (intmax_t)data_off);
+			cursor->data = NULL;
+			return (EIO);
+		}
+	}
 	cursor->data = hammer_bread_ext(hmp, data_off, data_len,
 					&error, &cursor->data_buffer);
 
--- a/sys/vfs/hammer/hammer_pfs.c	2026-09-08 03:14:36.652256326 +0000
+++ b/sys/vfs/hammer/hammer_pfs.c	2026-09-08 03:14:45.780124506 +0000
@@ -359,8 +359,15 @@
 	if (error == 0) {
 		error = hammer_ip_resolve_data(&cursor);
 		if (error == 0) {
+			int bytes = cursor.leaf->data_len;
+
+			if (bytes < 0)
+				bytes = 0;
+			if (bytes > sizeof(struct hammer_pseudofs_data))
+				bytes = sizeof(struct hammer_pseudofs_data);
 			if (pfs->ondisk)
-				copyout(cursor.data, pfs->ondisk, cursor.leaf->data_len);
+				error = copyout(cursor.data, pfs->ondisk,
+						bytes);
 			localization = cursor.leaf->base.key;
 			pfs->pfs_id = lo_to_pfs(localization);
 		}