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
next prev parent 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