On Wed, Oct 7, 2020 at 9:22 PM Cong Wang <xiyou.wangc...@gmail.com> wrote: > > GRE tunnel has its own header_ops, ipgre_header_ops, and sets it > conditionally. When it is set, it assumes the outer IP header is > already created before ipgre_xmit(). > > This is not true when we send packets through a raw packet socket, > where L2 headers are supposed to be constructed by user. Packet > socket calls dev_validate_header() to validate the header. But > GRE tunnel does not set dev->hard_header_len, so that check can > be simply bypassed, therefore uninit memory could be passed down > to ipgre_xmit().
If dev->hard_header_len is zero, the packet socket will not reserve room for the link layer header, so skb->data points to network_header. But I don't see any uninitialized packet data? > Fix this by setting dev->hard_header_len whenever sets header_ops, > as dev->hard_header_len is supposed to be the length of the header > created by dev->header_ops->create() anyway. Agreed. Xie has made similar changes to lapbether recently in commit c7ca03c216ac. > Reported-and-tested-by: syzbot+4a2c52677a8a1aa28...@syzkaller.appspotmail.com > Cc: William Tu <u9012...@gmail.com> > Cc: Willem de Bruijn <willemdebruijn.ker...@gmail.com> > Signed-off-by: Cong Wang <xiyou.wangc...@gmail.com> > --- > net/ipv4/ip_gre.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c > index 4e31f23e4117..43b62095559e 100644 > --- a/net/ipv4/ip_gre.c > +++ b/net/ipv4/ip_gre.c > @@ -987,10 +987,12 @@ static int ipgre_tunnel_init(struct net_device *dev) > return -EINVAL; > dev->flags = IFF_BROADCAST; > dev->header_ops = &ipgre_header_ops; > + dev->hard_header_len = tunnel->hlen + sizeof(*iph); > } > #endif > } else if (!tunnel->collect_md) { > dev->header_ops = &ipgre_header_ops; > + dev->hard_header_len = tunnel->hlen + sizeof(*iph); Unrelated to this patch, I do wonder if ipgre_header does the right thing when tunnel->hlen > sizeof(gre_base_hdr), i.e., for gre tunnels with optional fields. Currently it appears to not initialize those. > } > > return ip_tunnel_init(dev); > -- > 2.28.0 >