Skip to content

Commit 7c51a90

Browse files
committed
scsi: lpfc: Fix buffer free/clear order in deferred receive path
jira VULN-156029 cve CVE-2025-39841 commit-author John Evans <evans1210144@gmail.com> commit 9dba9a4 Fix a use-after-free window by correcting the buffer release sequence in the deferred receive path. The code freed the RQ buffer first and only then cleared the context pointer under the lock. Concurrent paths (e.g., ABTS and the repost path) also inspect and release the same pointer under the lock, so the old order could lead to double-free/UAF. Note that the repost path already uses the correct pattern: detach the pointer under the lock, then free it after dropping the lock. The deferred path should do the same. Fixes: 472e146 ("scsi: lpfc: Correct upcalling nvmet_fc transport during io done downcall") Cc: stable@vger.kernel.org Signed-off-by: John Evans <evans1210144@gmail.com> Link: https://lore.kernel.org/r/20250828044008.743-1-evans1210144@gmail.com Reviewed-by: Justin Tee <justin.tee@broadcom.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> (cherry picked from commit 9dba9a4) Signed-off-by: Roxana Nicolescu <rnicolescu@ciq.com>
1 parent c17a9df commit 7c51a90

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

drivers/scsi/lpfc/lpfc_nvmet.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,31 +1241,33 @@ lpfc_nvmet_defer_rcv(struct nvmet_fc_target_port *tgtport,
12411241
struct lpfc_nvmet_tgtport *tgtp;
12421242
struct lpfc_async_xchg_ctx *ctxp =
12431243
container_of(rsp, struct lpfc_async_xchg_ctx, hdlrctx.fcp_req);
1244-
struct rqb_dmabuf *nvmebuf = ctxp->rqb_buffer;
1244+
struct rqb_dmabuf *nvmebuf;
12451245
struct lpfc_hba *phba = ctxp->phba;
12461246
unsigned long iflag;
12471247

12481248

12491249
lpfc_nvmeio_data(phba, "NVMET DEFERRCV: xri x%x sz %d CPU %02x\n",
12501250
ctxp->oxid, ctxp->size, raw_smp_processor_id());
12511251

1252+
spin_lock_irqsave(&ctxp->ctxlock, iflag);
1253+
nvmebuf = ctxp->rqb_buffer;
12521254
if (!nvmebuf) {
1255+
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
12531256
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_IOERR,
12541257
"6425 Defer rcv: no buffer oxid x%x: "
12551258
"flg %x ste %x\n",
12561259
ctxp->oxid, ctxp->flag, ctxp->state);
12571260
return;
12581261
}
1262+
ctxp->rqb_buffer = NULL;
1263+
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
12591264

12601265
tgtp = phba->targetport->private;
12611266
if (tgtp)
12621267
atomic_inc(&tgtp->rcv_fcp_cmd_defer);
12631268

12641269
/* Free the nvmebuf since a new buffer already replaced it */
12651270
nvmebuf->hrq->rqbp->rqb_free_buffer(phba, nvmebuf);
1266-
spin_lock_irqsave(&ctxp->ctxlock, iflag);
1267-
ctxp->rqb_buffer = NULL;
1268-
spin_unlock_irqrestore(&ctxp->ctxlock, iflag);
12691271
}
12701272

12711273
static void

0 commit comments

Comments
 (0)