[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAF=yD-+Ynn+t0dPJXUrXKQ2XMdtiKz8t6PKJUMNqeydYv=yG9A@mail.gmail.com>
Date: Sat, 30 Dec 2017 08:42:41 +0100
From: Willem de Bruijn <willemdebruijn.kernel@...il.com>
To: syzbot <syzbot+fee64147a25aecd48055@...kaller.appspotmail.com>
Cc: David Miller <davem@...emloft.net>,
LKML <linux-kernel@...r.kernel.org>, linux-sctp@...r.kernel.org,
Network Development <netdev@...r.kernel.org>,
nhorman@...driver.com, syzkaller-bugs@...glegroups.com,
vyasevich@...il.com, marcelo.leitner@...il.com
Subject: Re: general protection fault in skb_segment
> syzkaller hit the following crash on
> 37759fa6d0fa9e4d6036d19ac12f555bfc0aeafd
> git://git.cmpxchg.org/linux-mmots.git/master
> compiler: gcc (GCC) 7.1.1 20170620
> .config is attached
> Raw console output is attached.
> C reproducer is attached
> syzkaller reproducer is attached. See https://goo.gl/kgGztJ
> for information about syzkaller reproducers
Reproduced with the C reproducer on v4.15-rc1 and mainline
going back at least to v4.8, but not v4.7. SCTP GSO was
introduced in v4.8-rc1, so a patch in this set is likely the starting
point. Indeed crashes at 90017accff61 ("sctp: Add GSO support"),
but not at 90017accff61~4.
The reproducer with its sandbox removed shows this invocation in strace -f
# strace -f ./repro2
[... skipped ...]
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
open("/dev/net/tun", O_RDONLY) = 4
fcntl(4, F_DUPFD, 3) = 5
socket(PF_PACKET, SOCK_RAW|SOCK_CLOEXEC, 8) = 6
ioctl(4, TUNSETIFF, 0x20e63000) = 0
ioctl(3, SIOCSIFFLAGS, {ifr_name="syz0",
ifr_flags=IFF_UP|IFF_PROMISC|IFF_ALLMULTI}) = 0
setsockopt(6, SOL_PACKET, 0xf /* PACKET_??? */, [4096], 4) = 0
ioctl(6, SIOCGIFINDEX, {ifr_name="syz0", ifr_index=24}) = 0
bind(6, {sa_family=AF_PACKET, proto=0000, if24, pkttype=PACKET_HOST,
addr(6)={1, aaaaaaaaaa00}, 20) = 0
dup2(6, 5) = 5
write(5, "\0\201\1\0\350\367\0\0\3\0E\364\0 \0d\0\0\7\2042\342\0\0\0
\177\0\0\1\0\t"..., 42
where 0xf in setsockopt is PACKET_VNET_HDR
So this is a packet socket writing something that apparently looks
like an SCTP packet, is only 42 bytes long, but has GSO set in its
virtio_net_hdr struct.
It crashes in skb_segment seemingly on a NULL list_skb.
(gdb) list *(skb_segment+0x2a4)
0xffffffff8167cc24 is in skb_segment (net/core/skbuff.c:3566).
3561 if (hsize < 0)
3562 hsize = 0;
3563 if (hsize > len || !sg)
3564 hsize = len;
3565
3566 if (!hsize && i >= nfrags && skb_headlen(list_skb) &&
3567 (skb_headlen(list_skb) == len || sg)) {
3568 BUG_ON(skb_headlen(list_skb) > len);
3569
3570 i = 0;
Likely there is a hidden assumption about SCTP GSO packets that does
not hold for such packets generated by PF_PACKET.
SCTP GSO introduced the GSO_BY_FRAGS mss value, so the code
takes a different path for SCTP packets generated by the SCTP stack.
PF_PACKET does not necessarily set gso_size to GSO_BY_FRAGS, so
does not take the branch that requires list_skb to be non-zero here:
if (unlikely(mss == GSO_BY_FRAGS)) {
len = list_skb->len;
} else {
len = head_skb->len - offset;
if (len > mss)
len = mss;
}
hsize = skb_headlen(head_skb) - offset;
if (hsize < 0)
hsize = 0;
if (hsize > len || !sg)
hsize = len;
if (!hsize && i >= nfrags && skb_headlen(list_skb) &&
(skb_headlen(list_skb) == len || sg)) {
Somewhat tangential, but any PF_PACKET socket can set this
magic gso_size value in its virtio_net_hdr, so if it is assumed to
be an SCTP GSO specific option, setting it for a TCP GSO packet
may also cause unexpected results.
The crash requires a kernel with CONFIG_IP_SCTP enabled.
Powered by blists - more mailing lists