DragonFlyBSD Kernel Audit
DF-2493 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/nata/ata-raid.c b/sys/dev/disk/nata/ata-raid.c
--- a/sys/dev/disk/nata/ata-raid.c
+++ b/sys/dev/disk/nata/ata-raid.c
@@ -3107,6 +3107,12 @@
 	raid->interleave = meta->stripe_sectors;
 	raid->width = meta->array_width;
 	raid->total_disks = meta->total_disks;
+	/* total_disks is read from untrusted on-disk metadata and is used to
+	 * iterate rdp->disks[MAX_DISKS] elsewhere.  Reject/cap out-of-range
+	 * values; the on-disk value can otherwise reach 256 and drive OOB
+	 * indexing of disks[].  See DF-2493. */
+	if (raid->total_disks > MAX_DISKS)
+	    raid->total_disks = MAX_DISKS;
 	raid->total_sectors = meta->total_sectors;
 	raid->heads = 255;
 	raid->sectors = 63;
@@ -3118,6 +3124,13 @@
 	if (meta->status & NV_S_DEGRADED)
 	    raid->status |= AR_S_DEGRADED;
 
+	/* meta->disk_number is read straight from untrusted on-disk metadata
+	 * and indexes the fixed disks[MAX_DISKS] array.  Reject out-of-range
+	 * values instead of writing past the end of ar_softc.  The same guard
+	 * is required in every vendor metadata parser (HighPoint v2/v3, LSI,
+	 * Silicon Image, Promise, Intel).  See DF-2493. */
+	if (meta->disk_number >= MAX_DISKS)
+	    goto nvidia_out;
 	raid->disks[meta->disk_number].dev = parent;
 	raid->disks[meta->disk_number].sectors =
 	    raid->total_sectors / raid->width;