DragonFlyBSD Kernel Audit
DF-2503 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/nata/atapi-cd.c b/sys/dev/disk/nata/atapi-cd.c
--- a/sys/dev/disk/nata/atapi-cd.c
+++ b/sys/dev/disk/nata/atapi-cd.c
@@ -495,6 +495,12 @@
 	    struct ioc_read_subchannel *args =
 		(struct ioc_read_subchannel *)ap->a_data;
 	    u_int8_t format;
+	    /* args is the raw user pointer; snapshot data_len into a local
+	     * immediately after validation and use it for the final copyout so
+	     * a concurrent mutation of the userspace value (TOCTOU) cannot
+	     * enlarge the copy past the 24-byte cdp->subchan and leak adjacent
+	     * kernel heap.  See DF-2503. */
+	    int data_len;
 	    int8_t ccb[16] = { ATAPI_READ_SUBCHANNEL, 0, 0x40, 1, 0, 0, 0,
 			       sizeof(cdp->subchan)>>8, sizeof(cdp->subchan),
 			       0, 0, 0, 0, 0, 0, 0 };
@@ -504,6 +510,7 @@
 		error = EINVAL;
 		break;
 	    }
+	    data_len = args->data_len;
 
 	    format = args->data_format;
 	    if ((format != CD_CURRENT_POSITION) &&
@@ -534,10 +541,10 @@
 		}
 	    }
 	    if (nocopyout == 0) {
-		error = copyout(&cdp->subchan, args->data, args->data_len);
+		error = copyout(&cdp->subchan, args->data, data_len);
 	    } else {
 		error = 0;
-		bcopy(&cdp->subchan, args->data, args->data_len);
+		bcopy(&cdp->subchan, args->data, data_len);
 	    }
 	}
 	break;