On Fri, 11 Jan 2019 04:55:52 -0800 Eric Dumazet <eduma...@google.com> wrote:
> Both gue_err() and gue6_err() incorrectly assume > linear skbs. Fix them to use pskb_may_pull(). Thanks for fixing this! I stupidly didn't suspect we could get non-linear skbs there. Just two things: > +++ b/net/ipv4/fou.c > @@ -1020,10 +1020,11 @@ static int gue_err(struct sk_buff *skb, u32 info) > { > int transport_offset = skb_transport_offset(skb); > struct guehdr *guehdr; > - size_t optlen; > + size_t len, optlen; > int ret; > > - if (skb->len < sizeof(struct udphdr) + sizeof(struct guehdr)) > + len = sizeof(struct udphdr) + sizeof(struct guehdr); > + if (!pskb_may_pull(skb, len)) > return -EINVAL; > > guehdr = (struct guehdr *)&udp_hdr(skb)[1]; > @@ -1058,6 +1059,10 @@ static int gue_err(struct sk_buff *skb, u32 info) > > optlen = guehdr->hlen << 2; > > + if (!pskb_may_pull(skb, len + optlen) ^ ) missing > + return -EINVAL; > + > + guehdr = (struct guehdr *)&udp_hdr(skb)[1]; > if (validate_gue_flags(guehdr, optlen)) > return -EINVAL; > > diff --git a/net/ipv6/fou6.c b/net/ipv6/fou6.c > index > 7da7bf3b7fe3953eeb60addfffd6687c4da582c4..320413af4890641e7199d7d7102e7d8c2794d557 > 100644 > --- a/net/ipv6/fou6.c > +++ b/net/ipv6/fou6.c > @@ -90,10 +90,11 @@ static int gue6_err(struct sk_buff *skb, struct > inet6_skb_parm *opt, > { > int transport_offset = skb_transport_offset(skb); > struct guehdr *guehdr; > - size_t optlen; > + size_t len, optlen; > int ret; > > - if (skb->len < sizeof(struct udphdr) + sizeof(struct guehdr)) > + len = sizeof(struct udphdr) + sizeof(struct guehdr); > + if (!pskb_may_pull(skb, len)) > return -EINVAL; > > guehdr = (struct guehdr *)&udp_hdr(skb)[1]; > @@ -128,6 +129,10 @@ static int gue6_err(struct sk_buff *skb, struct > inet6_skb_parm *opt, > > optlen = guehdr->hlen << 2; > > + if (!pskb_may_pull(skb, len + optlen) ^ ) missing > + return -EINVAL; > + > + guehdr = (struct guehdr *)&udp_hdr(skb)[1]; > if (validate_gue_flags(guehdr, optlen)) > return -EINVAL; > -- Stefano