From: Justin Tee justin.tee@broadcom.com
[ Upstream commit 6698796282e828733cde3329c887b4ae9e5545e9 ]
If a call to lpfc_sli4_read_rev() from lpfc_sli4_hba_setup() fails, the resultant cleanup routine lpfc_sli4_vport_delete_fcp_xri_aborted() may occur before sli4_hba.hdwqs are allocated. This may result in a null pointer dereference when attempting to take the abts_io_buf_list_lock for the first hardware queue. Fix by adding a null ptr check on phba->sli4_hba.hdwq and early return because this situation means there must have been an error during port initialization.
Signed-off-by: Justin Tee justin.tee@broadcom.com Link: https://lore.kernel.org/r/20250618192138.124116-4-justintee8345@gmail.com Signed-off-by: Martin K. Petersen martin.petersen@oracle.com Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
So, the issue is: 1. During driver initialization in `lpfc_sli4_pci_probe()` (around line 14868), `lpfc_sli4_hba_setup()` is called 2. Inside `lpfc_sli4_hba_setup()` at line 8517, `lpfc_sli4_read_rev()` is called 3. If `lpfc_sli4_read_rev()` fails, we goto `out_free_mbox` which returns error 4. The queue creation (`lpfc_sli4_queue_create()` at line 8811) that allocates `hdwq` is never reached 5. When the error is returned to `lpfc_sli4_pci_probe()`, it goes to `out_free_sysfs_attr` 6. This error path calls `lpfc_destroy_shost()` -> `destroy_port()` -> `lpfc_cleanup()` -> `lpfc_cleanup_vports_rrqs()` -> `lpfc_sli4_vport_delete_fcp_xri_aborted()` 7. `lpfc_sli4_vport_delete_fcp_xri_aborted()` tries to access `phba->sli4_hba.hdwq[idx]` which is NULL, causing a null pointer dereference
## Backport Analysis
**YES**
This commit should be backported to stable kernel trees for the following reasons:
1. **Critical Bug Fix**: The commit fixes a NULL pointer dereference that can cause a kernel crash. This is a serious bug that affects system stability when the lpfc driver fails to initialize properly.
2. **Clear Error Path Issue**: The bug occurs in a well-defined error handling path - when `lpfc_sli4_read_rev()` fails during HBA setup. This is not a theoretical issue but can happen in real-world scenarios when hardware initialization fails.
3. **Small and Contained Fix**: The fix is minimal - just adding a NULL check with early return (4 lines of code). This follows the stable kernel criteria of being a small, focused fix that addresses a specific issue.
4. **No Architectural Changes**: The fix doesn't introduce any new features or change the driver architecture. It simply adds defensive programming to prevent accessing unallocated memory.
5. **Low Risk of Regression**: The added check `if (!phba->sli4_hba.hdwq) return;` is safe - if hdwq is NULL, the function cannot proceed anyway. The early return prevents the crash without affecting normal operation when hdwq is properly allocated.
6. **Matches Stable Rules**: According to stable kernel rules, fixes for kernel crashes and oopses are prime candidates for backporting. This commit specifically prevents a NULL pointer dereference that would result in a kernel oops.
7. **Driver Initialization Robustness**: The issue affects error handling during driver initialization, which is a critical path. Failures during initialization should be handled gracefully without causing system crashes.
The commit message clearly describes the problem scenario and the solution, making it easy for stable maintainers to understand the importance of this fix. The fact that it adds a defensive check before dereferencing a pointer that may not be allocated in error paths is exactly the type of robustness improvement that stable kernels should receive.
drivers/scsi/lpfc/lpfc_scsi.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 8acb744febcd..31a9f142bcb9 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -390,6 +390,10 @@ lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport) if (!(vport->cfg_enable_fc4_type & LPFC_ENABLE_FCP)) return;
+ /* may be called before queues established if hba_setup fails */ + if (!phba->sli4_hba.hdwq) + return; + spin_lock_irqsave(&phba->hbalock, iflag); for (idx = 0; idx < phba->cfg_hdw_queue; idx++) { qp = &phba->sli4_hba.hdwq[idx];