Message ID | ZKNtndEkrzhtmqkF@gondor.apana.org.au (mailing list archive) |
---|---|
State | Awaiting Upstream |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | xfrm: Silence warnings triggerable by bad packets | expand |
On Tue, Jul 4, 2023 at 2:54 AM Herbert Xu <herbert@gondor.apana.org.au> wrote: > > On Fri, Jun 30, 2023 at 08:37:58AM -0700, Maciej Żenczykowski wrote: > > Steffan, this isn't of course a patch meant for inclusion, instead just a WARN_ON hit report. > > The patch is simply what prints the following extra info: > > > > xfrm_prepare_input: XFRM_MODE_SKB_CB(skb)->protocol: 17 > > xfrm_inner_mode_encap_remove: x->props.mode: 1 XFRM_MODE_SKB_SB(skb)->protocol:17 > > > > (note: XFRM_MODE_TUNNEL=1 IPPROTO_UDP=17) > > Thanks for the report. This patch should fix the warnings: > > ---8<--- > After the elimination of inner modes, a couple of warnings that > were previously unreachable can now be triggered by malformed > inbound packets. > > Fix this by: > > 1. Moving the setting of skb->protocol into the decap functions. > 2. Returning -EINVAL when unexpected protocol is seen. > > Reported-by: Maciej Żenczykowski<maze@google.com> > Fixes: 5f24f41e8ea6 ("xfrm: Remove inner/outer modes from input path") > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> > > diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c > index 815b38080401..d5ee96789d4b 100644 > --- a/net/xfrm/xfrm_input.c > +++ b/net/xfrm/xfrm_input.c > @@ -180,6 +180,8 @@ static int xfrm4_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb) > int optlen = 0; > int err = -EINVAL; > > + skb->protocol = htons(ETH_P_IP); > + > if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) { > struct ip_beet_phdr *ph; > int phlen; > @@ -232,6 +234,8 @@ static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb) > { > int err = -EINVAL; > > + skb->protocol = htons(ETH_P_IP); > + > if (!pskb_may_pull(skb, sizeof(struct iphdr))) > goto out; > > @@ -267,6 +271,8 @@ static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb) > { > int err = -EINVAL; > > + skb->protocol = htons(ETH_P_IPV6); > + > if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) > goto out; > > @@ -296,6 +302,8 @@ static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb) > int size = sizeof(struct ipv6hdr); > int err; > > + skb->protocol = htons(ETH_P_IPV6); > + > err = skb_cow_head(skb, size + skb->mac_len); > if (err) > goto out; > @@ -346,6 +354,7 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x, > return xfrm6_remove_tunnel_encap(x, skb); > break; > } > + return -EINVAL; > } > > WARN_ON_ONCE(1); > @@ -366,19 +375,6 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) > return -EAFNOSUPPORT; > } > > - switch (XFRM_MODE_SKB_CB(skb)->protocol) { > - case IPPROTO_IPIP: > - case IPPROTO_BEETPH: > - skb->protocol = htons(ETH_P_IP); > - break; > - case IPPROTO_IPV6: > - skb->protocol = htons(ETH_P_IPV6); > - break; > - default: > - WARN_ON_ONCE(1); > - break; > - } > - > return xfrm_inner_mode_encap_remove(x, skb); > } Reviewed-by: Maciej Żenczykowski <maze@google.com>
On Tue, Jul 04, 2023 at 08:53:49AM +0800, Herbert Xu wrote: > On Fri, Jun 30, 2023 at 08:37:58AM -0700, Maciej Żenczykowski wrote: > > Steffan, this isn't of course a patch meant for inclusion, instead just a WARN_ON hit report. > > The patch is simply what prints the following extra info: > > > > xfrm_prepare_input: XFRM_MODE_SKB_CB(skb)->protocol: 17 > > xfrm_inner_mode_encap_remove: x->props.mode: 1 XFRM_MODE_SKB_SB(skb)->protocol:17 > > > > (note: XFRM_MODE_TUNNEL=1 IPPROTO_UDP=17) > > Thanks for the report. This patch should fix the warnings: > > ---8<--- > After the elimination of inner modes, a couple of warnings that > were previously unreachable can now be triggered by malformed > inbound packets. > > Fix this by: > > 1. Moving the setting of skb->protocol into the decap functions. > 2. Returning -EINVAL when unexpected protocol is seen. > > Reported-by: Maciej Żenczykowski<maze@google.com> > Fixes: 5f24f41e8ea6 ("xfrm: Remove inner/outer modes from input path") > Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Applied, thanks a lot Herbert!
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 815b38080401..d5ee96789d4b 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -180,6 +180,8 @@ static int xfrm4_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb) int optlen = 0; int err = -EINVAL; + skb->protocol = htons(ETH_P_IP); + if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) { struct ip_beet_phdr *ph; int phlen; @@ -232,6 +234,8 @@ static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb) { int err = -EINVAL; + skb->protocol = htons(ETH_P_IP); + if (!pskb_may_pull(skb, sizeof(struct iphdr))) goto out; @@ -267,6 +271,8 @@ static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb) { int err = -EINVAL; + skb->protocol = htons(ETH_P_IPV6); + if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) goto out; @@ -296,6 +302,8 @@ static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb) int size = sizeof(struct ipv6hdr); int err; + skb->protocol = htons(ETH_P_IPV6); + err = skb_cow_head(skb, size + skb->mac_len); if (err) goto out; @@ -346,6 +354,7 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x, return xfrm6_remove_tunnel_encap(x, skb); break; } + return -EINVAL; } WARN_ON_ONCE(1); @@ -366,19 +375,6 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) return -EAFNOSUPPORT; } - switch (XFRM_MODE_SKB_CB(skb)->protocol) { - case IPPROTO_IPIP: - case IPPROTO_BEETPH: - skb->protocol = htons(ETH_P_IP); - break; - case IPPROTO_IPV6: - skb->protocol = htons(ETH_P_IPV6); - break; - default: - WARN_ON_ONCE(1); - break; - } - return xfrm_inner_mode_encap_remove(x, skb); }