DragonFlyBSD Kernel Audit
DF-1174 / 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
@@ -152,8 +152,17 @@
     ata_raid_config_changed(rdp, writeback);
 
     /* sanitize arrays total_size % (width * interleave) == 0 */
+    /* DF-1174: crafted metadata can set interleave or width to 0, which
+     * would make rounddown() divide by zero (#DE panic). Reject the array
+     * before the division. */
     if (rdp->type == AR_T_RAID0 || rdp->type == AR_T_RAID01 ||
 	rdp->type == AR_T_RAID5) {
+	if (rdp->interleave == 0 || rdp->width == 0) {
+	    kprintf("ar%d: invalid RAID geometry (interleave=%u width=%u), "
+	        "refusing to attach\n", rdp->lun,
+	        rdp->interleave, rdp->width);
+	    return;
+	}
 	rdp->total_sectors = rounddown(rdp->total_sectors,
 	    rdp->interleave * rdp->width);
 	ksprintf(buffer, " (stripe %d KB)",
@@ -1025,7 +1034,10 @@
     }
     status->interleave = rdp->interleave;
     status->status = rdp->status;
-    status->progress = 100 * rdp->rebuild_lba / rdp->total_sectors;
+    /* DF-1174: total_sectors may be 0 from crafted metadata; guard the
+     * division to avoid a #DE panic. */
+    status->progress = (rdp->total_sectors != 0) ?
+        (100 * rdp->rebuild_lba / rdp->total_sectors) : 0;
     return 0;
 }