Linux-NVME Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Guixin Liu" <kanie@linux.alibaba.com>
Cc: linux-nvme@lists.infradead.org
Subject: Re: [PATCH 2/6] nvme-fc: fix iterator over rport->ctrl_list in nvme_fc_match_disconn_ls()
Date: Fri, 06 Nov 2026 02:06:20 +0000	[thread overview]
Message-ID: <sashiko-outbox-200574@kernel.org> (raw)
In-Reply-To: <20261106015842.3534898-3-kanie@linux.alibaba.com>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Critical] nvme-fc: use-after-free in nvme_fc_match_disconn_ls() after nvme_fc_ctrl_put()
--

commit 8782ae8cb9a0539907c2a9d660e71e6ada06052f
Author: Guixin Liu <kanie@linux.alibaba.com>

nvme-fc: fix iterator over rport->ctrl_list in nvme_fc_match_disconn_ls()

This commit switches the rport->ctrl_list traversal in
nvme_fc_match_disconn_ls() from list_for_each_entry_safe() to
list_for_each_entry() to avoid caching a next entry that could be freed while
rport->lock is dropped.

> diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c
> index 0b9ff50d26ff3..edf192055618c 100644
> --- a/drivers/nvme/host/fc.c
> +++ b/drivers/nvme/host/fc.c
> @@ -1470,14 +1470,14 @@ nvme_fc_match_disconn_ls(struct nvme_fc_rport *rport,
>  {
>  	struct fcnvme_ls_disconnect_assoc_rqst *rqst =
>  					&lsop->rqstbuf->rq_dis_assoc;
> -	struct nvme_fc_ctrl *ctrl, *tmp, *ret = NULL;
> +	struct nvme_fc_ctrl *ctrl, *ret = NULL;
>  	struct nvmefc_ls_rcv_op *oldls = NULL;
>  	u64 association_id = be64_to_cpu(rqst->associd.association_id);
>  	unsigned long flags;
>  
>  	spin_lock_irqsave(&rport->lock, flags);
>  
> -	list_for_each_entry_safe(ctrl, tmp, &rport->ctrl_list, ctrl_list) {
> +	list_for_each_entry(ctrl, &rport->ctrl_list, ctrl_list) {
>  		if (!nvme_fc_ctrl_get(ctrl))
>  			continue;
>  		spin_lock(&ctrl->lock);

[Severity: Critical]
Does switching to list_for_each_entry() in nvme_fc_match_disconn_ls() in
drivers/nvme/host/fc.c still leave a use-after-free on ctrl itself when
nvme_fc_handle_ls_rqst_work() -> nvme_fc_ls_disconnect_assoc() ->
nvme_fc_match_disconn_ls() iterates past a non-matching controller that is
concurrently being torn down?

At the end of each non-matching iteration in nvme_fc_match_disconn_ls(), the
loop drops rport->lock and releases the reference on ctrl before the loop step
runs:

	list_for_each_entry(ctrl, &rport->ctrl_list, ctrl_list) {
		if (!nvme_fc_ctrl_get(ctrl))
			continue;
		...
		if (ret)
			/* leave the ctrl get reference */
			break;
		spin_unlock_irqrestore(&rport->lock, flags);
		nvme_fc_ctrl_put(ctrl);
		spin_lock_irqsave(&rport->lock, flags);
	}

Because list_for_each_entry() evaluates ctrl = list_next_entry(ctrl,
ctrl_list) after nvme_fc_ctrl_put(ctrl) and after rport->lock was dropped and
re-acquired, ctrl is no longer pinned when ctrl->ctrl_list.next is read. If
nvme_fc_ctrl_put(ctrl) (or a concurrent nvme_fc_free_ctrl() while rport->lock
is dropped) drops ctrl->ref to zero, nvme_fc_ctrl_free() unlinks and frees
ctrl:

	spin_lock_irqsave(&ctrl->rport->lock, flags);
	owns_opts = !list_empty(&ctrl->ctrl_list);
	list_del(&ctrl->ctrl_list);
	spin_unlock_irqrestore(&ctrl->rport->lock, flags);
	...
	kfree(ctrl);

When the loop step then reads ctrl->ctrl_list.next, it reads from the freed
ctrl struct and follows LIST_POISON1 into the next iteration (or loops
forever if a concurrent nvme_fc_init_ctrl() error path ran
list_del_init(&ctrl->ctrl_list)).

Since rport->lock already serializes against list_del() in
nvme_fc_ctrl_free() and list_del_init() in nvme_fc_init_ctrl(), could
nvme_fc_match_disconn_ls() avoid dropping rport->lock in the loop altogether
by checking association_id == ctrl->association_id first and only calling
nvme_fc_ctrl_get(ctrl) when a matching controller is found?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261106015842.3534898-1-kanie@linux.alibaba.com?part=2


  reply	other threads:[~2026-11-06  2:06 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-06  1:58 [PATCH 0/6] nvme: fabrics and target fixes Guixin Liu
2026-11-06  1:58 ` [PATCH 1/6] nvme: reject a reconnect_delay of 0 through sysfs Guixin Liu
2026-11-06  2:09   ` sashiko-bot
2026-11-06  7:39   ` Hannes Reinecke
2026-11-06 10:33   ` Christoph Hellwig
2026-11-06 13:32   ` Nilay Shroff
2026-11-06  1:58 ` [PATCH 2/6] nvme-fc: fix iterator over rport->ctrl_list in nvme_fc_match_disconn_ls() Guixin Liu
2026-11-06  2:06   ` sashiko-bot [this message]
2026-11-06  7:38   ` Hannes Reinecke
2026-11-06 10:49     ` Guixin Liu
2026-11-06  1:58 ` [PATCH 3/6] nvme-auth: fix data race on ctrl->transaction Guixin Liu
2026-11-06  7:27   ` Hannes Reinecke
2026-11-06  9:28     ` Guixin Liu
2026-11-06  1:58 ` [PATCH 4/6] nvmet: take subsys->lock in nvmet_subsys_attr_tbkas_store() Guixin Liu
2026-11-06  7:27   ` Hannes Reinecke
2026-11-06 10:34   ` Christoph Hellwig
2026-11-06 13:32   ` Nilay Shroff
2026-11-06  1:58 ` [PATCH 5/6] nvmet: fix controller reference leak in nvmet_install_queue() error paths Guixin Liu
2026-11-06  7:31   ` Hannes Reinecke
2026-11-06  9:29     ` Guixin Liu
2026-11-06  1:58 ` [PATCH 6/6] nvmet: use GFP_KERNEL for PR allocations Guixin Liu
2026-11-06  7:31   ` Hannes Reinecke
2026-11-06 10:35   ` Christoph Hellwig
2026-11-06 13:35   ` Nilay Shroff

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=sashiko-outbox-200574@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=kanie@linux.alibaba.com \
    --cc=linux-nvme@lists.infradead.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox