All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jesse Taube" <jtaubepe@redhat.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH 01/13] fc_els: use 'union fc_tlv_desc'
Date: Wed, 12 Aug 2026 18:26:16 +0000	[thread overview]
Message-ID: <20260812182616.C20A51F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260812181300.3712426-2-jtaubepe@redhat.com>

Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:

New issues:
- [High] ABI and Wire Protocol Breakage: `union fc_tlv_desc` introduces 8-byte alignment, inserting 4-byte padding before `desc[]` in ELS response structures.
- [High] Build Failure: Flexible array members nested inside a union and declared as an array violate the C standard.
- [High] UAPI Source Breakage: Redefining `struct fc_tlv_desc` as `union fc_tlv_desc` breaks userspace compilation.
- [High] Undefined Behavior: Casting unaligned network offsets to a union requiring 8-byte alignment crashes strict-alignment architectures.

Pre-existing issues:
- [High] Undefined Behavior: Overlapping memory regions in `memcpy` during descriptor shifting.
- [High] Race Condition / Use-After-Free: `fc_find_rport_by_wwpn()` returns an rport pointer without acquiring a reference.
- [High] Out-of-Bounds Read: Signed integer underflow in `bytes_remain` logic bypasses length validation.
- [High] Out-of-Bounds Read: Missing minimum payload length validation prior to parsing specific descriptors.
--

--- Patch [1]: [PATCH 01/13] fc_els: use 'union fc_tlv_desc' ---
commit 96c48d7bf5ab3d34f4f3bb76d985ca1b29c2c877
Author: Hannes Reinecke <hare@kernel.org>
Subject: fc_els: use 'union fc_tlv_desc'

This commit introduces union fc_tlv_desc to provide a common structure for
all FC ELS TLV structures, helping to avoid type casts when managing these
descriptors.

> diff --git a/include/uapi/scsi/fc/fc_els.h b/include/uapi/scsi/fc/fc_els.h
> --- a/include/uapi/scsi/fc/fc_els.h
> +++ b/include/uapi/scsi/fc/fc_els.h
> @@ -259,12 +259,12 @@ enum fc_ls_tlv_dtag {
[ ... ]
> +union fc_tlv_desc {
> +	struct fc_tlv_desc_hdr hdr;
> +	struct fc_els_lsri_desc lsri;
> +	struct fc_fn_li_desc li;
> +	struct fc_fn_deli_desc deli;
> +	struct fc_fn_peer_congn_desc peer_congn;
> +	struct fc_fn_congn_desc congn;
> +	struct fc_df_desc_fpin_reg fpin_reg;
> +	struct fc_diag_lnkflt_desc lnkflt;
> +	struct fc_diag_cg_sig_desc cg_sig;
> +};

[Severity: High]
Does changing struct fc_tlv_desc into a union break UAPI source
compatibility? Userspace applications that were previously compiling with
struct fc_tlv_desc will now fail to compile against these headers.

[ ... ]
> +static inline union fc_tlv_desc *fc_tlv_next_desc(union fc_tlv_desc *desc)
> +{
> +	return (union fc_tlv_desc *)((__u8 *)desc + FC_TLV_DESC_SZ_FROM_LENGTH(desc));
> +}

[Severity: High]
Can this cast lead to unaligned access panics on strict-alignment
architectures? The pointer math calculates an offset that is only guaranteed
to be 4-byte aligned, but it is then cast to union fc_tlv_desc. Because this
union contains 64-bit fields, the compiler expects 8-byte alignment, which
might trigger undefined behavior when dereferenced later in paths like
lpfc_els_rcv_edc().

[ ... ]
>  struct fc_els_fpin {
>  	__u8		fpin_cmd;	/* command (0x16) */
>  	__u8		fpin_zero[3];	/* specified as zero - part of cmd */
>  	__be32		desc_len;	/* Length of Descriptor List (in bytes).
>  					 * Size of ELS excluding fpin_cmd,
>  					 * fpin_zero and desc_len fields.
>  					 */
> -	struct fc_tlv_desc	fpin_desc[];	/* Descriptor list */
> +	union fc_tlv_desc	fpin_desc[];	/* Descriptor list */
>  };

[Severity: High]
Will this build successfully on standard C compilers? The C standard forbids
unions containing flexible array members from being elements of an array.
Nesting flexible array members inside the union fc_tlv_desc and then
declaring an array of that union might trigger a build constraint violation.

[ ... ]
>  struct fc_els_rdf_resp {
>  	struct fc_els_ls_acc	acc_hdr;
>  	__be32			desc_list_len;	/* Length of response (in
>  						 * bytes). Excludes acc_hdr
>  						 * and desc_list_len fields.
>  						 */
>  	struct fc_els_lsri_desc	lsri;
> -	struct fc_tlv_desc	desc[];	/* Supported Descriptor list */
> +	union fc_tlv_desc	desc[];	/* Supported Descriptor list */
>  };

[Severity: High]
Does this structure layout change break the wire protocol? By introducing
union fc_tlv_desc containing 64-bit members, the union adopts an 8-byte
alignment requirement. Because fc_els_lsri_desc ends at a 4-byte aligned
boundary, the compiler will silently insert 4 bytes of padding before the
desc array. This could corrupt the network payload offsets in ELS responses.
This same padding issue applies to the modified fc_els_edc_resp structure.

> diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
> --- a/drivers/scsi/lpfc/lpfc_els.c
> +++ b/drivers/scsi/lpfc/lpfc_els.c
[ ... ]
> @@ -9482,7 +9478,7 @@ lpfc_els_rcv_edc(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
>  			goto out;
>  		}
>  
> -		dtag = be32_to_cpu(tlv->desc_tag);
> +		dtag = be32_to_cpu(tlv->hdr.desc_tag);

[Severity: High]
This isn't a bug introduced by this patch, but does the bytes_remain loop
logic properly handle underflows? If a malicious or malformed payload causes
bytes_remain to become negative, it might bypass the length check in the while
loop because the negative value could be implicitly cast to size_t when
compared against FC_TLV_DESC_HDR_SZ, resulting in out-of-bounds kernel memory
reads.

[ ... ]
> @@ -10374,22 +10367,22 @@ lpfc_els_rcv_fpin(struct lpfc_vport *vport, void *p, u32 fpin_length)
>  	/* process each descriptor separately */
>  	while (bytes_remain >= FC_TLV_DESC_HDR_SZ &&
>  	       bytes_remain >= FC_TLV_DESC_SZ_FROM_LENGTH(tlv)) {
> -		dtag = be32_to_cpu(tlv->desc_tag);
> +		dtag = be32_to_cpu(tlv->hdr.desc_tag);
>  		switch (dtag) {
>  		case ELS_DTAG_LNK_INTEGRITY:
> -			lpfc_els_rcv_fpin_li(phba, tlv);
> +			lpfc_els_rcv_fpin_li(phba, &tlv->li);

[Severity: High]
This is a pre-existing issue, but does this parsing code ensure the TLV
payload is large enough before casting and accessing the specific structure?
The loop validates the TLV header length, but immediately dispatches to
parsing routines like lpfc_els_rcv_fpin_li which map the payload to larger
structures. This missing minimum payload length validation might lead to
reading out of bounds during structural extraction.

[ ... ]
>  		/* Sanity check descriptor length. The desc_len value does not
>  		 * include space for the desc_tag and the desc_len fields.
>  		 */
> -		len -= (cnt + sizeof(struct fc_tlv_desc));
> +		len -= (cnt + sizeof(struct fc_tlv_desc_hdr));
>  		if (len < 0) {

[Severity: High]
This is a pre-existing issue, but could the memcpy further down in this
routine cause undefined behavior?

If desc_cnt is true, the code calls:
    memcpy(first_tlv, current_tlv, (cnt + sizeof(struct fc_els_fpin)));

The source and destination memory regions for the descriptors overlap here
since they are being shifted in-place within the same buffer. This should
probably use memmove instead.

> diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
> --- a/drivers/scsi/scsi_transport_fc.c
> +++ b/drivers/scsi/scsi_transport_fc.c
> @@ -776,12 +776,11 @@ fc_fpin_pname_stats_update(struct Scsi_Host *shost,
>   *
>   */
>  static void
> -fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv)
> +fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_fn_li_desc *li_desc)
>  {
>  	struct fc_rport *rport = NULL;
>  	struct fc_rport *attach_rport = NULL;
>  	struct fc_host_attrs *fc_host = shost_to_fc_host(shost);
> -	struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv;
>  	u16 event_type = be16_to_cpu(li_desc->event_type);
>  
>  	rport = fc_find_rport_by_wwpn(shost,
>  				      be64_to_cpu(li_desc->attached_wwpn));
>  	if (rport &&

[Severity: High]
This isn't a bug introduced by this patch, but does fc_find_rport_by_wwpn()
safely manage the returned pointer? 

It appears to return an rport pointer without acquiring a reference. Since it
drops the host_lock before returning:

    if (rport->port_name == wwpn) {
        spin_unlock_irqrestore(shost->host_lock, flags);
        return rport;
    }

Concurrent destruction pathways could potentially free the structure while
it is being used here in fc_fpin_li_stats_update(), leading to a
use-after-free condition.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260812181300.3712426-1-jtaubepe@redhat.com?part=1

  reply	other threads:[~2026-08-12 18:26 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-12 18:12 [PATCH 00/13] nvme-fc: FPIN link integrity handling Jesse Taube
2026-08-12 18:12 ` [PATCH 01/13] fc_els: use 'union fc_tlv_desc' Jesse Taube
2026-08-12 18:26   ` sashiko-bot [this message]
2026-08-12 18:12 ` [PATCH 02/13] nvme: add NVME_CTRL_MARGINAL flag Jesse Taube
2026-08-12 18:21   ` sashiko-bot
2026-08-12 18:12 ` [PATCH 03/13] nvme-multipath: numa support for marginal paths Jesse Taube
2026-08-12 18:29   ` sashiko-bot
2026-08-12 18:12 ` [PATCH 04/13] nvme-multipath: queue-depth " Jesse Taube
2026-08-12 18:12 ` [PATCH 05/13] nvme-multipath: round-robin " Jesse Taube
2026-08-12 18:26   ` sashiko-bot
2026-08-12 18:12 ` [PATCH 06/13] nvme: sysfs: emit the marginal path state in show_state() Jesse Taube
2026-08-12 18:21   ` sashiko-bot
2026-08-12 18:12 ` [PATCH 07/13] scsi: scsi_transport_fc: Add set_rport_marginal to fc_function_template Jesse Taube
2026-08-12 18:28   ` sashiko-bot
2026-08-12 18:12 ` [PATCH 08/13] scsi: scsi_transport_fc: user support for clearing NVME_CTRL_MARGINAL Jesse Taube
2026-08-12 18:24   ` sashiko-bot
2026-08-12 18:12 ` [PATCH 09/13] nvme-fc: add nvme_fc_set_remoteport_fpin() Jesse Taube
2026-08-12 18:27   ` sashiko-bot
2026-08-12 18:12 ` [PATCH 10/13] scsi: qla2xxx: enable FPIN notification for NVMe Jesse Taube
2026-08-12 18:34   ` sashiko-bot
2026-08-12 19:38     ` Jesse Taube
2026-08-12 18:12 ` [PATCH 11/13] scsi: lpfc: " Jesse Taube
2026-08-12 18:35   ` sashiko-bot
2026-08-12 18:12 ` [PATCH 12/13] nvme: fcloop: Add set_rport_marginal to sysfs Jesse Taube
2026-08-12 18:31   ` sashiko-bot
2026-08-12 18:34   ` Jesse Taube
2026-08-12 18:13 ` [PATCH 13/13] docs: nvme-multipath: Add FC-NVMe marginal state Jesse Taube
2026-08-12 18:26   ` sashiko-bot
2026-08-12 18:46   ` Randy Dunlap
2026-08-12 18:50     ` Randy Dunlap

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=20260812182616.C20A51F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=jtaubepe@redhat.com \
    --cc=linux-scsi@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.