⬢ DragonFlyBSD Kernel Audit
DF-5175 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/disk/nata/ata-card.c
+++ b/sys/dev/disk/nata/ata-card.c
@@ -89,6 +89,18 @@
 				  ATA_IOSIZE, RF_ACTIVE)))
 	return (ENXIO);
 
+    /*
+     * The pccard bus hands back the CIS-declared I/O window verbatim, so its
+     * size is card-controlled.  Make sure it actually covers the primary
+     * register block (offsets 0..7) wired below before we use it.
+     */
+    if (rman_get_size(io) < ATA_IOSIZE) {
+	device_printf(dev, "CIS io window too small (%ju ports)\n",
+		      (uintmax_t)rman_get_size(io));
+	bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io);
+	return (ENXIO);
+    }
+
     /* setup the resource vectors */
     for (i = ATA_DATA; i <= ATA_COMMAND; i++) {
 	ch->r_io[i].res = io;
@@ -99,10 +111,11 @@
     /*
      * if we got more than the default ATA_IOSIZE ports, this is a device
      * where ctlio is located at offset 14 into "normal" io space.
+     * Only trust that layout when the window really covers offset 14.
      */
-    if (rman_get_size(io) > ATA_IOSIZE) {
+    if (rman_get_size(io) >= ATA_PCCARD_CTLOFFSET + ATA_CTLIOSIZE) {
 	ch->r_io[ATA_CONTROL].res = io;
-	ch->r_io[ATA_CONTROL].offset = 14;
+	ch->r_io[ATA_CONTROL].offset = ATA_PCCARD_CTLOFFSET;
     }
     else {
 	rid = ATA_CTLADDR_RID;