DragonFlyBSD Kernel Audit
DF-2509 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/nata/atapi-tape.c b/sys/dev/disk/nata/atapi-tape.c
--- a/sys/dev/disk/nata/atapi-tape.c
+++ b/sys/dev/disk/nata/atapi-tape.c
@@ -207,6 +207,16 @@
 
     if (((atadev->unit == ATA_MASTER) && !(ch->devices & ATA_ATAPI_MASTER)) ||
 	((atadev->unit == ATA_SLAVE) && !(ch->devices & ATA_ATAPI_SLAVE))) {
+	/* The device vanished during channel reset.  Previously this only did
+	 * device_set_ivars(NULL)+kfree(), so the later ast_detach dereferenced
+	 * the now-NULL ivars at destroy_dev(stp->cdev1) and panicked.  Tear down
+	 * the cdevs/queue/devstat here, mirroring ast_detach, so device_delete_child
+	 * -> ast_detach sees NULL ivars and returns cleanly.  See DF-2509. */
+	destroy_dev(stp->cdev1);
+	destroy_dev(stp->cdev2);
+	ata_fail_requests(dev);
+	dev_ops_remove_minor(&ast_ops, dkmakeunit(device_get_unit(dev)));
+	devstat_remove_entry(&stp->stats);
 	device_set_ivars(dev, NULL);
 	kfree(stp, M_AST);
 	return 1;