DragonFlyBSD Kernel Audit
DF-1172 / 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
@@ -2795,6 +2795,25 @@
     if (testing || bootverbose)
 	ata_raid_lsiv2_print_meta(meta);
 
+    /*
+     * meta->raid_number and meta->disk_number are u_int8_t (0..255) read
+     * straight off the disk.  They index raidp[..<MAX_ARRAYS=16>] (BSS),
+     * meta->configs[raid_entry=<raid_number>] (array of 30) and
+     * raid->disks[<disk_number>] (array of MAX_DISKS=16).  Reject any value
+     * that would index out of bounds: otherwise a crafted disk with
+     * raid_number>=16 writes a kmalloc'd heap pointer into BSS past
+     * ata_raid_arrays[] (and reads configs[] OOB), and disk_number>=16
+     * overflows raid->disks[] into the trailing ar_softc fields / adjacent
+     * heap.  (DF-1172)
+     */
+    if (meta->raid_number >= MAX_ARRAYS || meta->disk_number >= MAX_DISKS) {
+	if (testing || bootverbose)
+	    device_printf(parent,
+		"LSI (v2) metadata raid_number %u / disk_number %u out of range\n",
+		meta->raid_number, meta->disk_number);
+	goto lsiv2_out;
+    }
+
     /* now convert LSI (v2) config meta into our generic form */
     for (array = 0; array < MAX_ARRAYS; array++) {
 	int raid_entry, conf_entry;