Message ID | 20180110174510.138752-1-maloneykernel@gmail.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Series | [net] ipv6: fix udpv6 sendmsg crash caused by too small MTU | expand |
On Wed, 2018-01-10 at 12:45 -0500, Mike Maloney wrote: > From: Mike Maloney <maloney@google.com> > > The logic in __ip6_append_data() assumes that the MTU is at least large > enough for the headers. A device's MTU may be adjusted after being > added while sendmsg() is processing data, resulting in > __ip6_append_data() seeing any MTU. For an mtu smaller than the size of > the fragmentation header, the math results in a negative 'maxfraglen', > which causes problems when refragmenting any previous skb in the > skb_write_queue, leaving it possibly malformed. > > Instead sendmsg returns EINVAL when the mtu is calculated to be less > than IPV6_MIN_MTU. > > Reported-by: syzbot <syzkaller@googlegroups.com> > Signed-off-by: Mike Maloney <maloney@google.com> > > Reviewed-by: Eric Dumazet <edumazet@google.com>
From: Mike Maloney <maloneykernel@gmail.com> Date: Wed, 10 Jan 2018 12:45:10 -0500 > From: Mike Maloney <maloney@google.com> > > The logic in __ip6_append_data() assumes that the MTU is at least large > enough for the headers. A device's MTU may be adjusted after being > added while sendmsg() is processing data, resulting in > __ip6_append_data() seeing any MTU. For an mtu smaller than the size of > the fragmentation header, the math results in a negative 'maxfraglen', > which causes problems when refragmenting any previous skb in the > skb_write_queue, leaving it possibly malformed. > > Instead sendmsg returns EINVAL when the mtu is calculated to be less > than IPV6_MIN_MTU. ... > Reported-by: syzbot <syzkaller@googlegroups.com> > Signed-off-by: Mike Maloney <maloney@google.com> Applied and queued up for -stable, thank you.
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index f7dd51c42314..f309ce7120d0 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1206,14 +1206,16 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork, v6_cork->tclass = ipc6->tclass; if (rt->dst.flags & DST_XFRM_TUNNEL) mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(&rt->dst); + READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); else mtu = np->pmtudisc >= IPV6_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(rt->dst.path); + READ_ONCE(rt->dst.dev->mtu) : dst_mtu(rt->dst.path); if (np->frag_size < mtu) { if (np->frag_size) mtu = np->frag_size; } + if (mtu < IPV6_MIN_MTU) + return -EINVAL; cork->base.fragsize = mtu; if (dst_allfrag(rt->dst.path)) cork->base.flags |= IPCORK_ALLFRAG;