lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20240117080344.3817969-1-alexious@zju.edu.cn>
Date: Wed, 17 Jan 2024 16:03:42 +0800
From: Zhipeng Lu <alexious@....edu.cn>
To: alexious@....edu.cn
Cc: James Smart <james.smart@...adcom.com>,
	Ram Vegesna <ram.vegesna@...adcom.com>,
	"James E.J. Bottomley" <jejb@...ux.ibm.com>,
	"Martin K. Petersen" <martin.petersen@...cle.com>,
	Daniel Wagner <dwagner@...e.de>,
	Hannes Reinecke <hare@...e.de>,
	linux-scsi@...r.kernel.org,
	target-devel@...r.kernel.org,
	linux-kernel@...r.kernel.org
Subject: [PATCH] scsi: elx: efec: Fix a memleak in efct_hw_setup_io

In the error-handling path of hw->wqe_buffs, not only hw->io, but also
hw->io[i] should be freed. They should also be freed in the following
error-hanlding paths. So as the first dma->virt, which needs to be freed
when efct_hw_reqtag_alloc, sli_resource_alloc and the second
dma_alloc_coherent fails.

Fixes: 4df84e846624 ("scsi: elx: efct: Driver initialization routines")
Signed-off-by: Zhipeng Lu <alexious@....edu.cn>
---
 drivers/scsi/elx/efct/efct_hw.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/elx/efct/efct_hw.c b/drivers/scsi/elx/efct/efct_hw.c
index 5a5525054d71..62ef741a3ccf 100644
--- a/drivers/scsi/elx/efct/efct_hw.c
+++ b/drivers/scsi/elx/efct/efct_hw.c
@@ -485,6 +485,7 @@ efct_hw_setup_io(struct efct_hw *hw)
 	bool new_alloc = true;
 	struct efc_dma *dma;
 	struct efct *efct = hw->os;
+	int ret;
 
 	if (!hw->io) {
 		hw->io = kmalloc_array(hw->config.n_io, sizeof(io), GFP_KERNEL);
@@ -495,16 +496,18 @@ efct_hw_setup_io(struct efct_hw *hw)
 
 		for (i = 0; i < hw->config.n_io; i++) {
 			hw->io[i] = kzalloc(sizeof(*io), GFP_KERNEL);
-			if (!hw->io[i])
+			if (!hw->io[i]) {
+				ret = -ENOMEM;
 				goto error;
+			}
 		}
 
 		/* Create WQE buffs for IO */
 		hw->wqe_buffs = kzalloc((hw->config.n_io * hw->sli.wqe_size),
 					GFP_KERNEL);
 		if (!hw->wqe_buffs) {
-			kfree(hw->io);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto error;
 		}
 
 	} else {
@@ -517,8 +520,10 @@ efct_hw_setup_io(struct efct_hw *hw)
 		dma->size = sizeof(struct fcp_txrdy) * hw->config.n_io;
 		dma->virt = dma_alloc_coherent(&efct->pci->dev,
 					       dma->size, &dma->phys, GFP_KERNEL);
-		if (!dma->virt)
-			return -ENOMEM;
+		if (!dma->virt) {
+			ret = -ENOMEM;
+			goto free_wqe_buffs;
+		}
 	}
 	xfer_virt = (uintptr_t)hw->xfer_rdy.virt;
 	xfer_phys = hw->xfer_rdy.phys;
@@ -539,7 +544,8 @@ efct_hw_setup_io(struct efct_hw *hw)
 		wqcb = efct_hw_reqtag_alloc(hw, efct_hw_wq_process_io, io);
 		if (!wqcb) {
 			efc_log_err(hw->os, "can't allocate request tag\n");
-			return -ENOSPC;
+			ret = -ENOSPC;
+			goto free_dma_virt;
 		}
 		io->reqtag = wqcb->instance_index;
 
@@ -553,7 +559,8 @@ efct_hw_setup_io(struct efct_hw *hw)
 				       &io->indicator, &index)) {
 			efc_log_err(hw->os,
 				    "sli_resource_alloc failed @ %d\n", i);
-			return -ENOMEM;
+			ret = -ENOMEM;
+			goto free_dma_virt;
 		}
 
 		if (new_alloc) {
@@ -567,7 +574,8 @@ efct_hw_setup_io(struct efct_hw *hw)
 				efc_log_err(hw->os, "dma_alloc fail %d\n", i);
 				memset(&io->def_sgl, 0,
 				       sizeof(struct efc_dma));
-				return -ENOMEM;
+				ret = -ENOMEM;
+				goto free_dma_virt;
 			}
 		}
 		io->def_sgl_count = hw->config.n_sgl;
@@ -585,6 +593,12 @@ efct_hw_setup_io(struct efct_hw *hw)
 	}
 
 	return 0;
+free_dma_virt:
+	dma = &hw->xfer_rdy;
+	dma_free_coherent(&efct->pci->dev, dma->size, dma->virt, dma->phys);
+	memset(dma, 0, sizeof(struct efc_dma));
+free_wqe_buffs:
+	kfree(hw->wqe_buffs);
 error:
 	for (i = 0; i < hw->config.n_io && hw->io[i]; i++) {
 		kfree(hw->io[i]);
@@ -594,7 +608,7 @@ efct_hw_setup_io(struct efct_hw *hw)
 	kfree(hw->io);
 	hw->io = NULL;
 
-	return -ENOMEM;
+	return ret;
 }
 
 static int
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ