On Wed, Jan 17, 2018 at 10:48 PM, Jason Wang <jasow...@redhat.com> wrote: > > > On 2018年01月18日 07:11, Willem de Bruijn wrote: >> >> From: Willem de Bruijn<will...@google.com> >> >> Validate gso_type of untrusted SKB_GSO_DODGY packets during >> segmentation. >> >> Untrusted user packets are limited to a small set of gso types in >> virtio_net_hdr_to_skb. But segmentation occurs on packet contents. >> Syzkaller was able to enter gso callbacks that are not hardened >> against untrusted user input. >> >> Fixes: f43798c27684 ("tun: Allow GSO using virtio_net_hdr") > > > This commit is suspicious, I guess it should be 5c7cdf339af5 ("gso: Remove > arbitrary checks for unsupported GSO")
The specific SCTP path was introduced with commit 90017accff61 ("sctp: add GSO support"). But the main issue that packets can be delivered to gso handlers different from their gso_type goes back further. The commit you reference is actually older than the sctp gso patch, so it makes sense that it did not have a check in the sctp_gso_segment. I still think that we should check in inet_gso_segment when we have the proto, instead of in each {tcp, sctp, udp, esp, ...} handler having a check of the form. !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) Note that the above commit also only had these checks in the TSO branch if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { but the case where this condition fails has to be protected just as well, so a revert of that patch + new tests in all handlers added since is not sufficient. >> Link:http://lkml.kernel.org/r/<001a1137452496ffc305617e5...@google.com> >> Reported-by:syzbot+fee64147a25aecd48...@syzkaller.appspotmail.com >> Signed-off-by: Willem de Bruijn<will...@google.com> >> --- >> net/ipv4/af_inet.c | 21 +++++++++++++++++++++ >> net/ipv6/ip6_offload.c | 23 ++++++++++++++++++++++- >> 2 files changed, 43 insertions(+), 1 deletion(-) >> >> diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c >> index f00499a46927..d5a36827f7b1 100644 >> --- a/net/ipv4/af_inet.c >> +++ b/net/ipv4/af_inet.c >> @@ -1220,6 +1220,25 @@ int inet_sk_rebuild_header(struct sock *sk) >> } >> EXPORT_SYMBOL(inet_sk_rebuild_header); >> +static bool inet_gso_validate_dodgy(struct sk_buff *skb, int ipproto) >> +{ >> + unsigned int gso_type = skb_shinfo(skb)->gso_type; >> + >> + if (gso_type & SKB_GSO_DODGY) { >> + switch (gso_type & ~SKB_GSO_DODGY) { >> + case SKB_GSO_TCPV4: >> + case SKB_GSO_TCPV4 | SKB_GSO_TCP_ECN: >> + return ipproto == IPPROTO_TCP; >> + case SKB_GSO_UDP: >> + return ipproto == IPPROTO_UDP; >> + default: >> + return false; >> + } >> + } >> + >> + return true; >> +} > > > This seems more strict than what was removed by 5c7cdf339af5. Any reason for > this? I'm asking since this probably work for virito-net but I'm not sure it > works for other sources. All sources are limited to the same VIRTIO_NET_HDR_GSO_.. types that virtio_net_hdr_to_skb supports, as far as I know.