Merge branch 'fixes-for-seg6-and-rpl-lwtunnels-on-input'
Justin Iurman says:
====================
fixes for seg6 and rpl lwtunnels on input
As a follow up to commit 92191dd107
("net: ipv6: fix dst ref loops in
rpl, seg6 and ioam6 lwtunnels"), we also need a conditional dst cache on
input for seg6_iptunnel and rpl_iptunnel to prevent dst ref loops (i.e.,
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). This series provides a fix to respectively prevent a
dst ref loop on input in seg6_iptunnel and rpl_iptunnel.
v2:
- https://lore.kernel.org/netdev/20250211221624.18435-1-justin.iurman@uliege.be/
v1:
- https://lore.kernel.org/netdev/20250209193840.20509-1-justin.iurman@uliege.be/
====================
Link: https://patch.msgid.link/20250225175139.25239-1-justin.iurman@uliege.be
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
c907db8d44
2 changed files with 24 additions and 4 deletions
|
@ -262,10 +262,18 @@ static int rpl_input(struct sk_buff *skb)
|
|||
{
|
||||
struct dst_entry *orig_dst = skb_dst(skb);
|
||||
struct dst_entry *dst = NULL;
|
||||
struct lwtunnel_state *lwtst;
|
||||
struct rpl_lwt *rlwt;
|
||||
int err;
|
||||
|
||||
rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate);
|
||||
/* We cannot dereference "orig_dst" once ip6_route_input() or
|
||||
* skb_dst_drop() is called. However, in order to detect a dst loop, we
|
||||
* need the address of its lwtstate. So, save the address of lwtstate
|
||||
* now and use it later as a comparison.
|
||||
*/
|
||||
lwtst = orig_dst->lwtstate;
|
||||
|
||||
rlwt = rpl_lwt_lwtunnel(lwtst);
|
||||
|
||||
local_bh_disable();
|
||||
dst = dst_cache_get(&rlwt->cache);
|
||||
|
@ -280,7 +288,9 @@ static int rpl_input(struct sk_buff *skb)
|
|||
if (!dst) {
|
||||
ip6_route_input(skb);
|
||||
dst = skb_dst(skb);
|
||||
if (!dst->error) {
|
||||
|
||||
/* cache only if we don't create a dst reference loop */
|
||||
if (!dst->error && lwtst != dst->lwtstate) {
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&rlwt->cache, dst,
|
||||
&ipv6_hdr(skb)->saddr);
|
||||
|
|
|
@ -472,10 +472,18 @@ static int seg6_input_core(struct net *net, struct sock *sk,
|
|||
{
|
||||
struct dst_entry *orig_dst = skb_dst(skb);
|
||||
struct dst_entry *dst = NULL;
|
||||
struct lwtunnel_state *lwtst;
|
||||
struct seg6_lwt *slwt;
|
||||
int err;
|
||||
|
||||
slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
|
||||
/* We cannot dereference "orig_dst" once ip6_route_input() or
|
||||
* skb_dst_drop() is called. However, in order to detect a dst loop, we
|
||||
* need the address of its lwtstate. So, save the address of lwtstate
|
||||
* now and use it later as a comparison.
|
||||
*/
|
||||
lwtst = orig_dst->lwtstate;
|
||||
|
||||
slwt = seg6_lwt_lwtunnel(lwtst);
|
||||
|
||||
local_bh_disable();
|
||||
dst = dst_cache_get(&slwt->cache);
|
||||
|
@ -490,7 +498,9 @@ static int seg6_input_core(struct net *net, struct sock *sk,
|
|||
if (!dst) {
|
||||
ip6_route_input(skb);
|
||||
dst = skb_dst(skb);
|
||||
if (!dst->error) {
|
||||
|
||||
/* cache only if we don't create a dst reference loop */
|
||||
if (!dst->error && lwtst != dst->lwtstate) {
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&slwt->cache, dst,
|
||||
&ipv6_hdr(skb)->saddr);
|
||||
|
|
Loading…
Add table
Reference in a new issue