From e5549aecdd24c43ef9d05c376343a621f0e04277 Mon Sep 17 00:00:00 2001 From: Fushuai Wang Date: Tue, 14 Apr 2026 17:39:41 +0200 Subject: wireguard: allowedips: Use kfree_rcu() instead of call_rcu() Replace call_rcu() + kmem_cache_free() with kfree_rcu() to simplify the code and reduce function size. Signed-off-by: Fushuai Wang Reviewed-by: Simon Horman Signed-off-by: Jason A. Donenfeld Link: https://patch.msgid.link/20260414153944.2742252-2-Jason@zx2c4.com Signed-off-by: Jakub Kicinski --- drivers/net/wireguard/allowedips.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c index 09f7fcd7da78..5ece9acad64d 100644 --- a/drivers/net/wireguard/allowedips.c +++ b/drivers/net/wireguard/allowedips.c @@ -48,11 +48,6 @@ static void push_rcu(struct allowedips_node **stack, } } -static void node_free_rcu(struct rcu_head *rcu) -{ - kmem_cache_free(node_cache, container_of(rcu, struct allowedips_node, rcu)); -} - static void root_free_rcu(struct rcu_head *rcu) { struct allowedips_node *node, *stack[MAX_ALLOWEDIPS_DEPTH] = { @@ -271,13 +266,13 @@ static void remove_node(struct allowedips_node *node, struct mutex *lock) if (free_parent) child = rcu_dereference_protected(parent->bit[!(node->parent_bit_packed & 1)], lockdep_is_held(lock)); - call_rcu(&node->rcu, node_free_rcu); + kfree_rcu(node, rcu); if (!free_parent) return; if (child) child->parent_bit_packed = parent->parent_bit_packed; *(struct allowedips_node **)(parent->parent_bit_packed & ~3UL) = child; - call_rcu(&parent->rcu, node_free_rcu); + kfree_rcu(parent, rcu); } static int remove(struct allowedips_node __rcu **trie, u8 bits, const u8 *key, -- cgit v1.2.3 From f364db381c9d38c96de3148ac584f859c550fad5 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 14 Apr 2026 17:39:43 +0200 Subject: wireguard: allowedips: remove redundant space Not a contentful commit, but amusingly found when porting ba3d7b93 to Windows. Signed-off-by: Jason A. Donenfeld Link: https://patch.msgid.link/20260414153944.2742252-4-Jason@zx2c4.com Signed-off-by: Jakub Kicinski --- drivers/net/wireguard/selftest/allowedips.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireguard/selftest/allowedips.c b/drivers/net/wireguard/selftest/allowedips.c index 2da3008c3a01..3e857e6fb627 100644 --- a/drivers/net/wireguard/selftest/allowedips.c +++ b/drivers/net/wireguard/selftest/allowedips.c @@ -623,7 +623,7 @@ bool __init wg_allowedips_selftest(void) test_boolean(!remove(6, b, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128)); test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); /* invalid CIDR should have no effect and return -EINVAL */ - test_boolean(remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 129) == -EINVAL); + test_boolean(remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 129) == -EINVAL); test(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); remove(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128); test_negative(6, a, 0x24446801, 0x40e40800, 0xdeaebeef, 0xdefbeef); -- cgit v1.2.3 From 60a25ef8dacb3566b1a8c4de00572a498e2a3bf9 Mon Sep 17 00:00:00 2001 From: Shardul Bankar Date: Tue, 14 Apr 2026 17:39:44 +0200 Subject: wireguard: device: use exit_rtnl callback instead of manual rtnl_lock in pre_exit wg_netns_pre_exit() manually acquires rtnl_lock() inside the pernet .pre_exit callback. This causes a hung task when another thread holds rtnl_mutex - the cleanup_net workqueue (or the setup_net failure rollback path) blocks indefinitely in wg_netns_pre_exit() waiting to acquire the lock. Convert to .exit_rtnl, introduced in commit 7a60d91c690b ("net: Add ->exit_rtnl() hook to struct pernet_operations."), where the framework already holds RTNL and batches all callbacks under a single rtnl_lock()/rtnl_unlock() pair, eliminating the contention window. The rcu_assign_pointer(wg->creating_net, NULL) is safe to move from .pre_exit to .exit_rtnl (which runs after synchronize_rcu()) because all RCU readers of creating_net either use maybe_get_net() - which returns NULL for a dying namespace with zero refcount - or access net->user_ns which remains valid throughout the entire ops_undo_list sequence. Reported-by: syzbot+f2fbf7478a35a94c8b7c@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?id=cb64c22a492202ca929e18262fdb8cb89e635c70 Signed-off-by: Shardul Bankar [ Jason: added __net_exit and __read_mostly annotations that were missing. ] Fixes: 900575aa33a3 ("wireguard: device: avoid circular netns references") Cc: stable@vger.kernel.org Signed-off-by: Jason A. Donenfeld Link: https://patch.msgid.link/20260414153944.2742252-5-Jason@zx2c4.com Signed-off-by: Jakub Kicinski --- drivers/net/wireguard/device.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index 46a71ec36af8..67b07ee2d660 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -411,12 +411,11 @@ static struct rtnl_link_ops link_ops __read_mostly = { .newlink = wg_newlink, }; -static void wg_netns_pre_exit(struct net *net) +static void __net_exit wg_netns_exit_rtnl(struct net *net, struct list_head *dev_kill_list) { struct wg_device *wg; struct wg_peer *peer; - rtnl_lock(); list_for_each_entry(wg, &device_list, device_list) { if (rcu_access_pointer(wg->creating_net) == net) { pr_debug("%s: Creating namespace exiting\n", wg->dev->name); @@ -429,11 +428,10 @@ static void wg_netns_pre_exit(struct net *net) mutex_unlock(&wg->device_update_lock); } } - rtnl_unlock(); } -static struct pernet_operations pernet_ops = { - .pre_exit = wg_netns_pre_exit +static struct pernet_operations pernet_ops __read_mostly = { + .exit_rtnl = wg_netns_exit_rtnl }; int __init wg_device_init(void) -- cgit v1.2.3