DragonFlyBSD Kernel Audit
DF-2474 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/dev/disk/isp/isp_freebsd.h b/sys/dev/disk/isp/isp_freebsd.h
--- a/sys/dev/disk/isp/isp_freebsd.h
+++ b/sys/dev/disk/isp/isp_freebsd.h
@@ -152,6 +152,7 @@
 	struct thread *kthread;
 	bus_dma_tag_t tdmat;
 	bus_dmamap_t tdmap;
+	caddr_t	rscratch; /* DF-2474: scratch DMA vaddr for error cleanup */
 	uint64_t def_wwpn;
 	uint64_t def_wwnn;
 	uint32_t loop_down_time;
diff --git a/sys/dev/disk/isp/isp_pci.c b/sys/dev/disk/isp/isp_pci.c
--- a/sys/dev/disk/isp/isp_pci.c
+++ b/sys/dev/disk/isp/isp_pci.c
@@ -1615,6 +1615,7 @@
 	im.error = 0;
 
 	bus_dmamap_load(isp->isp_osinfo.cdmat, isp->isp_osinfo.cdmap, base, len, imc, &im, 0);
+	caddr_t ctrl_base = base; /* DF-2474: save control-area base */
 	if (im.error) {
 		isp_prt(isp, ISP_LOGERR, "error %d loading dma map for control areas", im.error);
 		goto bad;
@@ -1635,6 +1636,7 @@
 			im.vbase = base;
 			im.error = 0;
 			bus_dmamap_load(fc->tdmat, fc->tdmap, base, ISP_FC_SCRLEN, imc1, &im, 0);
+			fc->rscratch = base; /* DF-2474: save per-channel scratch base */
 			if (im.error) {
 				bus_dmamem_free(fc->tdmat, base, fc->tdmap);
 				bus_dma_tag_destroy(fc->tdmat);
@@ -1667,10 +1669,10 @@
 bad:
 	while (--cmap >= 0) {
 		struct isp_fc *fc = ISP_FC_PC(isp, cmap);
-		bus_dmamem_free(fc->tdmat, base, fc->tdmap);
+		bus_dmamem_free(fc->tdmat, fc->rscratch, fc->tdmap);
 		bus_dma_tag_destroy(fc->tdmat);
 	}
-	bus_dmamem_free(isp->isp_osinfo.cdmat, base, isp->isp_osinfo.cdmap);
+	bus_dmamem_free(isp->isp_osinfo.cdmat, ctrl_base, isp->isp_osinfo.cdmap);
 	bus_dma_tag_destroy(isp->isp_osinfo.cdmat);
 	kfree(isp->isp_xflist, M_DEVBUF);
 #ifdef	ISP_TARGET_MODE