net: ipv6: fix dst ref loops in rpl, seg6 and ioam6 lwtunnels
Some lwtunnels have a dst cache for post-transformation dst. If the packet destination did not change we may end up recording a reference to the lwtunnel in its own cache, and the lwtunnel state will never be freed. Discovered by the ioam6.sh test, kmemleak was recently fixed to catch per-cpu memory leaks. I'm not sure if rpl and seg6 can actually hit this, but in principle I don't see why not. Fixes:8cb3bf8bff
("ipv6: ioam: Add support for the ip6ip6 encapsulation") Fixes:6c8702c60b
("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels") Fixes:a7a29f9c36
("net: ipv6: add rpl sr tunnel") Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20250130031519.2716843-2-kuba@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
c71a192976
commit
92191dd107
3 changed files with 18 additions and 9 deletions
|
@ -410,9 +410,12 @@ do_encap:
|
|||
goto drop;
|
||||
}
|
||||
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&ilwt->cache, cache_dst, &fl6.saddr);
|
||||
local_bh_enable();
|
||||
/* cache only if we don't create a dst reference loop */
|
||||
if (dst->lwtstate != cache_dst->lwtstate) {
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&ilwt->cache, cache_dst, &fl6.saddr);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
err = skb_cow_head(skb, LL_RESERVED_SPACE(cache_dst->dev));
|
||||
if (unlikely(err))
|
||||
|
|
|
@ -235,9 +235,12 @@ static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
|||
goto drop;
|
||||
}
|
||||
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&rlwt->cache, dst, &fl6.saddr);
|
||||
local_bh_enable();
|
||||
/* cache only if we don't create a dst reference loop */
|
||||
if (orig_dst->lwtstate != dst->lwtstate) {
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&rlwt->cache, dst, &fl6.saddr);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
|
||||
if (unlikely(err))
|
||||
|
|
|
@ -576,9 +576,12 @@ static int seg6_output_core(struct net *net, struct sock *sk,
|
|||
goto drop;
|
||||
}
|
||||
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
|
||||
local_bh_enable();
|
||||
/* cache only if we don't create a dst reference loop */
|
||||
if (orig_dst->lwtstate != dst->lwtstate) {
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
|
||||
if (unlikely(err))
|
||||
|
|
Loading…
Add table
Reference in a new issue