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 2/2] scsi: lpfc: add KUnit coverage for EDC descriptor bounds
Date: Thu, 9 Jul 2026 22:29:32 -0400 [thread overview]
Message-ID: <20260710022932.3741311-3-michael.bommarito@gmail.com> (raw)
In-Reply-To: <20260710022932.3741311-1-michael.bommarito@gmail.com>
Add KUnit coverage for lpfc_els_rcv_edc() descriptor-list bounds. The
tests live in lpfc_els.c so they can drive the real static EDC parser
without exporting test-only symbols.
The suite covers a valid congestion-signaling EDC descriptor and a
malformed EDC payload whose top-level descriptor-list length exceeds the
received payload. That malformed case documents the frame rejected by
the previous patch.
Assisted-by: Codex:gpt-5-5-xhigh
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
---
drivers/scsi/Kconfig | 7 ++
drivers/scsi/lpfc/lpfc_els.c | 154 +++++++++++++++++++++++++++++++++++
2 files changed, 161 insertions(+)
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 19d0884479a24..e0f01ddd22707 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1163,6 +1163,13 @@ config SCSI_LPFC_DEBUG_FS
This makes debugging information from the lpfc driver
available via the debugfs filesystem.
+config LPFC_EDC_KUNIT_TEST
+ bool "KUnit tests for lpfc EDC descriptor bounds" if !KUNIT_ALL_TESTS
+ depends on KUNIT && SCSI_LPFC
+ default KUNIT_ALL_TESTS
+ help
+ Internal validation coverage for lpfc EDC descriptor list bounds.
+
source "drivers/scsi/elx/Kconfig"
config SCSI_SIM710
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 5408b116f2d5a..0711f88da3f1a 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -12574,3 +12574,157 @@ lpfc_cmpl_els_uvem(struct lpfc_hba *phba, struct lpfc_iocbq *icmdiocb,
lpfc_els_free_iocb(phba, icmdiocb);
lpfc_nlp_put(ndlp);
}
+
+#if IS_ENABLED(CONFIG_LPFC_EDC_KUNIT_TEST)
+#include <kunit/device.h>
+#include <kunit/test.h>
+
+static void lpfc_edc_kunit_prep_stub(struct lpfc_iocbq *cmdiocbq,
+ struct lpfc_vport *vport,
+ struct lpfc_dmabuf *bmp, u16 cmd_size,
+ u32 did, u32 elscmd, u8 tmo,
+ u8 expect_rsp)
+{
+}
+
+static void lpfc_edc_kunit_release_stub(struct lpfc_hba *phba,
+ struct lpfc_iocbq *iocbq)
+{
+}
+
+static int lpfc_edc_kunit_issue_mbox_stub(struct lpfc_hba *phba,
+ LPFC_MBOXQ_t *mboxq,
+ uint32_t flag)
+{
+ mempool_free(mboxq, phba->mbox_mem_pool);
+ return 0;
+}
+
+static void lpfc_edc_kunit_setup_hba(struct kunit *test,
+ struct lpfc_hba *phba,
+ struct lpfc_vport *vport)
+{
+ struct lpfc_iocbq *free_iocbs;
+ struct device *kdev;
+ int i;
+
+ spin_lock_init(&phba->hbalock);
+ INIT_LIST_HEAD(&phba->lpfc_iocb_list);
+ INIT_LIST_HEAD(&phba->elsbuf);
+ phba->link_state = LPFC_LINK_DOWN;
+ phba->sli_rev = LPFC_SLI_REV3;
+ phba->__lpfc_sli_prep_els_req_rsp = lpfc_edc_kunit_prep_stub;
+ phba->__lpfc_sli_release_iocbq = lpfc_edc_kunit_release_stub;
+ phba->lpfc_sli_issue_mbox = lpfc_edc_kunit_issue_mbox_stub;
+ phba->pport = vport;
+
+ free_iocbs = kunit_kzalloc(test, 4 * sizeof(*free_iocbs), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, free_iocbs);
+ for (i = 0; i < 4; i++)
+ list_add_tail(&free_iocbs[i].list, &phba->lpfc_iocb_list);
+
+ kdev = kunit_device_register(test, "lpfc_edc_test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, kdev);
+ phba->lpfc_mbuf_pool = dma_pool_create("lpfc_edc_mbuf", kdev,
+ LPFC_BPL_SIZE, 8, 0);
+ KUNIT_ASSERT_NOT_NULL(test, phba->lpfc_mbuf_pool);
+ phba->mbox_mem_pool = mempool_create_kmalloc_pool(1,
+ sizeof(LPFC_MBOXQ_t));
+ KUNIT_ASSERT_NOT_NULL(test, phba->mbox_mem_pool);
+}
+
+static void lpfc_edc_kunit_teardown_hba(struct lpfc_hba *phba)
+{
+ if (phba->mbox_mem_pool)
+ mempool_destroy(phba->mbox_mem_pool);
+ if (phba->lpfc_mbuf_pool)
+ dma_pool_destroy(phba->lpfc_mbuf_pool);
+}
+
+static void lpfc_edc_kunit_run(struct kunit *test, bool malformed)
+{
+ struct lpfc_hba *phba;
+ struct lpfc_vport *vport;
+ struct lpfc_nodelist *ndlp;
+ struct lpfc_iocbq *cmdiocb;
+ struct lpfc_dmabuf *cmd_dmabuf;
+ struct fc_els_edc *edc;
+ struct fc_tlv_desc *tlv;
+ size_t payload_len;
+
+ phba = kunit_kzalloc(test, sizeof(*phba), GFP_KERNEL);
+ vport = kunit_kzalloc(test, sizeof(*vport), GFP_KERNEL);
+ ndlp = kunit_kzalloc(test, sizeof(*ndlp), GFP_KERNEL);
+ cmdiocb = kunit_kzalloc(test, sizeof(*cmdiocb), GFP_KERNEL);
+ cmd_dmabuf = kunit_kzalloc(test, sizeof(*cmd_dmabuf), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, phba);
+ KUNIT_ASSERT_NOT_NULL(test, vport);
+ KUNIT_ASSERT_NOT_NULL(test, ndlp);
+ KUNIT_ASSERT_NOT_NULL(test, cmdiocb);
+ KUNIT_ASSERT_NOT_NULL(test, cmd_dmabuf);
+
+ vport->phba = phba;
+ ndlp->nlp_DID = Fabric_Cntl_DID;
+ lpfc_edc_kunit_setup_hba(test, phba, vport);
+
+ if (malformed)
+ payload_len = sizeof(*edc) + FC_TLV_DESC_HDR_SZ;
+ else
+ payload_len = sizeof(*edc) +
+ sizeof(struct fc_diag_cg_sig_desc);
+
+ cmd_dmabuf->virt = kunit_kzalloc(test, payload_len, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, cmd_dmabuf->virt);
+ INIT_LIST_HEAD(&cmd_dmabuf->list);
+
+ edc = cmd_dmabuf->virt;
+ edc->edc_cmd = ELS_EDC;
+ tlv = edc->desc;
+ if (malformed) {
+ edc->desc_len = cpu_to_be32(0x100);
+ tlv->desc_tag = cpu_to_be32(0xdeadbeef);
+ tlv->desc_len = cpu_to_be32(0);
+ } else {
+ struct fc_diag_cg_sig_desc *cgn = (void *)tlv;
+
+ edc->desc_len = cpu_to_be32(sizeof(*cgn));
+ cgn->desc_tag = cpu_to_be32(ELS_DTAG_CG_SIGNAL_CAP);
+ cgn->desc_len =
+ cpu_to_be32(FC_TLV_DESC_LENGTH_FROM_SZ(*cgn));
+ cgn->xmt_signal_capability =
+ cpu_to_be32(EDC_CG_SIG_NOTSUPPORTED);
+ cgn->xmt_signal_frequency.count =
+ cpu_to_be16(EDC_CG_SIGFREQ_CNT_MIN);
+ cgn->xmt_signal_frequency.units =
+ cpu_to_be16(EDC_CG_SIGFREQ_MSEC);
+ }
+
+ cmdiocb->cmd_dmabuf = cmd_dmabuf;
+ lpfc_els_rcv_edc(vport, cmdiocb, ndlp, payload_len);
+
+ KUNIT_EXPECT_TRUE(test, true);
+ lpfc_edc_kunit_teardown_hba(phba);
+}
+
+static void lpfc_edc_control_test(struct kunit *test)
+{
+ lpfc_edc_kunit_run(test, false);
+}
+
+static void lpfc_edc_oob_test(struct kunit *test)
+{
+ lpfc_edc_kunit_run(test, true);
+}
+
+static struct kunit_case lpfc_edc_test_cases[] = {
+ KUNIT_CASE(lpfc_edc_control_test),
+ KUNIT_CASE(lpfc_edc_oob_test),
+ {}
+};
+
+static struct kunit_suite lpfc_edc_test_suite = {
+ .name = "lpfc_edc",
+ .test_cases = lpfc_edc_test_cases,
+};
+kunit_test_suite(lpfc_edc_test_suite);
+#endif /* CONFIG_LPFC_EDC_KUNIT_TEST */
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 ` [PATCH 1/2] scsi: lpfc: bound EDC descriptor list by payload length Michael Bommarito
2026-07-10 2:29 ` Michael Bommarito [this message]
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-3-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