All of 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 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.