D'oh - resending with fixes. Thanks Eric.
On Wed, Jan 10, 2018 at 12:21 PM, Eric Dumazet <eric.duma...@gmail.com> wrote: > On Wed, 2018-01-10 at 12:10 -0500, Mike Maloney wrote: >> From: Mike Maloney <malo...@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. >> > > You forgot your SOB > >> Reported-by: syzbot <syzkal...@googlegroups.com> >> --- > > Also please add after this '---' marker that your patch depends on my > prior fix ( https://patchwork.ozlabs.org/patch/858234/ > ipv6: fix possible mem leaks in ipv6_make_skb() ) > > ( Or we leak a dst reference ) > > We probably should have sent a patch series. > > Thanks. > >> net/ipv6/ip6_output.c | 6 ++++-- >> 1 file changed, 4 insertions(+), 2 deletions(-) >> >> 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;