* [PATCH net 1/4] inet: frags: avoid theoretical race in ip_frag_reinit()
2025-12-07 1:09 [PATCH net 0/4] inet: frags: flush pending skbs in fqdir_pre_exit() Jakub Kicinski
@ 2025-12-07 1:09 ` Jakub Kicinski
2025-12-08 15:18 ` Eric Dumazet
2025-12-07 1:09 ` [PATCH net 2/4] inet: frags: add inet_frag_queue_flush() Jakub Kicinski
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Jakub Kicinski @ 2025-12-07 1:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, pablo, fw,
netfilter-devel, willemdebruijn.kernel, kuniyu, Jakub Kicinski
In ip_frag_reinit() we want to move the frag timeout timer into
the future. If the timer fires in the meantime we inadvertently
scheduled it again, and since the timer assumes a ref on frag_queue
we need to acquire one to balance things out.
This is technically racy, we should have acquired the reference
_before_ we touch the timer, it may fire again before we take the ref.
Avoid this entire dance by using mod_timer_pending() which only modifies
the timer if its pending (and which exists since Linux v2.6.30)
Note that this was the only place we ever took a ref on frag_queue
since Eric's conversion to RCU. So we could potentially replace
the whole refcnt field with an atomic flag and a bit more RCU.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
net/ipv4/inet_fragment.c | 4 +++-
net/ipv4/ip_fragment.c | 4 +---
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 025895eb6ec5..30f4fa50ee2d 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -327,7 +327,9 @@ static struct inet_frag_queue *inet_frag_alloc(struct fqdir *fqdir,
timer_setup(&q->timer, f->frag_expire, 0);
spin_lock_init(&q->lock);
- /* One reference for the timer, one for the hash table. */
+ /* One reference for the timer, one for the hash table.
+ * We never take any extra references, only decrement this field.
+ */
refcount_set(&q->refcnt, 2);
return q;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index f7012479713b..d7bccdc9dc69 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -242,10 +242,8 @@ static int ip_frag_reinit(struct ipq *qp)
{
unsigned int sum_truesize = 0;
- if (!mod_timer(&qp->q.timer, jiffies + qp->q.fqdir->timeout)) {
- refcount_inc(&qp->q.refcnt);
+ if (!mod_timer_pending(&qp->q.timer, jiffies + qp->q.fqdir->timeout))
return -ETIMEDOUT;
- }
sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments,
SKB_DROP_REASON_FRAG_TOO_FAR);
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net 1/4] inet: frags: avoid theoretical race in ip_frag_reinit()
2025-12-07 1:09 ` [PATCH net 1/4] inet: frags: avoid theoretical race in ip_frag_reinit() Jakub Kicinski
@ 2025-12-08 15:18 ` Eric Dumazet
0 siblings, 0 replies; 11+ messages in thread
From: Eric Dumazet @ 2025-12-08 15:18 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, pabeni, andrew+netdev, horms, pablo, fw,
netfilter-devel, willemdebruijn.kernel, kuniyu
On Sat, Dec 6, 2025 at 5:10 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> In ip_frag_reinit() we want to move the frag timeout timer into
> the future. If the timer fires in the meantime we inadvertently
> scheduled it again, and since the timer assumes a ref on frag_queue
> we need to acquire one to balance things out.
>
> This is technically racy, we should have acquired the reference
> _before_ we touch the timer, it may fire again before we take the ref.
> Avoid this entire dance by using mod_timer_pending() which only modifies
> the timer if its pending (and which exists since Linux v2.6.30)
>
> Note that this was the only place we ever took a ref on frag_queue
> since Eric's conversion to RCU. So we could potentially replace
> the whole refcnt field with an atomic flag and a bit more RCU.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> ---
Reviewed-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net 2/4] inet: frags: add inet_frag_queue_flush()
2025-12-07 1:09 [PATCH net 0/4] inet: frags: flush pending skbs in fqdir_pre_exit() Jakub Kicinski
2025-12-07 1:09 ` [PATCH net 1/4] inet: frags: avoid theoretical race in ip_frag_reinit() Jakub Kicinski
@ 2025-12-07 1:09 ` Jakub Kicinski
2025-12-08 15:19 ` Eric Dumazet
2025-12-07 1:09 ` [PATCH net 3/4] inet: frags: flush pending skbs in fqdir_pre_exit() Jakub Kicinski
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Jakub Kicinski @ 2025-12-07 1:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, pablo, fw,
netfilter-devel, willemdebruijn.kernel, kuniyu, Jakub Kicinski
Instead of exporting inet_frag_rbtree_purge() which requires that
caller takes care of memory accounting, add a new helper. We will
need to call it from a few places in the next patch.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
include/net/inet_frag.h | 5 ++---
net/ipv4/inet_fragment.c | 15 ++++++++++++---
net/ipv4/ip_fragment.c | 6 +-----
3 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 0eccd9c3a883..3ffaceee7bbc 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -141,9 +141,8 @@ void inet_frag_kill(struct inet_frag_queue *q, int *refs);
void inet_frag_destroy(struct inet_frag_queue *q);
struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key);
-/* Free all skbs in the queue; return the sum of their truesizes. */
-unsigned int inet_frag_rbtree_purge(struct rb_root *root,
- enum skb_drop_reason reason);
+void inet_frag_queue_flush(struct inet_frag_queue *q,
+ enum skb_drop_reason reason);
static inline void inet_frag_putn(struct inet_frag_queue *q, int refs)
{
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 30f4fa50ee2d..1bf969b5a1cb 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -263,8 +263,8 @@ static void inet_frag_destroy_rcu(struct rcu_head *head)
kmem_cache_free(f->frags_cachep, q);
}
-unsigned int inet_frag_rbtree_purge(struct rb_root *root,
- enum skb_drop_reason reason)
+static unsigned int
+inet_frag_rbtree_purge(struct rb_root *root, enum skb_drop_reason reason)
{
struct rb_node *p = rb_first(root);
unsigned int sum = 0;
@@ -284,7 +284,16 @@ unsigned int inet_frag_rbtree_purge(struct rb_root *root,
}
return sum;
}
-EXPORT_SYMBOL(inet_frag_rbtree_purge);
+
+void inet_frag_queue_flush(struct inet_frag_queue *q,
+ enum skb_drop_reason reason)
+{
+ unsigned int sum;
+
+ sum = inet_frag_rbtree_purge(&q->rb_fragments, reason);
+ sub_frag_mem_limit(q->fqdir, sum);
+}
+EXPORT_SYMBOL(inet_frag_queue_flush);
void inet_frag_destroy(struct inet_frag_queue *q)
{
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index d7bccdc9dc69..32f1c1a46ba7 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -240,14 +240,10 @@ static int ip_frag_too_far(struct ipq *qp)
static int ip_frag_reinit(struct ipq *qp)
{
- unsigned int sum_truesize = 0;
-
if (!mod_timer_pending(&qp->q.timer, jiffies + qp->q.fqdir->timeout))
return -ETIMEDOUT;
- sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments,
- SKB_DROP_REASON_FRAG_TOO_FAR);
- sub_frag_mem_limit(qp->q.fqdir, sum_truesize);
+ inet_frag_queue_flush(&qp->q, SKB_DROP_REASON_FRAG_TOO_FAR);
qp->q.flags = 0;
qp->q.len = 0;
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net 2/4] inet: frags: add inet_frag_queue_flush()
2025-12-07 1:09 ` [PATCH net 2/4] inet: frags: add inet_frag_queue_flush() Jakub Kicinski
@ 2025-12-08 15:19 ` Eric Dumazet
0 siblings, 0 replies; 11+ messages in thread
From: Eric Dumazet @ 2025-12-08 15:19 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, pabeni, andrew+netdev, horms, pablo, fw,
netfilter-devel, willemdebruijn.kernel, kuniyu
On Sat, Dec 6, 2025 at 5:10 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> Instead of exporting inet_frag_rbtree_purge() which requires that
> caller takes care of memory accounting, add a new helper. We will
> need to call it from a few places in the next patch.
>
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net 3/4] inet: frags: flush pending skbs in fqdir_pre_exit()
2025-12-07 1:09 [PATCH net 0/4] inet: frags: flush pending skbs in fqdir_pre_exit() Jakub Kicinski
2025-12-07 1:09 ` [PATCH net 1/4] inet: frags: avoid theoretical race in ip_frag_reinit() Jakub Kicinski
2025-12-07 1:09 ` [PATCH net 2/4] inet: frags: add inet_frag_queue_flush() Jakub Kicinski
@ 2025-12-07 1:09 ` Jakub Kicinski
2025-12-08 15:17 ` Eric Dumazet
2025-12-07 1:09 ` [PATCH net 4/4] netfilter: conntrack: warn when cleanup is stuck Jakub Kicinski
2025-12-10 9:50 ` [PATCH net 0/4] inet: frags: flush pending skbs in fqdir_pre_exit() patchwork-bot+netdevbpf
4 siblings, 1 reply; 11+ messages in thread
From: Jakub Kicinski @ 2025-12-07 1:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, pablo, fw,
netfilter-devel, willemdebruijn.kernel, kuniyu, Jakub Kicinski
We have been seeing occasional deadlocks on pernet_ops_rwsem since
September in NIPA. The stuck task was usually modprobe (often loading
a driver like ipvlan), trying to take the lock as a Writer.
lockdep does not track readers for rwsems so the read wasn't obvious
from the reports.
On closer inspection the Reader holding the lock was conntrack looping
forever in nf_conntrack_cleanup_net_list(). Based on past experience
with occasional NIPA crashes I looked thru the tests which run before
the crash and noticed that the crash follows ip_defrag.sh. An immediate
red flag. Scouring thru (de)fragmentation queues reveals skbs sitting
around, holding conntrack references.
The problem is that since conntrack depends on nf_defrag_ipv6,
nf_defrag_ipv6 will load first. Since nf_defrag_ipv6 loads first its
netns exit hooks run _after_ conntrack's netns exit hook.
Flush all fragment queue SKBs during fqdir_pre_exit() to release
conntrack references before conntrack cleanup runs. Also flush
the queues in timer expiry handlers when they discover fqdir->dead
is set, in case packet sneaks in while we're running the pre_exit
flush.
The commit under Fixes is not exactly the culprit, but I think
previously the timer firing would eventually unblock the spinning
conntrack.
Fixes: d5dd88794a13 ("inet: fix various use-after-free in defrags units")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
include/net/inet_frag.h | 13 +------------
include/net/ipv6_frag.h | 9 ++++++---
net/ipv4/inet_fragment.c | 36 ++++++++++++++++++++++++++++++++++++
net/ipv4/ip_fragment.c | 12 +++++++-----
4 files changed, 50 insertions(+), 20 deletions(-)
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index 3ffaceee7bbc..365925c9d262 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -123,18 +123,7 @@ void inet_frags_fini(struct inet_frags *);
int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net);
-static inline void fqdir_pre_exit(struct fqdir *fqdir)
-{
- /* Prevent creation of new frags.
- * Pairs with READ_ONCE() in inet_frag_find().
- */
- WRITE_ONCE(fqdir->high_thresh, 0);
-
- /* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire()
- * and ip6frag_expire_frag_queue().
- */
- WRITE_ONCE(fqdir->dead, true);
-}
+void fqdir_pre_exit(struct fqdir *fqdir);
void fqdir_exit(struct fqdir *fqdir);
void inet_frag_kill(struct inet_frag_queue *q, int *refs);
diff --git a/include/net/ipv6_frag.h b/include/net/ipv6_frag.h
index 38ef66826939..41d9fc6965f9 100644
--- a/include/net/ipv6_frag.h
+++ b/include/net/ipv6_frag.h
@@ -69,9 +69,6 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
int refs = 1;
rcu_read_lock();
- /* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
- if (READ_ONCE(fq->q.fqdir->dead))
- goto out_rcu_unlock;
spin_lock(&fq->q.lock);
if (fq->q.flags & INET_FRAG_COMPLETE)
@@ -80,6 +77,12 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
fq->q.flags |= INET_FRAG_DROP;
inet_frag_kill(&fq->q, &refs);
+ /* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
+ if (READ_ONCE(fq->q.fqdir->dead)) {
+ inet_frag_queue_flush(&fq->q, 0);
+ goto out;
+ }
+
dev = dev_get_by_index_rcu(net, fq->iif);
if (!dev)
goto out;
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 1bf969b5a1cb..001ee5c4d962 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -218,6 +218,41 @@ static int __init inet_frag_wq_init(void)
pure_initcall(inet_frag_wq_init);
+void fqdir_pre_exit(struct fqdir *fqdir)
+{
+ struct inet_frag_queue *fq;
+ struct rhashtable_iter hti;
+
+ /* Prevent creation of new frags.
+ * Pairs with READ_ONCE() in inet_frag_find().
+ */
+ WRITE_ONCE(fqdir->high_thresh, 0);
+
+ /* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire()
+ * and ip6frag_expire_frag_queue().
+ */
+ WRITE_ONCE(fqdir->dead, true);
+
+ rhashtable_walk_enter(&fqdir->rhashtable, &hti);
+ rhashtable_walk_start(&hti);
+
+ while ((fq = rhashtable_walk_next(&hti))) {
+ if (IS_ERR(fq)) {
+ if (PTR_ERR(fq) != -EAGAIN)
+ break;
+ continue;
+ }
+ spin_lock_bh(&fq->lock);
+ if (!(fq->flags & INET_FRAG_COMPLETE))
+ inet_frag_queue_flush(fq, 0);
+ spin_unlock_bh(&fq->lock);
+ }
+
+ rhashtable_walk_stop(&hti);
+ rhashtable_walk_exit(&hti);
+}
+EXPORT_SYMBOL(fqdir_pre_exit);
+
void fqdir_exit(struct fqdir *fqdir)
{
INIT_WORK(&fqdir->destroy_work, fqdir_work_fn);
@@ -290,6 +325,7 @@ void inet_frag_queue_flush(struct inet_frag_queue *q,
{
unsigned int sum;
+ reason = reason ?: SKB_DROP_REASON_FRAG_REASM_TIMEOUT;
sum = inet_frag_rbtree_purge(&q->rb_fragments, reason);
sub_frag_mem_limit(q->fqdir, sum);
}
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 32f1c1a46ba7..56b0f738d2f2 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -134,11 +134,6 @@ static void ip_expire(struct timer_list *t)
net = qp->q.fqdir->net;
rcu_read_lock();
-
- /* Paired with WRITE_ONCE() in fqdir_pre_exit(). */
- if (READ_ONCE(qp->q.fqdir->dead))
- goto out_rcu_unlock;
-
spin_lock(&qp->q.lock);
if (qp->q.flags & INET_FRAG_COMPLETE)
@@ -146,6 +141,13 @@ static void ip_expire(struct timer_list *t)
qp->q.flags |= INET_FRAG_DROP;
inet_frag_kill(&qp->q, &refs);
+
+ /* Paired with WRITE_ONCE() in fqdir_pre_exit(). */
+ if (READ_ONCE(qp->q.fqdir->dead)) {
+ inet_frag_queue_flush(&qp->q, 0);
+ goto out;
+ }
+
__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
__IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT);
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net 3/4] inet: frags: flush pending skbs in fqdir_pre_exit()
2025-12-07 1:09 ` [PATCH net 3/4] inet: frags: flush pending skbs in fqdir_pre_exit() Jakub Kicinski
@ 2025-12-08 15:17 ` Eric Dumazet
0 siblings, 0 replies; 11+ messages in thread
From: Eric Dumazet @ 2025-12-08 15:17 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, pabeni, andrew+netdev, horms, pablo, fw,
netfilter-devel, willemdebruijn.kernel, kuniyu
On Sat, Dec 6, 2025 at 5:10 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> We have been seeing occasional deadlocks on pernet_ops_rwsem since
> September in NIPA. The stuck task was usually modprobe (often loading
> a driver like ipvlan), trying to take the lock as a Writer.
> lockdep does not track readers for rwsems so the read wasn't obvious
> from the reports.
>
> On closer inspection the Reader holding the lock was conntrack looping
> forever in nf_conntrack_cleanup_net_list(). Based on past experience
> with occasional NIPA crashes I looked thru the tests which run before
> the crash and noticed that the crash follows ip_defrag.sh. An immediate
> red flag. Scouring thru (de)fragmentation queues reveals skbs sitting
> around, holding conntrack references.
>
> The problem is that since conntrack depends on nf_defrag_ipv6,
> nf_defrag_ipv6 will load first. Since nf_defrag_ipv6 loads first its
> netns exit hooks run _after_ conntrack's netns exit hook.
>
> Flush all fragment queue SKBs during fqdir_pre_exit() to release
> conntrack references before conntrack cleanup runs. Also flush
> the queues in timer expiry handlers when they discover fqdir->dead
> is set, in case packet sneaks in while we're running the pre_exit
> flush.
>
> The commit under Fixes is not exactly the culprit, but I think
> previously the timer firing would eventually unblock the spinning
> conntrack.
>
> Fixes: d5dd88794a13 ("inet: fix various use-after-free in defrags units")
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Reviewed-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH net 4/4] netfilter: conntrack: warn when cleanup is stuck
2025-12-07 1:09 [PATCH net 0/4] inet: frags: flush pending skbs in fqdir_pre_exit() Jakub Kicinski
` (2 preceding siblings ...)
2025-12-07 1:09 ` [PATCH net 3/4] inet: frags: flush pending skbs in fqdir_pre_exit() Jakub Kicinski
@ 2025-12-07 1:09 ` Jakub Kicinski
2025-12-07 10:21 ` Florian Westphal
2025-12-10 9:50 ` [PATCH net 0/4] inet: frags: flush pending skbs in fqdir_pre_exit() patchwork-bot+netdevbpf
4 siblings, 1 reply; 11+ messages in thread
From: Jakub Kicinski @ 2025-12-07 1:09 UTC (permalink / raw)
To: davem
Cc: netdev, edumazet, pabeni, andrew+netdev, horms, pablo, fw,
netfilter-devel, willemdebruijn.kernel, kuniyu, Jakub Kicinski
nf_conntrack_cleanup_net_list() calls schedule() so it does not
show up as a hung task. Add an explicit check to make debugging
leaked skbs/conntack references more obvious.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
net/netfilter/nf_conntrack_core.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 0b95f226f211..d1f8eb725d42 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -2487,6 +2487,7 @@ void nf_conntrack_cleanup_net(struct net *net)
void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
{
struct nf_ct_iter_data iter_data = {};
+ unsigned long start = jiffies;
struct net *net;
int busy;
@@ -2507,6 +2508,8 @@ void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
busy = 1;
}
if (busy) {
+ DEBUG_NET_WARN_ONCE(time_after(jiffies, start + 60 * HZ),
+ "conntrack cleanup blocked for 60s");
schedule();
goto i_see_dead_people;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH net 4/4] netfilter: conntrack: warn when cleanup is stuck
2025-12-07 1:09 ` [PATCH net 4/4] netfilter: conntrack: warn when cleanup is stuck Jakub Kicinski
@ 2025-12-07 10:21 ` Florian Westphal
2025-12-08 15:20 ` Eric Dumazet
0 siblings, 1 reply; 11+ messages in thread
From: Florian Westphal @ 2025-12-07 10:21 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, pablo,
netfilter-devel, willemdebruijn.kernel, kuniyu
Jakub Kicinski <kuba@kernel.org> wrote:
> nf_conntrack_cleanup_net_list() calls schedule() so it does not
> show up as a hung task. Add an explicit check to make debugging
> leaked skbs/conntack references more obvious.
Acked-by: Florian Westphal <fw@strlen.de>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net 4/4] netfilter: conntrack: warn when cleanup is stuck
2025-12-07 10:21 ` Florian Westphal
@ 2025-12-08 15:20 ` Eric Dumazet
0 siblings, 0 replies; 11+ messages in thread
From: Eric Dumazet @ 2025-12-08 15:20 UTC (permalink / raw)
To: Florian Westphal
Cc: Jakub Kicinski, davem, netdev, pabeni, andrew+netdev, horms,
pablo, netfilter-devel, willemdebruijn.kernel, kuniyu
On Sun, Dec 7, 2025 at 2:21 AM Florian Westphal <fw@strlen.de> wrote:
>
> Jakub Kicinski <kuba@kernel.org> wrote:
> > nf_conntrack_cleanup_net_list() calls schedule() so it does not
> > show up as a hung task. Add an explicit check to make debugging
> > leaked skbs/conntack references more obvious.
>
> Acked-by: Florian Westphal <fw@strlen.de>
Reviewed-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH net 0/4] inet: frags: flush pending skbs in fqdir_pre_exit()
2025-12-07 1:09 [PATCH net 0/4] inet: frags: flush pending skbs in fqdir_pre_exit() Jakub Kicinski
` (3 preceding siblings ...)
2025-12-07 1:09 ` [PATCH net 4/4] netfilter: conntrack: warn when cleanup is stuck Jakub Kicinski
@ 2025-12-10 9:50 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 11+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-12-10 9:50 UTC (permalink / raw)
To: Jakub Kicinski
Cc: davem, netdev, edumazet, pabeni, andrew+netdev, horms, pablo, fw,
netfilter-devel, willemdebruijn.kernel, kuniyu
Hello:
This series was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Sat, 6 Dec 2025 17:09:38 -0800 you wrote:
> Fix the issue reported by NIPA starting on Sep 18th [1], where
> pernet_ops_rwsem is constantly held by a reader, preventing writers
> from grabbing it (specifically driver modules from loading).
>
> The fact that reports started around that time seems coincidental.
> The issue seems to be skbs queued for defrag preventing conntrack
> from exiting.
>
> [...]
Here is the summary with links:
- [net,1/4] inet: frags: avoid theoretical race in ip_frag_reinit()
https://git.kernel.org/netdev/net/c/8ef522c8a59a
- [net,2/4] inet: frags: add inet_frag_queue_flush()
https://git.kernel.org/netdev/net/c/1231eec6994b
- [net,3/4] inet: frags: flush pending skbs in fqdir_pre_exit()
https://git.kernel.org/netdev/net/c/006a5035b495
- [net,4/4] netfilter: conntrack: warn when cleanup is stuck
https://git.kernel.org/netdev/net/c/92df4c56cf5b
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 11+ messages in thread