All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Tyrel Datwyler" <tyreld@linux.ibm.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH v2 10/33] ibmvfc: add logic for protocol specific fabric logins
Date: Thu, 23 Jul 2026 00:28:57 +0000	[thread overview]
Message-ID: <20260723002857.BB7FA1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260723000149.969416-11-tyreld@linux.ibm.com>

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

New issues:
- [High] The host initialization state machine permanently stalls if NPIV login completes while `vhost->do_enquiry` is false.
- [High] NVMe fabric login is entirely skipped if the VIOS advertises NVMe support but not SCSI support, or if SCSI fabric login is disabled.
- [High] Concurrent transmission of SCSI and NVMe discovery MADs causes state machine transitions to be lost, resulting in dropped targets.
- [High] If NVMe is disabled by the guest but supported by the VIOS, `ibmvfc_channel_setup()` unconditionally dereferences a NULL `nvme->scrqs` pointer.
- [Medium] Unintended switch fallthrough in `ibmvfc_fabric_login_scsi_done` default case sends NVMe MAD on a dead link.

Pre-existing issues:
- [High] Missing validation of hypervisor-provided `active_queues` in `ibmvfc_channel_setup_done` leads to out-of-bounds heap writes.
- [High] Integer overflow of `max_cmds` when calculating queue depths for NPIV login.
--

--- Patch [10]: [PATCH v2 10/33] ibmvfc: add logic for protocol specific fabric logins ---
commit bffd16f5906104e27c687d661ecee756b7747318
Author: Tyrel Datwyler <tyreld@linux.ibm.com>

    ibmvfc: add logic for protocol specific fabric logins

    Add support for the protocol-specific fabric login flow introduced by
    the updated client/VIOS interface. Track whether SCSI and NVMe/FC fabric
    login are needed, extend channel enquiry/setup handling to negotiate both
    SCSI and NVMe queue counts, and issue the appropriate fabric login MADs
    before target discovery begins.

> diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ibmvfc-core.c
> index d8c2b56258eeb..e0edd71e9fd4b 100644
> --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
> +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c

[ ... ]

> @@ -1512,7 +1520,7 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
>  	max_cmds = scsi_qdepth + IBMVFC_NUM_INTERNAL_REQ;
>  	if (mq_enabled)
>  		max_cmds += (scsi_qdepth + IBMVFC_NUM_INTERNAL_SUBQ_REQ) *
> -			vhost->scsi_scrqs.desired_queues;
> +			(vhost->scsi_scrqs.desired_queues + vhost->nvme_scrqs.desired_queues);

[Severity: High]
This isn't a bug introduced by this patch, but does calculating the queue
depth this way risk an integer overflow?

In ibmvfc_set_login_info(), max_cmds is declared as a 16-bit unsigned integer
(u16). If large values are configured for module parameters like scsi_qdepth,
this calculation could silently exceed 65,535 and wrap around.

Could this overflow submit a corrupted max_cmds limit to the VIOS?

[ ... ]

> +static void ibmvfc_fabric_login_scsi_done(struct ibmvfc_event *evt)
> +{
> +	struct ibmvfc_host *vhost = evt->vhost;
> +	struct ibmvfc_fabric_login_mad *rsp = &evt->xfer_iu->fabric_login;
> +	u32 mad_status = be16_to_cpu(rsp->common.status);
> +	int level = IBMVFC_DEFAULT_LOG_LEVEL;
> +
> +	switch (mad_status) {
> +	case IBMVFC_MAD_SUCCESS:
> +		ibmvfc_dbg(vhost, "SCSI fabric login succeeded\n");
> +		break;
> +	case IBMVFC_MAD_FAILED:

[ ... ]

> +	case IBMVFC_MAD_DRIVER_FAILED:
> +		ibmvfc_free_event(evt);
> +		return;
> +	default:
> +		dev_err(vhost->dev, "Invalid SCSI fabric login response: 0x%x\n", mad_status);
> +		ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
> +		break;
> +	}
> +
> +	ibmvfc_free_event(evt);
> +
> +	if (vhost->do_nvme_login) {
> +		ibmvfc_fabric_login_nvme(vhost);

[Severity: Medium]
Does the break statement in the default case above cause an unintended switch
fallthrough?

If SCSI fabric login fails with an unrecognized status, the default case calls
ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD). However, unlike the other error
cases which return, it breaks out of the switch.

Will this cause execution to fall through and improperly invoke
ibmvfc_fabric_login_nvme() on a dead link?

> +	} else {
> +		ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
> +		wake_up(&vhost->work_wait_q);
> +	}
> +}

[ ... ]

> @@ -5068,22 +5211,28 @@ static void ibmvfc_channel_setup_done(struct ibmvfc_event *evt)
>  		ibmvfc_dbg(vhost, "Channel Setup succeeded\n");
>  		flags = be32_to_cpu(setup->flags);
>  		vhost->do_enquiry = 0;
> -		active_queues = be32_to_cpu(setup->num_scsi_subq_channels);
> -		scrqs->active_queues = active_queues;
> +		scsi->active_queues = be32_to_cpu(setup->num_scsi_subq_channels);
> +		nvme->active_queues = be32_to_cpu(setup->num_nvme_subq_channels);

[Severity: High]
This is a pre-existing issue, but are these hypervisor-provided counts
validated against the array bounds?

The counts are taken directly from the untrusted 32-bit values returned by
the VIOS.

If the VIOS returns values larger than the dynamically allocated array sizes
(max_queues), will the subsequent loops that initialize vios_cookie corrupt
the guest kernel heap by writing out-of-bounds?

>  
>  		if (flags & IBMVFC_CHANNELS_CANCELED) {
>  			ibmvfc_dbg(vhost, "Channels Canceled\n");
>  			vhost->using_channels = 0;
> -		} else {
> -			if (active_queues)
> -				vhost->using_channels = 1;
> -			for (i = 0; i < active_queues; i++)
> -				scrqs->scrqs[i].vios_cookie =
> -					be64_to_cpu(setup->channel_handles[i]);
> -
> -			ibmvfc_dbg(vhost, "Using %u channels\n",
> -				   vhost->scsi_scrqs.active_queues);
> +			break;
>  		}
> +
> +		if (scsi->active_queues || nvme->active_queues)
> +			vhost->using_channels = 1;
> +		for (i = 0; i < scsi->active_queues; i++)
> +			scsi->scrqs[i].vios_cookie =
> +				be64_to_cpu(setup->channel_handles[i]);
> +		for (i = 0; i < nvme->active_queues; i++)
> +			nvme->scrqs[i].vios_cookie =
> +				be64_to_cpu(setup->channel_handles[scsi->active_queues + i]);

[ ... ]

> @@ -5098,8 +5247,12 @@ static void ibmvfc_channel_setup_done(struct ibmvfc_event *evt)
>  		return;
>  	}
>  
> -	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
> -	wake_up(&vhost->work_wait_q);
> +	if (vhost->do_scsi_login) {
> +		ibmvfc_fabric_login_scsi(vhost);
> +	} else {
> +		ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
> +		wake_up(&vhost->work_wait_q);
> +	}
>  }

[Severity: High]
Does this bypass NVMe fabric login if SCSI fabric login is disabled?

If vhost->do_scsi_login is false, the code immediately transitions the host
state to IBMVFC_HOST_ACTION_QUERY.

Since NVMe login is sequentially chained from the SCSI login completion
callback (ibmvfc_fabric_login_scsi_done), if the VIOS advertises NVMe support
but not SCSI support, will NVMe initialization fail because it is entirely
skipped?

>  
>  static void ibmvfc_channel_setup(struct ibmvfc_host *vhost)
> @@ -5120,12 +5276,17 @@ static void ibmvfc_channel_setup(struct ibmvfc_host *vhost)
>  	}
>  
>  	memset(setup_buf, 0, sizeof(*setup_buf));
> -	if (num_channels == 0)
> +	if (!scsi_channels && !nvme_channels)
>  		setup_buf->flags = cpu_to_be32(IBMVFC_CANCEL_CHANNELS);
>  	else {
> -		setup_buf->num_scsi_subq_channels = cpu_to_be32(num_channels);
> -		for (i = 0; i < num_channels; i++)
> -			setup_buf->channel_handles[i] = cpu_to_be64(scrqs->scrqs[i].cookie);
> +		setup_buf->num_scsi_subq_channels = cpu_to_be32(scsi_channels);
> +		setup_buf->num_nvme_subq_channels = cpu_to_be32(nvme_channels);
> +		for (i = 0; i < scsi_channels; i++)
> +			setup_buf->channel_handles[i] =
> +				cpu_to_be64(scsi->scrqs[i].cookie);
> +		for (i = 0; i < nvme_channels; i++)
> +			setup_buf->channel_handles[scsi_channels + i] =
> +				cpu_to_be64(nvme->scrqs[i].cookie);

[Severity: High]
Can nvme->scrqs be a NULL pointer here?

If the guest disables NVMe (e.g., via module parameter),
ibmvfc_alloc_channels() for NVMe is skipped, leaving nvme->scrqs as NULL.

When ibmvfc_channel_enquiry_done() executes, if the VIOS reports
num_nvme_subq_channels > 0, nvme_channels calculates to > 0.

Will the loop above then unconditionally dereference the NULL nvme->scrqs
pointer?

>  	}
>  
>  	ibmvfc_init_event(evt, ibmvfc_channel_setup_done, IBMVFC_MAD_FORMAT);

[ ... ]

> @@ -5290,8 +5452,14 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
>  	vhost->host->can_queue = be32_to_cpu(rsp->max_cmds) - IBMVFC_NUM_INTERNAL_REQ;
>  	vhost->host->max_sectors = npiv_max_sectors;
>  
> -	if (ibmvfc_check_caps(vhost, IBMVFC_CAN_SUPPORT_CHANNELS) && vhost->do_enquiry) {
> -		ibmvfc_channel_enquiry(vhost);
> +
> +	if (ibmvfc_check_caps(vhost, IBMVFC_CAN_SUPPORT_CHANNELS)) {
> +		if (ibmvfc_check_caps(vhost, IBMVFC_SUPPORT_SCSI))
> +			vhost->do_scsi_login = 1;
> +		if (ibmvfc_check_caps(vhost, IBMVFC_SUPPORT_NVMEOF))
> +			vhost->do_nvme_login = 1;
> +		if (vhost->do_enquiry)
> +			ibmvfc_channel_enquiry(vhost);
>  	} else {
>  		vhost->do_enquiry = 0;
>  		ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);

[Severity: High]
Does removing the else block here cause the host initialization state machine
to stall if vhost->do_enquiry is false?

If sub-CRQ channel allocation fails, do_enquiry is set to 0. When NPIV login
subsequently completes, this block skips ibmvfc_channel_enquiry().

Since there is no fallback to transition the state to IBMVFC_HOST_ACTION_QUERY
when do_enquiry is false, does this cause the state machine to permanently
stall?

[Severity: High]
One additional question about target discovery behavior in
ibmvfc_discover_targets():

When both SCSI and NVMe target discovery are active, both discovery MADs
are sent concurrently:

	if (!ibmvfc_send_event(evt, vhost, default_timeout))
		ibmvfc_dbg(vhost, "Sent discover SCSI targets\n");
    ...
	if (!ibmvfc_send_event(evt, vhost, default_timeout))
		ibmvfc_dbg(vhost, "Sent discover NVMe targets\n");

However, when each completes, they both call ibmvfc_discover_targets_done(),
which attempts to advance the shared state machine:

	ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS);

Will the second completion be ignored because the host action is no longer
IBMVFC_HOST_ACTION_INIT_WAIT, causing one protocol's discovered targets to be
silently dropped and never allocated?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260723000149.969416-1-tyreld@linux.ibm.com?part=10

  reply	other threads:[~2026-07-23  0:28 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-23  0:01 [PATCH v2 00/33] ibmvfc: NVMe/FC support over IBM Virtual FC Tyrel Datwyler
2026-07-23  0:01 ` [PATCH v2 01/33] ibmvfc: don't call locked done variant for MADs on send failure Tyrel Datwyler
2026-07-23  0:42   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 02/33] ibmvfc: flush rport_add_work_q during driver teardown Tyrel Datwyler
2026-07-23  0:35   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 03/33] ibmvfc: check for NULL evt in implicit LOGO and target delete path Tyrel Datwyler
2026-07-23  0:30   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 04/33] ibmvfc: free ibmvfc_target allocations with mempool_free Tyrel Datwyler
2026-07-23  0:01 ` [PATCH v2 05/33] ibmvfc: move target list from host to protocol specific channel groups Tyrel Datwyler
2026-07-23  0:34   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 06/33] ibmvfc: add NVMe/FC protocol interface definitions Tyrel Datwyler
2026-07-23  0:28   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 07/33] ibmvfc: split NVMe support into separate source file and add transport stubs Tyrel Datwyler
2026-07-23  0:22   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 08/33] ibmvfc: initialize NVMe channel configuration during driver probe Tyrel Datwyler
2026-07-23  0:21   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 09/33] ibmvfc: alloc/dealloc sub-queues for nvme channels Tyrel Datwyler
2026-07-23  0:33   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 10/33] ibmvfc: add logic for protocol specific fabric logins Tyrel Datwyler
2026-07-23  0:28   ` sashiko-bot [this message]
2026-07-23  0:01 ` [PATCH v2 11/33] ibmvfc: add wrapper to get vhost associated with a channel struct Tyrel Datwyler
2026-07-23  0:01 ` [PATCH v2 12/33] ibmvfc: add helper for creating protocol specific discovery event Tyrel Datwyler
2026-07-23  0:01 ` [PATCH v2 13/33] ibmvfc: add helper to check NVMe/FC support with active channels Tyrel Datwyler
2026-07-23  0:17   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 14/33] ibmvfc: allocate and free NVMe channel group discover buffer Tyrel Datwyler
2026-07-23  0:01 ` [PATCH v2 15/33] ibmvfc: send NVMe target discovery MAD Tyrel Datwyler
2026-07-23  0:31   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 16/33] ibmvfc: add NVMe/FC Implicit Logout and Move Login support Tyrel Datwyler
2026-07-23  0:36   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 17/33] ibmvfc: add NVMe/FC Port " Tyrel Datwyler
2026-07-23  0:38   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 18/33] ibmvfc: add NVMe/FC Process " Tyrel Datwyler
2026-07-23  0:39   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 19/33] ibmvfc: add NVMe/FC Query Target support Tyrel Datwyler
2026-07-23  0:50   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 20/33] ibmvfc: allocate targets based on protocol Tyrel Datwyler
2026-07-23  0:43   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 21/33] ibmvfc: delete NVMe/FC targets as well as SCSI Tyrel Datwyler
2026-07-23  0:52   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 22/33] ibmvfc: update state machine to process NVMe/FC targets Tyrel Datwyler
2026-07-23  0:53   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 23/33] ibmvfc: implement NVMe/FC stubs for local/remote port registration Tyrel Datwyler
2026-07-23  0:54   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 24/33] ibmvfc: register local nvme fc port after fabric login Tyrel Datwyler
2026-07-23  0:53   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 25/33] ibmvfc: process NVMe/FC rports in work thread Tyrel Datwyler
2026-07-23  0:50   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 26/33] ibmvfc: extend ibmvfc_debug visibility to ibmvfc-nvme.h Tyrel Datwyler
2026-07-23  0:42   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 27/33] ibmvfc: declare global function definitions Tyrel Datwyler
2026-07-23  0:01 ` [PATCH v2 28/33] ibmvfc: implement LLDD callbacks for mapping nvme-fc queues Tyrel Datwyler
2026-07-23  0:58   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 29/33] ibmvfc: implement nvme-fc LS submission transport callback Tyrel Datwyler
2026-07-23  1:00   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 30/33] ibmvfc: implement nvme-fc IO command submission callback Tyrel Datwyler
2026-07-23  1:08   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 31/33] ibmvfc: implement nvme-fc LS abort handling callback Tyrel Datwyler
2026-07-23  1:05   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 32/33] ibmvfc: implement nvme-fc FCP abort callback Tyrel Datwyler
2026-07-23  1:05   ` sashiko-bot
2026-07-23  0:01 ` [PATCH v2 33/33] ibmvfc: fail nvme-fc fcp-io and ls requests during transport reset Tyrel Datwyler
2026-07-23  0:58   ` sashiko-bot

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=20260723002857.BB7FA1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=tyreld@linux.ibm.com \
    /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.