Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934636AbcKMQa4 (ORCPT ); Sun, 13 Nov 2016 11:30:56 -0500 Received: from mail-it0-f54.google.com ([209.85.214.54]:36033 "EHLO mail-it0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933841AbcKMQaz (ORCPT ); Sun, 13 Nov 2016 11:30:55 -0500 Subject: Re: [PATCH] ip6_output: ensure flow saddr actually belongs to device To: "Jason A. Donenfeld" , Netdev , WireGuard mailing list , LKML , YOSHIFUJI Hideaki , Hannes Frederic Sowa References: <20161113132347.17907-1-Jason@zx2c4.com> From: David Ahern Message-ID: <405b2e79-854d-4c30-07b0-bd524137d2f6@cumulusnetworks.com> Date: Sun, 13 Nov 2016 09:30:15 -0700 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.4.0 MIME-Version: 1.0 In-Reply-To: <20161113132347.17907-1-Jason@zx2c4.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1440 Lines: 34 On 11/13/16 6:23 AM, Jason A. Donenfeld wrote: > This puts the IPv6 routing functions in parity with the IPv4 routing > functions. Namely, we now check in v6 that if a flowi6 requests an > saddr, the returned dst actually corresponds to a net device that has > that saddr. This mirrors the v4 logic with __ip_dev_find in > __ip_route_output_key_hash. In the event that the returned dst is not > for a dst with a dev that has the saddr, we return -EINVAL, just like > v4; this makes it easy to use the same error handlers for both cases. > > Signed-off-by: Jason A. Donenfeld > Cc: David Ahern > --- > net/ipv6/ip6_output.c | 5 +++++ > 1 file changed, 5 insertions(+) > > diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c > index 6001e78..a834129 100644 > --- a/net/ipv6/ip6_output.c > +++ b/net/ipv6/ip6_output.c > @@ -1011,6 +1011,11 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, > } > } > #endif > + if (!ipv6_addr_any(&fl6->saddr) && > + !ipv6_chk_addr(net, &fl6->saddr, (*dst)->dev, 1)) { > + err = -EINVAL; > + goto out_err_release; > + } > > return 0; You can't require the address to be on the dst device. e.g., it can be an address from the loopback/vrf device. This block needs to be done at function entry, and pass dev as NULL to mean is the address assigned to any interface. That gets you the equivalency of the IPv4 check.