From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric Dumazet Subject: Re: [PATCH net] ipv6: fix udpv6 sendmsg crash caused by too small MTU Date: Wed, 10 Jan 2018 09:21:51 -0800 Message-ID: <1515604911.131759.23.camel@gmail.com> References: <20180110171013.129868-1-maloneykernel@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit Cc: Mike Maloney To: Mike Maloney , netdev@vger.kernel.org, davem@davemloft.net Return-path: Received: from mail-pg0-f65.google.com ([74.125.83.65]:36414 "EHLO mail-pg0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751205AbeAJRVy (ORCPT ); Wed, 10 Jan 2018 12:21:54 -0500 Received: by mail-pg0-f65.google.com with SMTP id j2so10119346pgv.3 for ; Wed, 10 Jan 2018 09:21:53 -0800 (PST) In-Reply-To: <20180110171013.129868-1-maloneykernel@gmail.com> Sender: netdev-owner@vger.kernel.org List-ID: On Wed, 2018-01-10 at 12:10 -0500, Mike Maloney wrote: > From: Mike Maloney > > 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 > --- 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;