[RESEND PATCH] scsi: megaraid_sas: Fix double free on cmd_list alloc failure

Dawei Feng posted 1 patch 3 days, 17 hours ago
drivers/scsi/megaraid/megaraid_sas_fusion.c | 1 +
1 file changed, 1 insertion(+)
[RESEND PATCH] scsi: megaraid_sas: Fix double free on cmd_list alloc failure
Posted by Dawei Feng 3 days, 17 hours ago
If one of the per-command allocations in
megasas_alloc_cmdlist_fusion() fails, megasas_alloc_cmdlist_fusion()
frees the previously allocated command objects and the cmd_list array
before returning an error. megasas_alloc_cmds_fusion() then goes to
fail_exit and calls megasas_free_cmds_fusion(), which tries to free
the same cmd_list resources again.

Set fusion->cmd_list to NULL after local cleanup in
megasas_alloc_cmdlist_fusion() so the outer cleanup path skips the
already freed array and only releases the remaining resources.

The bug was first flagged by an experimental analysis tool we are
developing for kernel memory-management bugs while analyzing
v6.13-rc1. The tool is still under development and is not yet publicly
available. Manual inspection confirms that the bug is still
present in v7.1-rc3.

Runtime validation was not performed because reproducing this path
requires a MegaRAID controller and fault injection for command-list
allocation failure during controller initialization.

Fixes: e97e673ca63b ("scsi: megaraid_sas: Retry with reduced queue depth when alloc fails for higher QD")
Cc: stable@vger.kernel.org
Signed-off-by: Zilin Guan <zilin@seu.edu.cn>
Signed-off-by: Dawei Feng <dawei.feng@seu.edu.cn>
---
Resending to LKML as I had a typo in the domain name earlier. No code changes.
 drivers/scsi/megaraid/megaraid_sas_fusion.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c
index 2699e4e09b5b..a68e08132a61 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fusion.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c
@@ -611,6 +611,7 @@ megasas_alloc_cmdlist_fusion(struct megasas_instance *instance)
 			for (j = 0; j < i; j++)
 				kfree(fusion->cmd_list[j]);
 			kfree(fusion->cmd_list);
+			fusion->cmd_list = NULL;
 			dev_err(&instance->pdev->dev,
 				"Failed from %s %d\n",  __func__, __LINE__);
 			return -ENOMEM;
-- 
2.34.1