summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-06-25 08:53:02 -0700
committerJakub Kicinski <kuba@kernel.org>2026-06-25 08:53:03 -0700
commit106f6b1dfa1f45f116c5c700342188a3cd4a4b9f (patch)
tree1c9330007771e51609e6080f025dc8379e3c1c23
parent36323f54cd323122a1be89ab2c316a6e55a94e30 (diff)
parentc1481c94e74c955e0448ddf46b8615a44d840c1e (diff)
Merge branch 'tipc-syzbot-related-fixes'
Eric Dumazet says: ==================== tipc: syzbot related fixes First patch fixes a recent syzbot report. Second patch is inspired by numerous syzbot soft lockup reports with RTNL pressure. ==================== Link: https://patch.msgid.link/20260623173030.2925059-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--net/tipc/core.c4
-rw-r--r--net/tipc/udp_media.c19
2 files changed, 16 insertions, 7 deletions
diff --git a/net/tipc/core.c b/net/tipc/core.c
index 1ddecea1df6e..315975c3be81 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -45,6 +45,7 @@
#include "crypto.h"
#include <linux/module.h>
+#include <linux/wait_bit.h>
/* configurable TIPC parameters */
unsigned int tipc_net_id __read_mostly;
@@ -118,8 +119,7 @@ static void __net_exit tipc_exit_net(struct net *net)
#ifdef CONFIG_TIPC_CRYPTO
tipc_crypto_stop(&tipc_net(net)->crypto_tx);
#endif
- while (atomic_read(&tn->wq_count))
- cond_resched();
+ wait_var_event(&tn->wq_count, atomic_read(&tn->wq_count) == 0);
}
static void __net_exit tipc_pernet_pre_exit(struct net *net)
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 988b8a7f953a..62ae7f5b5840 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -40,6 +40,7 @@
#include <linux/igmp.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
+#include <linux/wait_bit.h>
#include <linux/list.h>
#include <net/sock.h>
#include <net/ip.h>
@@ -803,6 +804,14 @@ err:
return err;
}
+static void rcast_free_rcu(struct rcu_head *rcu)
+{
+ struct udp_replicast *rcast = container_of(rcu, struct udp_replicast, rcu);
+
+ dst_cache_destroy(&rcast->dst_cache);
+ kfree(rcast);
+}
+
/* cleanup_bearer - break the socket/bearer association */
static void cleanup_bearer(struct work_struct *work)
{
@@ -811,19 +820,19 @@ static void cleanup_bearer(struct work_struct *work)
struct tipc_net *tn;
list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
- dst_cache_destroy(&rcast->dst_cache);
list_del_rcu(&rcast->list);
- kfree_rcu(rcast, rcu);
+ call_rcu_hurry(&rcast->rcu, rcast_free_rcu);
}
tn = tipc_net(sock_net(ub->sk));
- dst_cache_destroy(&ub->rcast.dst_cache);
udp_tunnel_sock_release(ub->sk);
- /* Note: could use a call_rcu() to avoid another synchronize_net() */
synchronize_net();
- atomic_dec(&tn->wq_count);
+
+ dst_cache_destroy(&ub->rcast.dst_cache);
+ if (atomic_dec_and_test(&tn->wq_count))
+ wake_up_var(&tn->wq_count);
kfree(ub);
}