⬢ DragonFlyBSD Kernel Audit
DF-4810 / fix.diff
← back to finding ↓ download raw
--- sys/dev/disk/nata/ata-all.h
+++ sys/dev/disk/nata/ata-all.h
@@ -236,7 +236,9 @@
 #define ATA_AHCI_CL_OFFSET              0
 #define ATA_AHCI_FB_OFFSET              1024
 #define ATA_AHCI_CT_OFFSET              1024+256
 #define ATA_AHCI_CT_SG_OFFSET           128
-#define ATA_AHCI_CT_SIZE                256
+/* must equal sizeof(struct ata_ahci_cmd_tab) = 128 + 64*16 = 1152.
+ * tag is currently hardcoded 0; any per-tag dispatch must also size the
+ * work area (MAXWSPCSZ) for the number of supported tags. */
+#define ATA_AHCI_CT_SIZE                1152
 
 struct ata_ahci_dma_prd {
     u_int64_t                   dba;
--- sys/dev/disk/nata/chipsets/ata-ahci.c
+++ sys/dev/disk/nata/chipsets/ata-ahci.c
@@ -531,13 +531,14 @@ ata_ahci_dmasetprd(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
     struct ata_ahci_dma_prd *prd = args->dmatab;
     int i;
 
+    /* assert the bound BEFORE writing the table */
+    KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n"));
     if (!(args->error = error)) {
 	for (i = 0; i < nsegs; i++) {
 	    prd[i].dba = htole64(segs[i].ds_addr);
 	    prd[i].dbc = htole32((segs[i].ds_len - 1) & ATA_AHCI_PRD_MASK);
 	}
     }
 
-    KASSERT(nsegs <= ATA_AHCI_DMA_ENTRIES, ("too many DMA segment entries\n"));
     args->nsegs = nsegs;
 }
@@ -575,3 +586,7 @@ ata_ahci_setup_fis(struct ata_ahci_cmd_tab *ctp, struct ata_request *request)
     }
     return ata_request2fis_h2d(request, &ctp->cfis[0]);
 }
+
+/* keep the cmd-table stride honest against the struct it indexes */
+_Static_assert(ATA_AHCI_CT_SIZE == sizeof(struct ata_ahci_cmd_tab),
+	       ("ATA_AHCI_CT_SIZE must equal sizeof(struct ata_ahci_cmd_tab)"));