DragonFlyBSD Kernel Audit
DF-2500 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/nata/atapi-cam.c b/sys/dev/disk/nata/atapi-cam.c
--- a/sys/dev/disk/nata/atapi-cam.c
+++ b/sys/dev/disk/nata/atapi-cam.c
@@ -881,6 +881,14 @@
     struct atapi_hcb *hcb;
 
     if (scp != NULL) {
+	/* Abort any ATA requests still in flight for this atapi_cam device
+	 * BEFORE freeing the hcbs.  atapi_action() submits requests via the
+	 * asynchronous ata_queue_request() with request->driver = hcb; without
+	 * this drain, a request completing after detach invokes atapi_cb() which
+	 * dereferences the already-freed hcb (and the lockuninit'd state_lock).
+	 * See DF-2500. */
+	ata_fail_requests(scp->dev);
+
 	lockmgr(&scp->state_lock, LK_EXCLUSIVE);
 	TAILQ_FOREACH(hcb, &scp->pending_hcbs, chain) {
 	    free_hcb_and_ccb_done(hcb, CAM_UNREC_HBA_ERROR);