From: Michael Bommarito <michael.bommarito@gmail.com>
To: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>,
"Martin K. Petersen" <martin.petersen@oracle.com>,
Justin Tee <justin.tee@broadcom.com>
Cc: Paul Ely <paul.ely@broadcom.com>,
James Smart <jsmart2021@gmail.com>,
linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH 1/2] scsi: lpfc: bound EDC descriptor list by payload length
Date: Thu, 9 Jul 2026 22:29:31 -0400 [thread overview]
Message-ID: <20260710022932.3741311-2-michael.bommarito@gmail.com> (raw)
In-Reply-To: <20260710022932.3741311-1-michael.bommarito@gmail.com>
drivers/scsi/lpfc/lpfc_els.c:lpfc_els_rcv_edc() trusts the EDC
descriptor-list length from the received frame without checking that it
fits in the actual ELS payload. An adjacent Fibre Channel fabric peer or
device can send an unsolicited EDC frame with a short payload and an
oversized descriptor-list length. The TLV walk can then read past the
receive buffer and trip a KASAN slab-out-of-bounds read in the LPFC ELS
receive path.
Impact: An adjacent Fibre Channel fabric peer or device can crash an
LPFC host via a malformed EDC ELS frame.
Pass the received payload length into lpfc_els_rcv_edc(), reject
truncated EDC headers and descriptor lists larger than the received
payload, and avoid logging a third payload word unless it is present.
Fixes: 9064aeb2df8e ("scsi: lpfc: Add EDC ELS support")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5-5-xhigh
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
I reproduced this with a same-translation-unit KUnit/KASAN test on
f5459048c38a. Without the patch, the malformed EDC frame triggers
BUG: KASAN: slab-out-of-bounds in lpfc_els_rcv_edc after the benign EDC
control passes. With the patch, the benign and malformed KUnit cases
both pass.
drivers/scsi/lpfc/lpfc_els.c | 41 ++++++++++++++++++++++++------------
1 file changed, 28 insertions(+), 13 deletions(-)
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index cee709617a313..5408b116f2d5a 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -9409,13 +9409,14 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
+ * @payload_len: received EDC payload length in bytes.
*
* Return code
* 0 - Successfully processed echo iocb (currently always return 0)
**/
static int
lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
- struct lpfc_nodelist *ndlp)
+ struct lpfc_nodelist *ndlp, u32 payload_len)
{
struct lpfc_hba *phba = vport->phba;
struct fc_els_edc *edc_req;
@@ -9423,25 +9424,39 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
uint8_t *payload;
uint32_t *ptr, dtag;
const char *dtag_nm;
- int desc_cnt = 0, bytes_remain;
+ int desc_cnt = 0;
+ u32 bytes_remain, desc_len, word2 = 0;
struct fc_diag_lnkflt_desc *plnkflt;
payload = cmdiocb->cmd_dmabuf->virt;
+ /* No signal support unless there is a congestion descriptor */
+ phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
+ phba->cgn_sig_freq = 0;
+ phba->cgn_reg_fpin = LPFC_CGN_FPIN_ALARM | LPFC_CGN_FPIN_WARN;
+
+ if (payload_len < sizeof(*edc_req))
+ goto out;
+
edc_req = (struct fc_els_edc *)payload;
- bytes_remain = be32_to_cpu(edc_req->desc_len);
+ desc_len = be32_to_cpu(edc_req->desc_len);
+ if (desc_len > payload_len - sizeof(*edc_req)) {
+ lpfc_printf_log(phba, KERN_WARNING,
+ LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
+ "6468 Bad EDC descriptor list length %u: %u\n",
+ desc_len, payload_len);
+ goto out;
+ }
+ bytes_remain = desc_len;
ptr = (uint32_t *)payload;
+ if (payload_len >= 3 * sizeof(*ptr))
+ word2 = be32_to_cpu(*(ptr + 2));
lpfc_printf_vlog(vport, KERN_INFO,
LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
- "3319 Rcv EDC payload len %d: x%x x%x x%x\n",
+ "3319 Rcv EDC payload len %u: x%x x%x x%x\n",
bytes_remain, be32_to_cpu(*ptr),
- be32_to_cpu(*(ptr + 1)), be32_to_cpu(*(ptr + 2)));
-
- /* No signal support unless there is a congestion descriptor */
- phba->cgn_reg_signal = EDC_CG_SIG_NOTSUPPORTED;
- phba->cgn_sig_freq = 0;
- phba->cgn_reg_fpin = LPFC_CGN_FPIN_ALARM | LPFC_CGN_FPIN_WARN;
+ be32_to_cpu(*(ptr + 1)), word2);
if (bytes_remain <= 0)
goto out;
@@ -9471,7 +9486,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
lpfc_printf_log(phba, KERN_WARNING,
LOG_ELS | LOG_CGN_MGMT | LOG_LDS_EVENT,
"6465 Truncated Link Fault Diagnostic "
- "descriptor[%d]: %d vs 0x%zx 0x%zx\n",
+ "descriptor[%d]: %u vs 0x%zx 0x%zx\n",
desc_cnt, bytes_remain,
FC_TLV_DESC_SZ_FROM_LENGTH(tlv),
sizeof(struct fc_diag_lnkflt_desc));
@@ -9497,7 +9512,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
lpfc_printf_log(
phba, KERN_WARNING, LOG_CGN_MGMT,
"6466 Truncated cgn signal Diagnostic "
- "descriptor[%d]: %d vs 0x%zx 0x%zx\n",
+ "descriptor[%d]: %u vs 0x%zx 0x%zx\n",
desc_cnt, bytes_remain,
FC_TLV_DESC_SZ_FROM_LENGTH(tlv),
sizeof(struct fc_diag_cg_sig_desc));
@@ -10815,7 +10830,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
/* There are no replies, so no rjt codes */
break;
case ELS_CMD_EDC:
- lpfc_els_rcv_edc(vport, elsiocb, ndlp);
+ lpfc_els_rcv_edc(vport, elsiocb, ndlp, payload_len);
break;
case ELS_CMD_RDF:
phba->fc_stat.elsRcvRDF++;
next prev parent reply other threads:[~2026-07-10 2:29 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-10 2:29 [PATCH 0/2] scsi: lpfc: bound EDC descriptor TLV walk Michael Bommarito
2026-07-10 2:29 ` Michael Bommarito [this message]
2026-07-10 2:29 ` [PATCH 2/2] scsi: lpfc: add KUnit coverage for EDC descriptor bounds Michael Bommarito
2026-07-10 16:53 ` [PATCH 0/2] scsi: lpfc: bound EDC descriptor TLV walk Justin Tee
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260710022932.3741311-2-michael.bommarito@gmail.com \
--to=michael.bommarito@gmail.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=jsmart2021@gmail.com \
--cc=justin.tee@broadcom.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=martin.petersen@oracle.com \
--cc=paul.ely@broadcom.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox