* [PATCH v2 net] ipv6: Fix dst leak for uncached routes.
@ 2026-09-20 19:14 Kuniyuki Iwashima
2026-09-21 9:26 ` Ido Schimmel
2026-09-22 1:20 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 4+ messages in thread
From: Kuniyuki Iwashima @ 2026-09-20 19:14 UTC (permalink / raw)
To: David Ahern, Ido Schimmel, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
Cc: Simon Horman, Kuniyuki Iwashima, Kuniyuki Iwashima, netdev,
Hangbin Liu, Xuanqiang Luo
ip6_route_output_flags(), ip6_rt_put_flags(), and ip6_dst_check()
detect an uncached route by list_empty(&rt->dst.rt_uncached),
which replaced the static DST_NOCACHE flag check in commit
a4c2fd7f7891 ("net: remove DST_NOCACHE flag").
When a device is unregistered, rt6_uncached_list_flush_dev()
unlinks uncached routes tied to the device from rt6_uncached_list.
Previously, they were moved to another list with list_move()
(__list_del_entry() + list_add()), and since commit 98aa546af5e4
("inet: remove (struct uncached_list)->quarantine"), the routes
are just unlinked with list_del_init().
If list_del_init() runs concurrently, list_empty() evaluates to
true; ip6_route_output_flags() calls dst_hold_safe() incorrectly
and ip6_rt_put_flags() skips ip6_rt_put(), leaking dst, and thus
dev tied via rt->from as well.
The same race is partially fixed by commit 9a6f0c4d5796 ("dst:
fix races in rt6_uncached_list_del() and rt_del_uncached_list()").
Let's check rt6->dst.rt_uncached_list instead.
Note that IPv4 does not have the same issue.
Fixes: 98aa546af5e4 ("inet: remove (struct uncached_list)->quarantine")
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn>
Reviewed-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
---
v2: Add a comment, update stale comments, correct Fixes: tag
v1: https://lore.kernel.org/netdev/20260918041439.2575935-1-kuniyu@google.com/
---
include/net/ip6_route.h | 4 ++--
net/ipv6/route.c | 7 ++++---
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index b9e8d2b759e9..0f9b7a260d25 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -101,12 +101,12 @@ static inline struct dst_entry *ip6_route_output(struct net *net,
}
/* Only conditionally release dst if flags indicates
- * !RT6_LOOKUP_F_DST_NOREF or dst is in uncached_list.
+ * !RT6_LOOKUP_F_DST_NOREF or dst is uncached.
*/
static inline void ip6_rt_put_flags(struct rt6_info *rt, int flags)
{
if (!(flags & RT6_LOOKUP_F_DST_NOREF) ||
- !list_empty(&rt->dst.rt_uncached))
+ rt->dst.rt_uncached_list)
ip6_rt_put(rt);
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 08bd68f1b5bb..70d643336610 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -139,6 +139,7 @@ void rt6_uncached_list_add(struct rt6_info *rt)
{
struct uncached_list *ul = raw_cpu_ptr(&rt6_uncached_list);
+ /* Set once and never cleared: non-NULL marks an uncached route. */
rt->dst.rt_uncached_list = ul;
spin_lock_bh(&ul->lock);
@@ -2721,8 +2722,8 @@ struct dst_entry *ip6_route_output_flags(struct net *net,
rcu_read_lock();
dst = ip6_route_output_flags_noref(net, sk, fl6, flags);
rt6 = dst_rt6_info(dst);
- /* For dst cached in uncached_list, refcnt is already taken. */
- if (list_empty(&rt6->dst.rt_uncached) && !dst_hold_safe(dst)) {
+ /* For an uncached dst, refcnt is already taken. */
+ if (!rt6->dst.rt_uncached_list && !dst_hold_safe(dst)) {
dst = &net->ipv6.ip6_null_entry->dst;
dst_hold(dst);
}
@@ -2831,7 +2832,7 @@ INDIRECT_CALLABLE_SCOPE struct dst_entry *ip6_dst_check(struct dst_entry *dst,
from = rcu_dereference(rt->from);
if (from && (rt->rt6i_flags & RTF_PCPU ||
- unlikely(!list_empty(&rt->dst.rt_uncached))))
+ unlikely(rt->dst.rt_uncached_list)))
dst_ret = rt6_dst_from_check(rt, from, cookie);
else
dst_ret = rt6_check(rt, from, cookie);
--
2.55.0.1082.g2b9226bbc0-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 net] ipv6: Fix dst leak for uncached routes.
2026-09-20 19:14 [PATCH v2 net] ipv6: Fix dst leak for uncached routes Kuniyuki Iwashima
@ 2026-09-21 9:26 ` Ido Schimmel
2026-09-21 9:31 ` Eric Dumazet
2026-09-22 1:20 ` patchwork-bot+netdevbpf
1 sibling, 1 reply; 4+ messages in thread
From: Ido Schimmel @ 2026-09-21 9:26 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: David Ahern, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Simon Horman, Kuniyuki Iwashima, netdev, Hangbin Liu,
Xuanqiang Luo
On Sun, Sep 20, 2026 at 07:14:32PM +0000, Kuniyuki Iwashima wrote:
> ip6_route_output_flags(), ip6_rt_put_flags(), and ip6_dst_check()
> detect an uncached route by list_empty(&rt->dst.rt_uncached),
> which replaced the static DST_NOCACHE flag check in commit
> a4c2fd7f7891 ("net: remove DST_NOCACHE flag").
>
> When a device is unregistered, rt6_uncached_list_flush_dev()
> unlinks uncached routes tied to the device from rt6_uncached_list.
>
> Previously, they were moved to another list with list_move()
> (__list_del_entry() + list_add()), and since commit 98aa546af5e4
> ("inet: remove (struct uncached_list)->quarantine"), the routes
> are just unlinked with list_del_init().
>
> If list_del_init() runs concurrently, list_empty() evaluates to
> true; ip6_route_output_flags() calls dst_hold_safe() incorrectly
> and ip6_rt_put_flags() skips ip6_rt_put(), leaking dst, and thus
> dev tied via rt->from as well.
>
> The same race is partially fixed by commit 9a6f0c4d5796 ("dst:
> fix races in rt6_uncached_list_del() and rt_del_uncached_list()").
>
> Let's check rt6->dst.rt_uncached_list instead.
>
> Note that IPv4 does not have the same issue.
>
> Fixes: 98aa546af5e4 ("inet: remove (struct uncached_list)->quarantine")
> Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
> Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn>
> Reviewed-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2 net] ipv6: Fix dst leak for uncached routes.
2026-09-21 9:26 ` Ido Schimmel
@ 2026-09-21 9:31 ` Eric Dumazet
0 siblings, 0 replies; 4+ messages in thread
From: Eric Dumazet @ 2026-09-21 9:31 UTC (permalink / raw)
To: Ido Schimmel
Cc: Kuniyuki Iwashima, David Ahern, David S. Miller, Jakub Kicinski,
Paolo Abeni, Simon Horman, Kuniyuki Iwashima, netdev, Hangbin Liu,
Xuanqiang Luo
On Mon, Sep 21, 2026 at 11:26 AM Ido Schimmel <idosch@nvidia.com> wrote:
>
> On Sun, Sep 20, 2026 at 07:14:32PM +0000, Kuniyuki Iwashima wrote:
> > ip6_route_output_flags(), ip6_rt_put_flags(), and ip6_dst_check()
> > detect an uncached route by list_empty(&rt->dst.rt_uncached),
> > which replaced the static DST_NOCACHE flag check in commit
> > a4c2fd7f7891 ("net: remove DST_NOCACHE flag").
> >
> > When a device is unregistered, rt6_uncached_list_flush_dev()
> > unlinks uncached routes tied to the device from rt6_uncached_list.
> >
> > Previously, they were moved to another list with list_move()
> > (__list_del_entry() + list_add()), and since commit 98aa546af5e4
> > ("inet: remove (struct uncached_list)->quarantine"), the routes
> > are just unlinked with list_del_init().
> >
> > If list_del_init() runs concurrently, list_empty() evaluates to
> > true; ip6_route_output_flags() calls dst_hold_safe() incorrectly
> > and ip6_rt_put_flags() skips ip6_rt_put(), leaking dst, and thus
> > dev tied via rt->from as well.
> >
> > The same race is partially fixed by commit 9a6f0c4d5796 ("dst:
> > fix races in rt6_uncached_list_del() and rt_del_uncached_list()").
> >
> > Let's check rt6->dst.rt_uncached_list instead.
> >
> > Note that IPv4 does not have the same issue.
> >
> > Fixes: 98aa546af5e4 ("inet: remove (struct uncached_list)->quarantine")
> > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
> > Reviewed-by: Hangbin Liu <liuhangbin@kylinos.cn>
> > Reviewed-by: Xuanqiang Luo <luoxuanqiang@kylinos.cn>
>
> Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2 net] ipv6: Fix dst leak for uncached routes.
2026-09-20 19:14 [PATCH v2 net] ipv6: Fix dst leak for uncached routes Kuniyuki Iwashima
2026-09-21 9:26 ` Ido Schimmel
@ 2026-09-22 1:20 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-22 1:20 UTC (permalink / raw)
To: Kuniyuki Iwashima
Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms, kuni1840,
netdev, liuhangbin, luoxuanqiang
Hello:
This patch was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Sun, 20 Sep 2026 19:14:32 +0000 you wrote:
> ip6_route_output_flags(), ip6_rt_put_flags(), and ip6_dst_check()
> detect an uncached route by list_empty(&rt->dst.rt_uncached),
> which replaced the static DST_NOCACHE flag check in commit
> a4c2fd7f7891 ("net: remove DST_NOCACHE flag").
>
> When a device is unregistered, rt6_uncached_list_flush_dev()
> unlinks uncached routes tied to the device from rt6_uncached_list.
>
> [...]
Here is the summary with links:
- [v2,net] ipv6: Fix dst leak for uncached routes.
https://git.kernel.org/netdev/net/c/be31fe6333f5
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] 4+ messages in thread
end of thread, other threads:[~2026-09-22 1:21 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-20 19:14 [PATCH v2 net] ipv6: Fix dst leak for uncached routes Kuniyuki Iwashima
2026-09-21 9:26 ` Ido Schimmel
2026-09-21 9:31 ` Eric Dumazet
2026-09-22 1:20 ` patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox