From nobody Sun Jul 26 01:45:21 2026 Received: from mail-qk1-f175.google.com (mail-qk1-f175.google.com [209.85.222.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D92DF1FE471 for ; Fri, 10 Jul 2026 02:29:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783650581; cv=none; b=hoGDqqpgrROuU0h6FoWpP+VG5KVWsCTJKJF0dXx9f+PRl9yQnhJuMQy1ZB/tvTPRgCDrQxBpgegSfK8a7wRSw/mJ5VHl6xSm+M9H1biowOfWTvRkF4ZLmmbfNLjHyDXWCUHGnqRrU5OeL+ehR+8SNAuD3VKrenw7eVsKsQq1vlg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783650581; c=relaxed/simple; bh=0xR7aHWTe/ITOzofM0fEnD0N5azaQJKg215EeZ5MstQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CNgJ04zanUubvz72/S0mFoLgfbKyg154A3Py/uEszmgmEt7hVTYedqbVyRUNNTgnUq77KiibSWeJdkjxsTy6rP2kUMlZHPr9tmXx39jkLcC7d5QgP1K8Qpft9LvYvAaFDKWXB8FaKyNcfmkf6BlZgBgp1paAKpE3H9heUMTbego= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nXu0VNe7; arc=none smtp.client-ip=209.85.222.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nXu0VNe7" Received: by mail-qk1-f175.google.com with SMTP id af79cd13be357-92e50a650a0so18290885a.1 for ; Thu, 09 Jul 2026 19:29:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783650579; x=1784255379; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=l0wDYbfJ49+lBvuR6ZGZa4EeCwLvpXP1kmuJhSQU9pU=; b=nXu0VNe7sw6Ecayvuvzkxmmf0b+nN9//1ET/vXD9gUcwJnK4KZN1pByOwsvTdA0ShO XoQyYvwHXqnLIHJsZ7le82ShjdKib5zlXnB+dquZlrdflHdGkTBgIKnL8Z2UeOiX1OMg ZgUo9vjYaDYtygJkqEZvS6JiG8iLoLjggp+WZgvw9m32l6gFrdtIinDAStBkgwkrNSMP mgYvbK9aeWS8Y9uMjLvTh9J3QreNoHrEPv23JaiJqehEdYyVjxWG2veTZtVE3PFoxXFm VJZ36M4H3PEMKFFqOEghBxaaGC9oZ0Qm4/P+4af7u4U3w69Fmr1bYVq4ZZ/njjG6mO4f tE8w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783650579; x=1784255379; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=l0wDYbfJ49+lBvuR6ZGZa4EeCwLvpXP1kmuJhSQU9pU=; b=pagBB1pvIpdXQTUKGQEap0xFieADUWknDG4SxFY/ERyKMclG9IaZDSzcsmkbGYBHoW lrm2dF0X4M18yIKByQcGX3DA6b4dVFMVocCcAmt7VQ6E7TgnLb1ZtyUa67aM7fa50OLK JE2lY+sxCwcpL4i47NdNH32f27mzf9CBCpDNclc3SEN3a0ROcpoK7xYL2OHUCHy8BNml Q33+PRmdEodiGiQU5x63mGPPlH0OxIqSVyA5KRPBcb66uvKrFdrZWCGifvxmLmCzo/nM ggz0HCwFG+wlYzbT78rTgVybsg/CXgCcw4rCm/wCHXVXHAwWIJz/55yojhjFbaING03T GSMg== X-Forwarded-Encrypted: i=1; AHgh+RqIvFJS5n+LZsk07z8NACXizei3GkhfnV8IgBx5oP1ygqnrTTNi6QOpUBnslJ7J5NRPoUlf4QNrV51dbFI=@vger.kernel.org X-Gm-Message-State: AOJu0Yxis6jUXH+eksO3Ia2kbFlwowxkQyM+vdm6EzQXCGTa0mvf6axq wsA2WKzHMynfecg2R3DtLLr3kzPtetM+J1li6ZOYCNy0jBp7HrWgadM2 X-Gm-Gg: AfdE7ck/eW5LN5CaC+tqoDZmTVl5IPj329bwV0UFBQzNGPyMdKdj+hIhLc9m3lWwVDJ n5QalufGt7nXBcaWdRYRRKP8WM9SMAYmm/HrlA3Ni8C2aiQtAVgZOP9+rLAJ4AnFbw8Lpc7wgaP Zl+zX8hCKVPPWTU5cdxdC6VRNJ/CR+5weSvbvaO3lmqCoGRDiH3gsxgbApXWBvYMRCzL3HnuLOt ujnRGvbp3GhlGj+11x18m6e2bwVKxjyAxESPqmQoXgLE2z4DMq/KW3lhzLRNWGuzkA9CugNdZiu 0fb6aOrAUdzgfHY2zoufNlpqqF1csl1OHaSAF3xJNTHDI2OA0YctzvtQHgeSovDt3tGbje4ZJ+6 mjd7xg/Vc7TSmQFQjIq/cM9XeGS0ZXhjV0VOXBKbvShHCQJdUccIHJYikJvDVSiI610Zottq5Bj yHGsaVFi+74Dysa2c4IKQBeoURGoDm/HgufhqAd7mGBn5EDwyqRDkh4atiTr/8H3PKJ8wFkFMN5 Qv9pFt9bNtJGrNGLPskGjh+9GAdv6YO X-Received: by 2002:ac8:7e8a:0:b0:51c:7b12:5fec with SMTP id d75a77b69052e-51c8b42d223mr130403491cf.88.1783650578948; Thu, 09 Jul 2026 19:29:38 -0700 (PDT) Received: from server0.tail6e7dd.ts.net (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-51caafd8b4fsm6951101cf.31.2026.07.09.19.29.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Jul 2026 19:29:38 -0700 (PDT) From: Michael Bommarito To: "James E.J. Bottomley" , "Martin K. Petersen" , Justin Tee Cc: Paul Ely , James Smart , 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 Message-ID: <20260710022932.3741311-2-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260710022932.3741311-1-michael.bommarito@gmail.com> References: <20260710022932.3741311-1-michael.bommarito@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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 l= pfc_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 =3D vport->phba; struct fc_els_edc *edc_req; @@ -9423,25 +9424,39 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct l= pfc_iocbq *cmdiocb, uint8_t *payload; uint32_t *ptr, dtag; const char *dtag_nm; - int desc_cnt =3D 0, bytes_remain; + int desc_cnt =3D 0; + u32 bytes_remain, desc_len, word2 =3D 0; struct fc_diag_lnkflt_desc *plnkflt; =20 payload =3D cmdiocb->cmd_dmabuf->virt; =20 + /* No signal support unless there is a congestion descriptor */ + phba->cgn_reg_signal =3D EDC_CG_SIG_NOTSUPPORTED; + phba->cgn_sig_freq =3D 0; + phba->cgn_reg_fpin =3D LPFC_CGN_FPIN_ALARM | LPFC_CGN_FPIN_WARN; + + if (payload_len < sizeof(*edc_req)) + goto out; + edc_req =3D (struct fc_els_edc *)payload; - bytes_remain =3D be32_to_cpu(edc_req->desc_len); + desc_len =3D 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 =3D desc_len; =20 ptr =3D (uint32_t *)payload; + if (payload_len >=3D 3 * sizeof(*ptr)) + word2 =3D 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 =3D EDC_CG_SIG_NOTSUPPORTED; - phba->cgn_sig_freq =3D 0; - phba->cgn_reg_fpin =3D LPFC_CGN_FPIN_ALARM | LPFC_CGN_FPIN_WARN; + be32_to_cpu(*(ptr + 1)), word2); =20 if (bytes_remain <=3D 0) goto out; @@ -9471,7 +9486,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpf= c_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 lpf= c_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++; From nobody Sun Jul 26 01:45:21 2026 Received: from mail-qt1-f174.google.com (mail-qt1-f174.google.com [209.85.160.174]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C0AD2E62D9 for ; Fri, 10 Jul 2026 02:29:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783650583; cv=none; b=WWYyA09C8Vj8dFVsfZe/f7Lr76sRVJR2PrTsDJqU1VpTODngGfOjktglmjXeL9ZyJ4Ff8+6U3gULBCS2SjlTtAxJfObwFiOET0T5o6eysfSg9HLWa0C72ofQLcXgW4+nOBqV3EPxDow+zMiis6nbkUvwsNfe6ZxNaqhI8WNui3g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783650583; c=relaxed/simple; bh=oh1kfYgKX27DSge+HLhXzF1K4TKLBE9pDdto0ALosBA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gr9HDg/MN6olVyFms4kN90HCD3Emw4kcyNiRkxC75EWgjHID2Q+PNKzY07KI5Uig9RJyIvx0Ng7XMwHZi8U20cJE0QnHM0XxV7SyA1ftNgg1zd159qgQztnBmJf6r/8B6r3sbKpJZ0ENttG4U7P3Kb1rkf2ij81DJzdS/z/4kLU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WtM4fSCk; arc=none smtp.client-ip=209.85.160.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WtM4fSCk" Received: by mail-qt1-f174.google.com with SMTP id d75a77b69052e-51c928bf172so2108991cf.3 for ; Thu, 09 Jul 2026 19:29:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783650581; x=1784255381; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=mSn3YhBAthUo8TVHErzQl7PVMQ/a9rmwb+lYlYlzHec=; b=WtM4fSCk8WQVq7J3/jep0Lo27p7P+M0h82njpmB26KnPQSTV8wXuhm1qZZ9QiWXE3r fpIGnKo/7pP5gZiI3s4tjXkM+BMhT7nzDmvcQDUfEqLYRkKrJKyBzVrAAt3SUXI1pT3w t8dwCj6pIUmaWHIE/UF2bl5RPnu6mpRR2QJZwvgMqcyjESrfzONxx0rOs2rAGNIbb7YS rLl16skn7nyRscKTvnOEBFYyG4x3p3k/JQDjX+zJVR2OHxJF8bl3LlF/ya/KHJNkBvx4 xFxOfVx2e3yUYLzayo35fRoZaPe/ArH3E5z+djbea/wNdrN2T5nCE/YSv285WJ0tO+Z8 oXrQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783650581; x=1784255381; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=mSn3YhBAthUo8TVHErzQl7PVMQ/a9rmwb+lYlYlzHec=; b=cv/mvD+gW50K7fseszhvJFPvlkfXeIXbtcLD6DQexv33yy5EfeU4PJOMOnZ+G5x2aM w0twa8bKs6DrzNYuat4lgKGljETDfrES9djRunebynu8t8cE+BaqP4JtOhNtihwP2t9q m5goKPluSggBaUWUtLxQpWxeqIo11VmaV/2cvTAo+BqOfJRas3HYbZyI05LNeOA4XatA 8P/isYEljP8oH60Zphr8Ta6tFAdMoQLsT4ozCK9EnltzMHTDiEHmUXxNgE/15tLQ5btQ 84ibI6rf/r7IY8IPCJpVWmsIbDWaEnna1Sq3v/Q72nDiVjTE0FHCduYeZIhH4QM7x26T EU2w== X-Forwarded-Encrypted: i=1; AHgh+RqcroDER387LVIuqV13L3g+stu4TRuE9UYCN9q0aS8gX9REpBoJ+eYPs8S2JBZRzpJ7WtkC4yyDyv4tpdc=@vger.kernel.org X-Gm-Message-State: AOJu0YxEY+5wAgFUhHrUKutfcUE3LC7fXNAwX6mrQznh4vnP3Nr1R2CA 4gw9WbrNEed4PB9zGLh/9xbcu1DMcFdIXjx3dmJC34dEsoRqPhep9tXK X-Gm-Gg: AfdE7cl1xlZ5PyRsOFLgMy/axI1ouEwdC42U9FYa99oieQHl9JXAZs01kVewH3691bq QBRdMDIUN94gjA58ZEi+CxkVLL3vfRtM78XDRTPLEgWCyqbs81GdjFblELlJRbWJeVh2MvPoiqd MU7wuA2X30FRjLHDRx/5S8gCiv80a5XYOz1OJ+9CcADTUkbq2C7S6ZreE8/L8pBg11D0s6rGKI8 mAOFphS53T94hStCTYBd441n5M2WncwDqBX8ts2emAK7Pb9S+I31+KN/dg3iSfexZHJcINkA5NP Jf+4bp0xBFqGsAh6i0AoPGwcRw3QOFL4M1AwvtbdLGznHIWzbFqG3QKSYqn7aOAOh2VKITBekMI O2qH8rLRF6OvsO0IejNs9s4bi7IEndxhrXLXWpcYYRW6+5WEarv/ITny/tXMnJ2ILZxqomtFsgW iR1hbHppAaByY8USrh2yATFyBUXPDLaPk1ba+2iZoiWmTHccN+tckONCgM9Q6e3ru7nQ/pzQGsy IRe/iXyqC0kv5N8WHL92vEha58W6PHd X-Received: by 2002:ac8:5a84:0:b0:51c:1967:5091 with SMTP id d75a77b69052e-51c8b3b4c44mr109183901cf.41.1783650580950; Thu, 09 Jul 2026 19:29:40 -0700 (PDT) Received: from server0.tail6e7dd.ts.net (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-51caafd8b4fsm6951101cf.31.2026.07.09.19.29.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 09 Jul 2026 19:29:39 -0700 (PDT) From: Michael Bommarito To: "James E.J. Bottomley" , "Martin K. Petersen" , Justin Tee Cc: Paul Ely , James Smart , 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 Message-ID: <20260710022932.3741311-3-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260710022932.3741311-1-michael.bommarito@gmail.com> References: <20260710022932.3741311-1-michael.bommarito@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 --- 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. =20 +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" =20 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 +#include + +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 =3D LPFC_LINK_DOWN; + phba->sli_rev =3D LPFC_SLI_REV3; + phba->__lpfc_sli_prep_els_req_rsp =3D lpfc_edc_kunit_prep_stub; + phba->__lpfc_sli_release_iocbq =3D lpfc_edc_kunit_release_stub; + phba->lpfc_sli_issue_mbox =3D lpfc_edc_kunit_issue_mbox_stub; + phba->pport =3D vport; + + free_iocbs =3D kunit_kzalloc(test, 4 * sizeof(*free_iocbs), GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, free_iocbs); + for (i =3D 0; i < 4; i++) + list_add_tail(&free_iocbs[i].list, &phba->lpfc_iocb_list); + + kdev =3D kunit_device_register(test, "lpfc_edc_test"); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, kdev); + phba->lpfc_mbuf_pool =3D 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 =3D 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 =3D kunit_kzalloc(test, sizeof(*phba), GFP_KERNEL); + vport =3D kunit_kzalloc(test, sizeof(*vport), GFP_KERNEL); + ndlp =3D kunit_kzalloc(test, sizeof(*ndlp), GFP_KERNEL); + cmdiocb =3D kunit_kzalloc(test, sizeof(*cmdiocb), GFP_KERNEL); + cmd_dmabuf =3D 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 =3D phba; + ndlp->nlp_DID =3D Fabric_Cntl_DID; + lpfc_edc_kunit_setup_hba(test, phba, vport); + + if (malformed) + payload_len =3D sizeof(*edc) + FC_TLV_DESC_HDR_SZ; + else + payload_len =3D sizeof(*edc) + + sizeof(struct fc_diag_cg_sig_desc); + + cmd_dmabuf->virt =3D kunit_kzalloc(test, payload_len, GFP_KERNEL); + KUNIT_ASSERT_NOT_NULL(test, cmd_dmabuf->virt); + INIT_LIST_HEAD(&cmd_dmabuf->list); + + edc =3D cmd_dmabuf->virt; + edc->edc_cmd =3D ELS_EDC; + tlv =3D edc->desc; + if (malformed) { + edc->desc_len =3D cpu_to_be32(0x100); + tlv->desc_tag =3D cpu_to_be32(0xdeadbeef); + tlv->desc_len =3D cpu_to_be32(0); + } else { + struct fc_diag_cg_sig_desc *cgn =3D (void *)tlv; + + edc->desc_len =3D cpu_to_be32(sizeof(*cgn)); + cgn->desc_tag =3D cpu_to_be32(ELS_DTAG_CG_SIGNAL_CAP); + cgn->desc_len =3D + cpu_to_be32(FC_TLV_DESC_LENGTH_FROM_SZ(*cgn)); + cgn->xmt_signal_capability =3D + cpu_to_be32(EDC_CG_SIG_NOTSUPPORTED); + cgn->xmt_signal_frequency.count =3D + cpu_to_be16(EDC_CG_SIGFREQ_CNT_MIN); + cgn->xmt_signal_frequency.units =3D + cpu_to_be16(EDC_CG_SIGFREQ_MSEC); + } + + cmdiocb->cmd_dmabuf =3D 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[] =3D { + KUNIT_CASE(lpfc_edc_control_test), + KUNIT_CASE(lpfc_edc_oob_test), + {} +}; + +static struct kunit_suite lpfc_edc_test_suite =3D { + .name =3D "lpfc_edc", + .test_cases =3D lpfc_edc_test_cases, +}; +kunit_test_suite(lpfc_edc_test_suite); +#endif /* CONFIG_LPFC_EDC_KUNIT_TEST */