[PATCH] scsi: qla2xxx: Fix resource leak and metadata corruption in default_item cleanup
From: Jiasheng Jiang
Date: Mon Feb 16 2026 - 15:31:16 EST
The qla2xxx driver utilizes a pre-allocated fallback item
(vha->default_item) to handle purex items during low memory (OOM)
conditions. Its lifecycle is managed via an atomic counter (in_use).
However, the cleanup paths for this item exhibit two critical
inconsistencies that lead to resource leaks and potential crashes:
1. In `qla24xx_free_purex_list()`, when the default_item is encountered,
it is removed from the list and skipped via `continue`, but its
`in_use` atomic counter is never decremented. Consequently, once the
default_item is used for the first time, its reference count remains
elevated permanently, rendering the fallback mechanism dead in all
subsequent OOM scenarios.
2. In `qla24xx_free_purex_item()`, the function attempts to reset the
default_item using a blanket `memset()`. This non-atomic operation not
only clobbers the `in_use` counter but also zeroes out essential
metadata pointers, most notably `item->vha`. If this default_item is
subsequently reallocated, any dereference of `item->vha` will result
in a NULL pointer dereference and a kernel panic.
Fix both issues by replacing the destructive `memset()` and the leaky
`continue` path with a unified, safe atomic reset of the `in_use`
counter (`atomic_set(&item->vha->default_item.in_use, 0)`). This
properly relinquishes the item for future allocations while preserving
its structural integrity.
Fixes: 0972252450f9 ("scsi: qla2xxx: Fix crash during module load unload test")
Fixes: 62e9dd177732 ("scsi: qla2xxx: Change in PUREX to handle FPIN ELS requests")
Signed-off-by: Jiasheng Jiang <jiashengjiangcool@xxxxxxxxx>
---
drivers/scsi/qla2xxx/qla_os.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a88b460641f2..a424dc6b093e 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -3984,8 +3984,10 @@ qla24xx_free_purex_list(struct purex_list *list)
spin_lock_irqsave(&list->lock, flags);
list_for_each_entry_safe(item, next, &list->head, list) {
list_del(&item->list);
- if (item == &item->vha->default_item)
+ if (item == &item->vha->default_item) {
+ atomic_set(&item->vha->default_item.in_use, 0);
continue;
+ }
kfree(item);
}
spin_unlock_irqrestore(&list->lock, flags);
@@ -6467,7 +6469,7 @@ void
qla24xx_free_purex_item(struct purex_item *item)
{
if (item == &item->vha->default_item)
- memset(&item->vha->default_item, 0, sizeof(struct purex_item));
+ atomic_set(&item->vha->default_item.in_use, 0);
else
kfree(item);
}
--
2.25.1