Message ID | f4659f17b136eaec554d8678de0034c3578580c1.1742557254.git.pabeni@redhat.com (mailing list archive) |
---|---|
State | New |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | udp_tunnel: GRO optimization follow-up | expand |
Paolo Abeni wrote: > The blamed commit below does not take in account that xfrm > can enable GRO over UDP encapsulation without going through > setup_udp_tunnel_sock(). > > At deletion time such socket will still go through > udp_tunnel_cleanup_gro(), and the failed GRO type lookup will > trigger the reported warning. > > Add the GRO accounting for XFRM tunnel when GRO is enabled, and > adjust the known gro types accordingly. > > Note that we can't use setup_udp_tunnel_sock() here, as the xfrm > tunnel setup can be "incremental" - e.g. the encapsulation is created > first and GRO is enabled later. > > Also we can not allow GRO sk lookup optimization for XFRM tunnels, as > the socket could match the selection criteria at enable time, and > later on the user-space could disconnect/bind it breaking such > criteria. > > Reported-by: syzbot+8c469a2260132cd095c1@syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?extid=8c469a2260132cd095c1 > Fixes: 311b36574ceac ("udp_tunnel: use static call for GRO hooks when possible") > Signed-off-by: Paolo Abeni <pabeni@redhat.com> > --- > v1 -> v2: > - do proper account for xfrm, retain the warning > --- > net/ipv4/udp.c | 5 +++++ > net/ipv4/udp_offload.c | 4 +++- > 2 files changed, 8 insertions(+), 1 deletion(-) > > diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c > index db606f7e41638..79efbf465fb04 100644 > --- a/net/ipv4/udp.c > +++ b/net/ipv4/udp.c > @@ -2903,10 +2903,15 @@ static void set_xfrm_gro_udp_encap_rcv(__u16 encap_type, unsigned short family, > { > #ifdef CONFIG_XFRM > if (udp_test_bit(GRO_ENABLED, sk) && encap_type == UDP_ENCAP_ESPINUDP) { > + bool old_enabled = !!udp_sk(sk)->gro_receive; > + > if (family == AF_INET) > WRITE_ONCE(udp_sk(sk)->gro_receive, xfrm4_gro_udp_encap_rcv); > else if (IS_ENABLED(CONFIG_IPV6) && family == AF_INET6) > WRITE_ONCE(udp_sk(sk)->gro_receive, ipv6_stub->xfrm6_gro_udp_encap_rcv); > + > + if (!old_enabled && udp_sk(sk)->gro_receive) > + udp_tunnel_update_gro_rcv(sk, true); The second part of the condition is always true right?
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index db606f7e41638..79efbf465fb04 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2903,10 +2903,15 @@ static void set_xfrm_gro_udp_encap_rcv(__u16 encap_type, unsigned short family, { #ifdef CONFIG_XFRM if (udp_test_bit(GRO_ENABLED, sk) && encap_type == UDP_ENCAP_ESPINUDP) { + bool old_enabled = !!udp_sk(sk)->gro_receive; + if (family == AF_INET) WRITE_ONCE(udp_sk(sk)->gro_receive, xfrm4_gro_udp_encap_rcv); else if (IS_ENABLED(CONFIG_IPV6) && family == AF_INET6) WRITE_ONCE(udp_sk(sk)->gro_receive, ipv6_stub->xfrm6_gro_udp_encap_rcv); + + if (!old_enabled && udp_sk(sk)->gro_receive) + udp_tunnel_update_gro_rcv(sk, true); } #endif } diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 088aa8cb8ac0c..02365b818f1af 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -37,9 +37,11 @@ struct udp_tunnel_type_entry { refcount_t count; }; +/* vxlan, fou and xfrm have 2 different gro_receive hooks each */ #define UDP_MAX_TUNNEL_TYPES (IS_ENABLED(CONFIG_GENEVE) + \ IS_ENABLED(CONFIG_VXLAN) * 2 + \ - IS_ENABLED(CONFIG_NET_FOU) * 2) + IS_ENABLED(CONFIG_NET_FOU) * 2 + \ + IS_ENABLED(CONFIG_XFRM) * 2) DEFINE_STATIC_CALL(udp_tunnel_gro_rcv, dummy_gro_rcv); static DEFINE_STATIC_KEY_FALSE(udp_tunnel_static_call);
The blamed commit below does not take in account that xfrm can enable GRO over UDP encapsulation without going through setup_udp_tunnel_sock(). At deletion time such socket will still go through udp_tunnel_cleanup_gro(), and the failed GRO type lookup will trigger the reported warning. Add the GRO accounting for XFRM tunnel when GRO is enabled, and adjust the known gro types accordingly. Note that we can't use setup_udp_tunnel_sock() here, as the xfrm tunnel setup can be "incremental" - e.g. the encapsulation is created first and GRO is enabled later. Also we can not allow GRO sk lookup optimization for XFRM tunnels, as the socket could match the selection criteria at enable time, and later on the user-space could disconnect/bind it breaking such criteria. Reported-by: syzbot+8c469a2260132cd095c1@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=8c469a2260132cd095c1 Fixes: 311b36574ceac ("udp_tunnel: use static call for GRO hooks when possible") Signed-off-by: Paolo Abeni <pabeni@redhat.com> --- v1 -> v2: - do proper account for xfrm, retain the warning --- net/ipv4/udp.c | 5 +++++ net/ipv4/udp_offload.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-)