From: Binbin Deng <18983559317@163.com>
To: sam@mendozajonas.com, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com
Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
Binbin Deng <18983559317@163.com>
Subject: [PATCH net v1] ncsi: Fix use-after-free in the device unregister path
Date: Fri, 9 Oct 2026 21:20:21 +0800 [thread overview]
Message-ID: <20261009132021.39611-1-18983559317@163.com> (raw)
ncsi_unregister_dev() tears the NCSI device down in this order:
dev_remove_pack(&ndp->ptype);
list_for_each_entry_safe(np, tmp, &ndp->packages, node)
ncsi_remove_package(np);
...
disable_work_sync(&ndp->work);
kfree(ndp);
ncsi_remove_package() and ncsi_remove_channel() remove the objects
with list_del_rcu() and free them with an immediate kfree(). Two
concurrent users are not covered by this sequence:
1. The NCSI state machine work (ndp->work) iterates the package and
channel lists (NCSI_FOR_EACH_PACKAGE/NCSI_FOR_EACH_CHANNEL, which
are list_for_each_entry_rcu) while configuring channels, holding
neither ndp->lock nor np->lock across the iteration.
disable_work_sync() runs only after all packages have been freed,
so it does not prevent the work from walking the lists over freed
objects.
2. RCU readers of the published lists. list_del_rcu() removes the
entry for subsequent readers, but the following bare kfree() is
not covered by any grace period, so a reader that has already
obtained the node pointer (e.g. a list_for_each_entry_rcu
iteration in flight) dereferences freed memory when it resumes.
The ordering is reachable on BMC systems: ftgmac100_remove() calls
ncsi_unregister_dev() before unregister_netdev(), i.e. before
ncsi_stop_dev() has stopped the state machine, so the work is still
active while the packages are freed. Device removal concurrent with
the NCSI configuration cycle or a netlink query triggers the race.
Fix this in two parts:
- stop the state machine work before freeing the packages and
channels instead of after;
- free the package and channel objects with kfree_rcu() so that
readers covered by an RCU read-side critical section do not
access freed memory.
Fixes: e6f44ed6d04d ("net/ncsi: Package and channel management")
Signed-off-by: Binbin Deng <18983559317@163.com>
---
net/ncsi/internal.h | 2 ++
net/ncsi/ncsi-manage.c | 8 ++++----
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index 2c9d1f22c16a..461469cc2600 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -239,6 +239,7 @@ struct ncsi_channel {
} monitor;
struct list_head node;
struct list_head link;
+ struct rcu_head rcu_head;
};
struct ncsi_package {
@@ -253,6 +254,7 @@ struct ncsi_package {
bool multi_channel; /* Enable multiple channels */
u32 channel_whitelist; /* Channels to configure */
struct ncsi_channel *preferred_channel; /* Primary channel */
+ struct rcu_head rcu_head;
};
struct ncsi_request {
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 1d63958c4429..39ac7075cd1b 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -263,7 +263,7 @@ static void ncsi_remove_channel(struct ncsi_channel *nc)
np->channel_num--;
spin_unlock_irqrestore(&np->lock, flags);
- kfree(nc);
+ kfree_rcu(nc, rcu_head);
}
struct ncsi_package *ncsi_find_package(struct ncsi_dev_priv *ndp,
@@ -326,7 +326,7 @@ void ncsi_remove_package(struct ncsi_package *np)
ndp->package_num--;
spin_unlock_irqrestore(&ndp->lock, flags);
- kfree(np);
+ kfree_rcu(np, rcu_head);
}
void ncsi_find_package_and_channel(struct ncsi_dev_priv *ndp,
@@ -1958,6 +1958,8 @@ void ncsi_unregister_dev(struct ncsi_dev *nd)
struct ncsi_package *np, *tmp;
unsigned long flags;
+ disable_work_sync(&ndp->work);
+
dev_remove_pack(&ndp->ptype);
list_for_each_entry_safe(np, tmp, &ndp->packages, node)
@@ -1967,8 +1969,6 @@ void ncsi_unregister_dev(struct ncsi_dev *nd)
list_del_rcu(&ndp->node);
spin_unlock_irqrestore(&ncsi_dev_lock, flags);
- disable_work_sync(&ndp->work);
-
kfree(ndp);
}
EXPORT_SYMBOL_GPL(ncsi_unregister_dev);
--
2.43.0
next reply other threads:[~2026-10-09 13:21 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 13:20 Binbin Deng [this message]
2026-10-09 13:24 ` [PATCH net v1] ncsi: Fix use-after-free in the device unregister path netdev-bot+sinfo
2026-10-10 14:06 ` netdev-bot+sashiko
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=20261009132021.39611-1-18983559317@163.com \
--to=18983559317@163.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=sam@mendozajonas.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox