Re: general protection fault in skb_segment
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
Date: 2018-01-16 20:33:16
Also in:
linux-sctp, lkml
On Tue, Jan 2, 2018 at 12:23 PM, Willem de Bruijn [off-list ref] wrote:
quoted
Actually, changes just to inet_gso_segment and ipv6_gso_segment will suffice: bool udpfrag = false, fixedid = false, gso_partial, encap; struct sk_buff *segs = ERR_PTR(-EINVAL); + unsigned int offset = 0, gso_type; const struct net_offload *ops; - unsigned int offset = 0; struct iphdr *iph; int proto, tot_len; int nhoff;@@ -1258,6 +1258,22 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb, skb_reset_transport_header(skb); + gso_type = skb_shinfo(skb)->gso_type; + if (gso_type & SKB_GSO_DODGY) { + switch (gso_type & (SKB_GSO_TCPV4 | SKB_GSO_UDP)) { + case SKB_GSO_TCPV4: + if (proto != IPPROTO_TCP) + goto out; + break; + case SKB_GSO_UDP: + if (proto != IPPROTO_UDP) + goto out; + break; + default: + goto out; + } + }and analogous for IPv6. For a real patch I would deduplicate this logic between them and move it to a separate helper function (in a header file, then).This approach would also need an skb->protocol check either in virtio_net_hdr_to_skb or skb_mac_gso_segment.
It turns out that all paths already call skb_probe_transport_header, which also does flow dissection, so has the necessary preconditions for dissection checked: skb->protocol and network header have been initialized. I posted http://patchwork.ozlabs.org/patch/861874/ which adds gso type and protocol tests based on that flow dissector pass. Flow dissection was short circuited when csum offload already set the transport header, so this does add a flow dissector call to gso packets in practice, even if the datapath is not new.