syzkaller wireguard key situation [was: Re: [PATCH net-next v2] net: WireGuard secure network tunnel]

Dmitry Vyukov dvyukov at google.com
Mon Feb 17 16:42:39 CET 2020


On Mon, Feb 17, 2020 at 4:19 PM Dmitry Vyukov <dvyukov at google.com> wrote:
>
> On Mon, Feb 17, 2020 at 12:44 PM Jason A. Donenfeld <Jason at zx2c4.com> wrote:
> >
> > Observation:
> >
> > It seems to be starting to synthesize packets sent to the wireguard
> > socket. These aren't the proper handshake packets generated internally
> > by that triangle commit, but rather ones that syzkaller creates
> > itself. That's why we have coverage on wg_receive, which otherwise
> > wouldn't be called from a userspace process, since syzbot is sending
> > its own packets to that function.
> >
> > However, the packets it generates aren't getting very far, failing all
> > of the tests in validate_header_len. None of those checks are at all
> > cryptographic, which means it should be able to hit those eventually.
> > Anything we should be doing to help it out? After it gets past that
> > check, it'll wind up in the handshake queue or the data queue, and
> > then (in theory) it should be rejected on a cryptographic basis. But
> > maybe syzbot will figure out how to crash it instead :-P.
>
> Looking into this.
>
> Found the program that gives wg_receive coverage:
>
> r0 = openat$tun(0xffffffffffffff9c,
> &(0x7f0000000080)='/dev/net/tun\x00', 0x88002, 0x0)
> ioctl$TUNSETIFF(r0, 0x400454ca, &(0x7f00000000c0)={'syzkaller1\x00',
> 0x420000015001})
> r1 = socket$netlink(0x10, 0x3, 0x0)
> ioctl$sock_inet_SIOCSIFADDR(r1, 0x8914,
> &(0x7f0000000140)={'syzkaller1\x00', {0x7, 0x0, @empty}})
> write$tun(r0, &(0x7f00000002c0)={@void, @val, @ipv4=@udp={{0x5, 0x4,
> 0x0, 0x0, 0x1c, 0x0, 0x0, 0x0, 0x11, 0x0, @remote, @broadcast}, {0x0,
> 0x4e21, 0x8}}}, 0x26)
>
> Checked that doing SIOCSIFADDR is also required, otherwise the packet
> does not reach wg_receive.


All packets we inject with standard means (syz_emit_ethernet) get
rejected on the following check:

static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
{
const struct iphdr *iph;
u32 len;

/* When the interface is in promisc. mode, drop all the crap
* that it receives, do not try to analyse it.
*/
if (skb->pkt_type == PACKET_OTHERHOST)
goto drop;

Even if we drop IFF_NAPI_FRAGS which diverges packets who-knows-where.

Somehow we need to get something other than PACKET_OTHERHOST...
Why is it dropping all remote packets?...
How do remote packets get into stack then?...


More information about the WireGuard mailing list