[PATCH net-next] netdev: fix the locking for netdev notifications

11 views
Skip to first unread message

Jakub Kicinski

unread,
Apr 11, 2025, 4:46:35 PM4/11/25
to da...@davemloft.net, net...@vger.kernel.org, edum...@google.com, pab...@redhat.com, andrew...@lunn.ch, ho...@kernel.org, Jakub Kicinski, syzkaller, Kuniyuki Iwashima, s...@fomichev.me, jda...@fastly.com, almas...@google.com
Kuniyuki reports that the assert for netdev lock fires when
there are netdev event listeners (otherwise we skip the netlink
event generation).

Correct the locking when coming from the notifier.

The NETDEV_XDP_FEAT_CHANGE notifier is already fully locked,
it's the documentation that's incorrect.

Fixes: 99e44f39a8f7 ("netdev: depend on netdev->lock for xdp features")
Reported-by: syzkaller <syzk...@googlegroups.com>
Reported-by: Kuniyuki Iwashima <kun...@amazon.com>
Link: https://lore.kernel.org/20250410171019...@amazon.com
Signed-off-by: Jakub Kicinski <ku...@kernel.org>
---
CC: kun...@amazon.com
CC: s...@fomichev.me
CC: jda...@fastly.com
CC: almas...@google.com
---
Documentation/networking/netdevices.rst | 4 +++-
include/linux/netdevice.h | 2 +-
include/net/netdev_lock.h | 12 ++++++++++++
net/core/lock_debug.c | 4 +++-
net/core/netdev-genl.c | 4 ++++
5 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/Documentation/networking/netdevices.rst b/Documentation/networking/netdevices.rst
index 0ccc7dcf4390..feadefe61849 100644
--- a/Documentation/networking/netdevices.rst
+++ b/Documentation/networking/netdevices.rst
@@ -386,11 +386,13 @@ For device drivers that implement shaping or queue management APIs,
some of the notifiers (``enum netdev_cmd``) are running under the netdev
instance lock.

+The following netdev notifiers are always run under the instance lock:
+* ``NETDEV_XDP_FEAT_CHANGE``
+
For devices with locked ops, currently only the following notifiers are
running under the lock:
* ``NETDEV_REGISTER``
* ``NETDEV_UP``
-* ``NETDEV_XDP_FEAT_CHANGE``

The following notifiers are running without the lock:
* ``NETDEV_UNREGISTER``
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index a28a08046615..0976c85932e5 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2526,7 +2526,7 @@ struct net_device {
* @net_shaper_hierarchy, @reg_state, @threaded
*
* Double protects:
- * @up, @moving_ns, @nd_net, @xdp_flags
+ * @up, @moving_ns, @nd_net, @xdp_features
*
* Double ops protects:
* @real_num_rx_queues, @real_num_tx_queues
diff --git a/include/net/netdev_lock.h b/include/net/netdev_lock.h
index 5706835a660c..c63448b17f9e 100644
--- a/include/net/netdev_lock.h
+++ b/include/net/netdev_lock.h
@@ -48,6 +48,18 @@ static inline void netdev_unlock_ops(struct net_device *dev)
netdev_unlock(dev);
}

+static inline void netdev_lock_ops_to_full(struct net_device *dev)
+{
+ if (!netdev_need_ops_lock(dev))
+ netdev_lock(dev);
+}
+
+static inline void netdev_unlock_full_to_ops(struct net_device *dev)
+{
+ if (!netdev_need_ops_lock(dev))
+ netdev_unlock(dev);
+}
+
static inline void netdev_ops_assert_locked(const struct net_device *dev)
{
if (netdev_need_ops_lock(dev))
diff --git a/net/core/lock_debug.c b/net/core/lock_debug.c
index 598c443ef2f3..72d3f5dd610c 100644
--- a/net/core/lock_debug.c
+++ b/net/core/lock_debug.c
@@ -18,9 +18,11 @@ int netdev_debug_event(struct notifier_block *nb, unsigned long event,

/* Keep enum and don't add default to trigger -Werror=switch */
switch (cmd) {
+ case NETDEV_XDP_FEAT_CHANGE:
+ netdev_assert_locked(dev);
+ fallthrough;
case NETDEV_REGISTER:
case NETDEV_UP:
- case NETDEV_XDP_FEAT_CHANGE:
netdev_ops_assert_locked(dev);
fallthrough;
case NETDEV_DOWN:
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index b64c614a00c4..2c104947d224 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -963,10 +963,14 @@ static int netdev_genl_netdevice_event(struct notifier_block *nb,

switch (event) {
case NETDEV_REGISTER:
+ netdev_lock_ops_to_full(netdev);
netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_ADD_NTF);
+ netdev_unlock_full_to_ops(netdev);
break;
case NETDEV_UNREGISTER:
+ netdev_lock(netdev);
netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_DEL_NTF);
+ netdev_unlock(netdev);
break;
case NETDEV_XDP_FEAT_CHANGE:
netdev_genl_dev_notify(netdev, NETDEV_CMD_DEV_CHANGE_NTF);
--
2.49.0

Jakub Kicinski

unread,
Apr 14, 2025, 3:59:09 PM4/14/25
to da...@davemloft.net, net...@vger.kernel.org, edum...@google.com, pab...@redhat.com, andrew...@lunn.ch, ho...@kernel.org, Jakub Kicinski, syzkaller, Kuniyuki Iwashima, s...@fomichev.me, jda...@fastly.com, almas...@google.com
Kuniyuki reports that the assert for netdev lock fires when
there are netdev event listeners (otherwise we skip the netlink
event generation).

Correct the locking when coming from the notifier.

The NETDEV_XDP_FEAT_CHANGE notifier is already fully locked,
it's the documentation that's incorrect.

Fixes: 99e44f39a8f7 ("netdev: depend on netdev->lock for xdp features")
Reported-by: syzkaller <syzk...@googlegroups.com>
Reported-by: Kuniyuki Iwashima <kun...@amazon.com>
Link: https://lore.kernel.org/20250410171019...@amazon.com
Signed-off-by: Jakub Kicinski <ku...@kernel.org>
---
v2:
- rebase vs net merge which brought in
commit 04efcee6ef8d ("net: hold instance lock during NETDEV_CHANGE")
v1: https://lore.kernel.org/20250411204629...@kernel.org

CC: kun...@amazon.com
CC: s...@fomichev.me
CC: jda...@fastly.com
CC: almas...@google.com
---
Documentation/networking/netdevices.rst | 4 +++-
include/linux/netdevice.h | 2 +-
include/net/netdev_lock.h | 12 ++++++++++++
net/core/lock_debug.c | 4 +++-
net/core/netdev-genl.c | 4 ++++
5 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/Documentation/networking/netdevices.rst b/Documentation/networking/netdevices.rst
index f87bb55b4afe..a73a39b206e3 100644
--- a/Documentation/networking/netdevices.rst
+++ b/Documentation/networking/netdevices.rst
@@ -387,12 +387,14 @@ For device drivers that implement shaping or queue management APIs,
some of the notifiers (``enum netdev_cmd``) are running under the netdev
instance lock.

+The following netdev notifiers are always run under the instance lock:
+* ``NETDEV_XDP_FEAT_CHANGE``
+
For devices with locked ops, currently only the following notifiers are
running under the lock:
* ``NETDEV_CHANGE``
* ``NETDEV_REGISTER``
* ``NETDEV_UP``
-* ``NETDEV_XDP_FEAT_CHANGE``

The following notifiers are running without the lock:
* ``NETDEV_UNREGISTER``
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index e6036b82ef4c..0321fd952f70 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2520,7 +2520,7 @@ struct net_device {
index 6fade574bc2a..9e9fb25314b9 100644
--- a/net/core/lock_debug.c
+++ b/net/core/lock_debug.c
@@ -18,10 +18,12 @@ int netdev_debug_event(struct notifier_block *nb, unsigned long event,

/* Keep enum and don't add default to trigger -Werror=switch */
switch (cmd) {
+ case NETDEV_XDP_FEAT_CHANGE:
+ netdev_assert_locked(dev);
+ fallthrough;
case NETDEV_CHANGE:

Stanislav Fomichev

unread,
Apr 14, 2025, 9:11:18 PM4/14/25
to Jakub Kicinski, da...@davemloft.net, net...@vger.kernel.org, edum...@google.com, pab...@redhat.com, andrew...@lunn.ch, ho...@kernel.org, syzkaller, Kuniyuki Iwashima, s...@fomichev.me, jda...@fastly.com, almas...@google.com
On 04/14, Jakub Kicinski wrote:
> Kuniyuki reports that the assert for netdev lock fires when
> there are netdev event listeners (otherwise we skip the netlink
> event generation).
>
> Correct the locking when coming from the notifier.
>
> The NETDEV_XDP_FEAT_CHANGE notifier is already fully locked,
> it's the documentation that's incorrect.
>
> Fixes: 99e44f39a8f7 ("netdev: depend on netdev->lock for xdp features")
> Reported-by: syzkaller <syzk...@googlegroups.com>
> Reported-by: Kuniyuki Iwashima <kun...@amazon.com>
> Link: https://lore.kernel.org/20250410171019...@amazon.com
> Signed-off-by: Jakub Kicinski <ku...@kernel.org>

Acked-by: Stanislav Fomichev <s...@fomichev.me>
Optional nit: I'm getting lost in all the helpers, I'd add the following here:

else
netdev_ops_assert_locked(dev);

Or maybe even:

if (netdev_need_ops_lock)
netdev_ops_assert_locked
else
netdev_lock

To express the constraints better.

Jakub Kicinski

unread,
Apr 15, 2025, 10:53:04 AM4/15/25
to Stanislav Fomichev, da...@davemloft.net, net...@vger.kernel.org, edum...@google.com, pab...@redhat.com, andrew...@lunn.ch, ho...@kernel.org, syzkaller, Kuniyuki Iwashima, s...@fomichev.me, jda...@fastly.com, almas...@google.com
On Mon, 14 Apr 2025 18:11:14 -0700 Stanislav Fomichev wrote:
> > +static inline void netdev_lock_ops_to_full(struct net_device *dev)
> > +{
> > + if (!netdev_need_ops_lock(dev))
> > + netdev_lock(dev);
>
> Optional nit: I'm getting lost in all the helpers, I'd add the following here:
>
> else
> netdev_ops_assert_locked(dev);
>
> Or maybe even:
>
> if (netdev_need_ops_lock)
> netdev_ops_assert_locked
> else
> netdev_lock
>
> To express the constraints better.

Hm, yes, I like.

Jakub Kicinski

unread,
Apr 15, 2025, 11:04:57 PM4/15/25
to da...@davemloft.net, net...@vger.kernel.org, edum...@google.com, pab...@redhat.com, andrew...@lunn.ch, ho...@kernel.org, Jakub Kicinski, syzkaller, Kuniyuki Iwashima, s...@fomichev.me, jda...@fastly.com, almas...@google.com
Kuniyuki reports that the assert for netdev lock fires when
there are netdev event listeners (otherwise we skip the netlink
event generation).

Correct the locking when coming from the notifier.

The NETDEV_XDP_FEAT_CHANGE notifier is already fully locked,
it's the documentation that's incorrect.

Fixes: 99e44f39a8f7 ("netdev: depend on netdev->lock for xdp features")
Reported-by: syzkaller <syzk...@googlegroups.com>
Reported-by: Kuniyuki Iwashima <kun...@amazon.com>
Link: https://lore.kernel.org/20250410171019...@amazon.com
Signed-off-by: Jakub Kicinski <ku...@kernel.org>
---
v3:
- add else branch in the helpers with a lockdep assert
v2: https://lore.kernel.org/20250414195903...@kernel.org
- rebase vs net merge which brought in
commit 04efcee6ef8d ("net: hold instance lock during NETDEV_CHANGE")
v1: https://lore.kernel.org/20250411204629...@kernel.org

CC: kun...@amazon.com
CC: s...@fomichev.me
CC: jda...@fastly.com
CC: almas...@google.com
---
Documentation/networking/netdevices.rst | 4 +++-
include/linux/netdevice.h | 2 +-
include/net/netdev_lock.h | 16 ++++++++++++++++
net/core/lock_debug.c | 4 +++-
net/core/netdev-genl.c | 4 ++++
5 files changed, 27 insertions(+), 3 deletions(-)
index 5706835a660c..2a753813f849 100644
--- a/include/net/netdev_lock.h
+++ b/include/net/netdev_lock.h
@@ -48,6 +48,22 @@ static inline void netdev_unlock_ops(struct net_device *dev)
netdev_unlock(dev);
}

+static inline void netdev_lock_ops_to_full(struct net_device *dev)
+{
+ if (netdev_need_ops_lock(dev))
+ netdev_assert_locked(dev);
+ else
+ netdev_lock(dev);
+}
+
+static inline void netdev_unlock_full_to_ops(struct net_device *dev)
+{
+ if (netdev_need_ops_lock(dev))
+ netdev_assert_locked(dev);
+ else

Stanislav Fomichev

unread,
Apr 16, 2025, 10:40:47 AM4/16/25
to Jakub Kicinski, da...@davemloft.net, net...@vger.kernel.org, edum...@google.com, pab...@redhat.com, andrew...@lunn.ch, ho...@kernel.org, syzkaller, Kuniyuki Iwashima, s...@fomichev.me, jda...@fastly.com, almas...@google.com
On 04/15, Jakub Kicinski wrote:
> Kuniyuki reports that the assert for netdev lock fires when
> there are netdev event listeners (otherwise we skip the netlink
> event generation).
>
> Correct the locking when coming from the notifier.
>
> The NETDEV_XDP_FEAT_CHANGE notifier is already fully locked,
> it's the documentation that's incorrect.
>
> Fixes: 99e44f39a8f7 ("netdev: depend on netdev->lock for xdp features")
> Reported-by: syzkaller <syzk...@googlegroups.com>
> Reported-by: Kuniyuki Iwashima <kun...@amazon.com>
> Link: https://lore.kernel.org/20250410171019...@amazon.com
> Signed-off-by: Jakub Kicinski <ku...@kernel.org>

Acked-by: Stanislav Fomichev <s...@fomichev.me>

patchwork-b...@kernel.org

unread,
Apr 17, 2025, 10:10:09 PM4/17/25
to Jakub Kicinski, da...@davemloft.net, net...@vger.kernel.org, edum...@google.com, pab...@redhat.com, andrew...@lunn.ch, ho...@kernel.org, syzk...@googlegroups.com, kun...@amazon.com, s...@fomichev.me, jda...@fastly.com, almas...@google.com
Hello:

This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <ku...@kernel.org>:

On Tue, 15 Apr 2025 20:04:47 -0700 you wrote:
> Kuniyuki reports that the assert for netdev lock fires when
> there are netdev event listeners (otherwise we skip the netlink
> event generation).
>
> Correct the locking when coming from the notifier.
>
> The NETDEV_XDP_FEAT_CHANGE notifier is already fully locked,
> it's the documentation that's incorrect.
>
> [...]

Here is the summary with links:
- [net-next,v3] netdev: fix the locking for netdev notifications
https://git.kernel.org/netdev/net-next/c/22cbc1ee268b

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html


Reply all
Reply to author
Forward
0 new messages