Netdev List
 help / color / mirror / Atom feed
* [PATCH net] tcp: avoid fastopen API to be used on AF_UNSPEC
From: Wei Wang @ 2017-05-24 16:59 UTC (permalink / raw)
  To: David Miller, netdev; +Cc: Yuchung Cheng, Vegard Nossum, Eric Dumazet, Wei Wang

From: Wei Wang <weiwan@google.com>

Fastopen API should be used to perform fastopen operations on the TCP
socket. It does not make sense to use fastopen API to perform disconnect
by calling it with AF_UNSPEC. The fastopen data path is also prone to
race conditions and bugs when using with AF_UNSPEC.

One issue reported and analyzed by Vegard Nossum is as follows:
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Thread A:                            Thread B:
------------------------------------------------------------------------
sendto()
 - tcp_sendmsg()
     - sk_stream_memory_free() = 0
         - goto wait_for_sndbuf
	     - sk_stream_wait_memory()
	        - sk_wait_event() // sleep
          |                          sendto(flags=MSG_FASTOPEN, dest_addr=AF_UNSPEC)
	  |                           - tcp_sendmsg()
	  |                              - tcp_sendmsg_fastopen()
	  |                                 - __inet_stream_connect()
	  |                                    - tcp_disconnect() //because of AF_UNSPEC
	  |                                       - tcp_transmit_skb()// send RST
	  |                                    - return 0; // no reconnect!
	  |                           - sk_stream_wait_connect()
	  |                                 - sock_error()
	  |                                    - xchg(&sk->sk_err, 0)
	  |                                    - return -ECONNRESET
	- ... // wake up, see sk->sk_err == 0
    - skb_entail() on TCP_CLOSE socket

If the connection is reopened then we will send a brand new SYN packet
after thread A has already queued a buffer. At this point I think the
socket internal state (sequence numbers etc.) becomes messed up.

When the new connection is closed, the FIN-ACK is rejected because the
sequence number is outside the window. The other side tries to
retransmit,
but __tcp_retransmit_skb() calls tcp_trim_head() on an empty skb which
corrupts the skb data length and hits a BUG() in copy_and_csum_bits().
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Hence, this patch adds a check for AF_UNSPEC in the fastopen data path
and return EOPNOTSUPP to user if such case happens.

Fixes: cf60af03ca4e7 ("tcp: Fast Open client - sendmsg(MSG_FASTOPEN)")
Reported-by: Vegard Nossum <vegard.nossum@oracle.com>
Signed-off-by: Wei Wang <weiwan@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/tcp.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 60203f1c793e..fea7c4f2d36c 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1161,9 +1161,12 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct inet_sock *inet = inet_sk(sk);
+	struct sockaddr *uaddr = msg->msg_name;
 	int err, flags;
 
-	if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE))
+	if (!(sysctl_tcp_fastopen & TFO_CLIENT_ENABLE) ||
+	    (uaddr && msg->msg_namelen >= sizeof(uaddr->sa_family) &&
+	     uaddr->sa_family == AF_UNSPEC))
 		return -EOPNOTSUPP;
 	if (tp->fastopen_req)
 		return -EALREADY; /* Another Fast Open is in progress */
@@ -1185,7 +1188,7 @@ static int tcp_sendmsg_fastopen(struct sock *sk, struct msghdr *msg,
 		}
 	}
 	flags = (msg->msg_flags & MSG_DONTWAIT) ? O_NONBLOCK : 0;
-	err = __inet_stream_connect(sk->sk_socket, msg->msg_name,
+	err = __inet_stream_connect(sk->sk_socket, uaddr,
 				    msg->msg_namelen, flags, 1);
 	/* fastopen_req could already be freed in __inet_stream_connect
 	 * if the connection times out or gets rst
-- 
2.13.0.219.gdb65acc882-goog

^ permalink raw reply related

* Re: [PATCH v2] drivers: phy: Add Cortina CS4340 driver
From: Florian Fainelli @ 2017-05-24 17:02 UTC (permalink / raw)
  To: Bogdan Purcareata, Andrew Lunn
  Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <DB5PR04MB124053B977F50D4A68C99D7BEAFE0@DB5PR04MB1240.eurprd04.prod.outlook.com>

On 05/24/2017 07:34 AM, Bogdan Purcareata wrote:
>> You should do that as well.
> 
> Okay, I will include this check in a probe function in v3.

When you do so, can you change the subject to be net: phy: Add Cortina
CS4340 driver for the driver, and use dt-bindings: net:  for the Device
Tree binding patch?

Thanks!
-- 
Florian

^ permalink raw reply

* RE: [PATCH v2] drivers: phy: Add Cortina CS4340 driver
From: Bogdan Purcareata @ 2017-05-24 17:04 UTC (permalink / raw)
  To: Florian Fainelli, Andrew Lunn
  Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <1c7a1799-7b76-6e1d-5050-b4abb7855a94@gmail.com>

> -----Original Message-----
> From: Florian Fainelli [mailto:f.fainelli@gmail.com]
> Sent: Wednesday, May 24, 2017 8:03 PM
> To: Bogdan Purcareata <bogdan.purcareata@nxp.com>; Andrew Lunn
> <andrew@lunn.ch>
> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: Re: [PATCH v2] drivers: phy: Add Cortina CS4340 driver
> 
> On 05/24/2017 07:34 AM, Bogdan Purcareata wrote:
> >> You should do that as well.
> >
> > Okay, I will include this check in a probe function in v3.
> 
> When you do so, can you change the subject to be net: phy: Add Cortina
> CS4340 driver for the driver, and use dt-bindings: net:  for the Device
> Tree binding patch?

Will do, thanks!
Bogdan

^ permalink raw reply

* Re: [PATCH] nfc: Ensure presence of required attributes in the activate_target netlink handler
From: Kees Cook @ 2017-05-24 17:05 UTC (permalink / raw)
  To: Mateusz Jurczyk
  Cc: Samuel Ortiz, David S. Miller, linux-wireless,
	Network Development, LKML,
	security-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
In-Reply-To: <20170524104226.14841-1-mjurczyk-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>

On Wed, May 24, 2017 at 3:42 AM, Mateusz Jurczyk <mjurczyk-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org> wrote:
> Check that the NFC_ATTR_TARGET_INDEX and NFC_ATTR_PROTOCOLS attributes (in
> addition to NFC_ATTR_DEVICE_INDEX) are provided by the netlink client
> prior to accessing them. This prevents potential unhandled NULL pointer
> dereference exceptions which can be triggered by malicious user-mode
> programs, if they omit one or both of these attributes.
>
> Signed-off-by: Mateusz Jurczyk <mjurczyk-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>

Acked-by: Kees Cook <keescook-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

-Kees

> ---
>  net/nfc/netlink.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
> index 6b0850e63e09..b251fb936a27 100644
> --- a/net/nfc/netlink.c
> +++ b/net/nfc/netlink.c
> @@ -907,7 +907,9 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
>         u32 device_idx, target_idx, protocol;
>         int rc;
>
> -       if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
> +       if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
> +           !info->attrs[NFC_ATTR_TARGET_INDEX] ||
> +           !info->attrs[NFC_ATTR_PROTOCOLS])
>                 return -EINVAL;
>
>         device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
> --
> 2.13.0.219.gdb65acc882-goog
>



-- 
Kees Cook
Pixel Security

^ permalink raw reply

* Re: Deleting a dynamic mac entry..
From: Manohar Kumar @ 2017-05-24 18:05 UTC (permalink / raw)
  To: Toshiaki Makita; +Cc: netdev, bridge
In-Reply-To: <e6143108-3eb4-6f6a-c58b-857722f706b9@lab.ntt.co.jp>

Thanks, Toshiaki.

What is the right way to set the default_pvid using the bridge command
? I tried this, which fails..

root@net-3:~# ip link set dev vxlan0 name untagged type vlan id 0
RTNETLINK answers: Operation not supported
root@net-3:~#

All the interfaces in the bridge are untagged.

thanks,
Manohar.


On Mon, May 22, 2017 at 8:17 PM, Toshiaki Makita
<makita.toshiaki@lab.ntt.co.jp> wrote:
> On 2017/05/21 11:28, Manohar Kumar wrote:
>> Hello,
>>
>> In 3.19 the following bridge fdb command to delete a dynamically
>> learned entry fails..
>>
>> root@net-3:~# bridge fdb show | grep 02:42:0a:ff:00:06
>> 02:42:0a:ff:00:06 dev vxlan0 master br0
>> root@net-3:~# bridge fdb del 02:42:0a:ff:00:06 dev vxlan0 master
>> RTNETLINK answers: No such file or directory
>>
>> It works in 4.4.
>>
>> Can someone please point to the patch that made this change ?
>
> 25d3b493a52d ("bridge: Fix inability to add non-vlan fdb entry") might
> be what you are looking for, but you might want to do git-bisect to
> track down any regression or fix.
>
>> In kernels without this patch is there an alternative to delete
>> (actually I want to do it programmatically) dynamic mac entries ?
>
> If 25d3b493a52d is causing your problem, set default_pvid to 0 in order
> to disable default_pvid, and delete any vlans which is already
> configured in bridge's vlan_filtering. Then, delete the fdb entry.
>
> Toshiaki Makita
>

^ permalink raw reply

* Re: [PATCH v4 next 0/3] modules: automatic module loading restrictions
From: Djalal Harouni @ 2017-05-24 18:06 UTC (permalink / raw)
  To: Solar Designer
  Cc: Kees Cook, linux-kernel, Network Development, LSM List,
	kernel-hardening@lists.openwall.com, Andy Lutomirski,
	Andrew Morton, Rusty Russell, Serge E. Hallyn, Jessica Yu,
	David S. Miller, James Morris, Paul Moore, Stephen Smalley,
	Greg Kroah-Hartman, Tetsuo Handa, Ingo Molnar, Linux API,
	Dongsu Park, Casey Schaufler, Jonathan Corbet, Arn
In-Reply-To: <20170523074808.GA4562@openwall.com>

On Tue, May 23, 2017 at 9:48 AM, Solar Designer <solar@openwall.com> wrote:
>> >>> On Mon, May 22, 2017 at 2:08 PM, Solar Designer <solar@openwall.com> wrote:
>> >>> > On Mon, May 22, 2017 at 01:57:03PM +0200, Djalal Harouni wrote:
>> >>> >> *) When modules_autoload_mode is set to (2), automatic module loading is
>> >>> >> disabled for all. Once set, this value can not be changed.
>> >>> >
>> >>> > What purpose does this securelevel-like property ("Once set, this value
>> >>> > can not be changed.") serve here?  I think this mode 2 is needed, but
>> >>> > without this extra property, which is bypassable by e.g. explicitly
>> >>> > loaded kernel modules anyway (and that's OK).
>
> On Mon, May 22, 2017 at 04:07:56PM -0700, Kees Cook wrote:
>> I'm on the fence. For modules_disabled and Yama, it was tied to
>> CAP_SYS_ADMIN, basically designed to be a at-boot setting that could
>> not later be undone by an attacker gaining that privilege, keeping
>> them out of either kernel memory or existing user process memory.
>> Here, it's CAP_SYS_MODULE... it's hard to imagine the situation where
>> a CAP_SYS_MODULE-capable process could write to this sysctl but NOT
>> issue direct modprobe requests, but it's _possible_ via crazy symlink
>> games to trick capable processes into writing to sysctls. We've seen
>> this multiple times before, and it's a way for attackers to turn a
>> single privileged write into a privileged exec.
>
> OK, tricking a process via crazy symlink games is finally a potentially
> valid reason.  The question then becomes: are there perhaps so many
> other important sysctl's, disk files, etc. (which the vulnerable capable
> process could similarly be tricked into writing) so that specifically
> resetting modules_autoload_mode isn't particularly lucrative?  I think
> that the answer to that is usually yes.  Another related question: do we
> really want to inconsistently single out a handful of sysctl's for this
> kind of extra protection?  I think not.
>
> I agree there are some other settings where being unable to reset them
> makes sense, but I think this isn't one of those.
>

Alright, I already replied to Andy, since it was requested I will drop
it. I definitely prefer that we have something merged and usable ;-)


>> I might turn the question around, though: why would we want to have it
>> changeable at this setting?
>
> Convenience for the sysadmin - being able to correct one's error (e.g.,
> wrong order of shell commands), respond to new findings (thought module
> autoloading was unneeded after some point, then found out some software
> relies on it), change one's mind, reuse a system differently than
> originally intended without a forced reboot.
>
>> I'm fine leaving that piece off, either way.
>
> I'm also fine with either decision.  I just thought I'd point out what
> looked weird to me.
>
> I think this is an important patch that should get in, but primarily
> for modules_autoload_mode=1, which many distros could make the default
> (and maybe the kernel eventually should?)

I do not think that desktop, or interactive systems will set it.
Ubuntu has snaps for their app store, and they can use the per-task
flag and other vendors too Flatpak, etc.


> For modules_autoload_mode=2, we already seem to have the equivalent of
> modprobe=/bin/true (or does it differ subtly, maybe in return values?),
> which I already use at startup on a GPU box like this (preloading
> modules so that the OpenCL backends wouldn't need the autoloading):
>
> nvidia-smi
> nvidia-modprobe -u -c=0
> #modprobe nvidia_uvm
> #modprobe fglrx
>
> sysctl -w kernel.modprobe=/bin/true
> sysctl -w kernel.hotplug=/bin/true
>
> but it's good to also have this supported more explicitly and more
> consistently through modules_autoload_mode=2 while we're at it.  So I
> support having this mode as well.  I just question the need to have it
> non-resettable.
>

Ok, yes with mode=2 it is clear interface, it logs what was denied, it
is consistent with the per-task flag that we want for sandboxes and
desktop, it will work with CONFIG_STATIC_USERMODEHELPER, more
importantly it will avoid doing the usermod upcall, even if one day
the kernel support upcall into namespaces, I'm pretty sure that no one
will like the idea of namespaced modprobe paths, modules are global
anyway, this allows to say we are safe by default from any future
change that may make an upcall into the wrong context, we just avoid
that.


-- 
tixxdz

^ permalink raw reply

* [PATCH net-next 0/8] net: extend RTM_GETROUTE to return fib result
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay

From: Roopa Prabhu <roopa@cumulusnetworks.com>

This series adds a new RTM_F_FIB_MATCH flag to return matched fib result
with RTM_GETROUTE. This is useful for applications and protocols in
userspace wanting to query the selected route.

examples (with patched iproute2):
ipv4:
----
$ip route show
default via 192.168.0.2 dev eth0
10.0.14.0/24
        nexthop via 172.16.0.3  dev dummy0 weight 1
        nexthop via 172.16.1.3  dev dummy1 weight 1

$ip route get 10.0.14.2
10.0.14.2 via 172.16.1.3 dev dummy1  src 172.16.1.1 
    cache 

$ip route get fibmatch 10.0.14.2
10.0.14.0/24
        nexthop via 172.16.0.3  dev dummy0 weight 1
        nexthop via 172.16.1.3  dev dummy1 weight 1

ipv6:
----
$ip -6 route show
2001:db9:100::/120  metric 1024 
        nexthop via 2001:db8:2::2  dev dummy0 weight 1
        nexthop via 2001:db8:12::2  dev dummy1 weight 1

$ip -6 route get 2001:db9:100::1
2001:db9:100::1 from :: via 2001:db8:12::2 dev dummy1  src 2001:db8:12::1  metric 1024  pref medium

$ip -6 route get fibmatch 2001:db9:100::1
2001:db9:100::/120  metric 1024 
        nexthop via 2001:db8:12::2  dev dummy1 weight 1
        nexthop via 2001:db8:2::2  dev dummy0 weight 1


David Ahern (5):
  net: ipv4: refactor __ip_route_output_key_hash
  net: ipv4: refactor ip_route_input_noref
  net: ipv4: Remove event arg to rt_fill_info
  net: ipv4: Convert inet_rtm_getroute to rcu versions of route lookup
  net: ipv4: Save trie prefix to fib lookup result

Roopa Prabhu (3):
  net: ipv4: add new RTM_F_FIB_MATCH flag for use with RTM_GETROUTE
  net: ipv4: RTM_GETROUTE: return matched fib result when requested
  net: ipv6: RTM_GETROUTE: return matched fib result when requested

 include/net/ip_fib.h           |   1 +
 include/net/route.h            |  10 ++-
 include/uapi/linux/rtnetlink.h |   1 +
 net/ipv4/fib_trie.c            |   1 +
 net/ipv4/icmp.c                |   2 +-
 net/ipv4/route.c               | 160 ++++++++++++++++++++++++-----------------
 net/ipv6/route.c               |  11 ++-
 7 files changed, 116 insertions(+), 70 deletions(-)

-- 
1.9.1

^ permalink raw reply

* [PATCH net-next 2/8] net: ipv4: refactor ip_route_input_noref
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-1-git-send-email-roopa@cumulusnetworks.com>

From: David Ahern <dsahern@gmail.com>

A later patch wants access to the fib result on an input route lookup
with the rcu lock held. Refactor ip_route_input_noref pushing the logic
between rcu_read_lock ... rcu_read_unlock into a new helper that takes
the fib_result as an input arg.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 include/net/route.h |  3 +++
 net/ipv4/route.c    | 66 ++++++++++++++++++++++++++++++-----------------------
 2 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/include/net/route.h b/include/net/route.h
index 5a92347..8d209ad 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -180,6 +180,9 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4
 
 int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src,
 			 u8 tos, struct net_device *devin);
+int ip_route_input_rcu(struct sk_buff *skb, __be32 dst, __be32 src,
+		       u8 tos, struct net_device *devin,
+		       struct fib_result *res);
 
 static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src,
 				 u8 tos, struct net_device *devin)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index f787208..fe7b765 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1852,9 +1852,9 @@ static int ip_mkroute_input(struct sk_buff *skb,
  */
 
 static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
-			       u8 tos, struct net_device *dev)
+			       u8 tos, struct net_device *dev,
+			       struct fib_result *res)
 {
-	struct fib_result res;
 	struct in_device *in_dev = __in_dev_get_rcu(dev);
 	struct ip_tunnel_info *tun_info;
 	struct flowi4	fl4;
@@ -1884,8 +1884,8 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	if (ipv4_is_multicast(saddr) || ipv4_is_lbcast(saddr))
 		goto martian_source;
 
-	res.fi = NULL;
-	res.table = NULL;
+	res->fi = NULL;
+	res->table = NULL;
 	if (ipv4_is_lbcast(daddr) || (saddr == 0 && daddr == 0))
 		goto brd_input;
 
@@ -1921,17 +1921,17 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	fl4.daddr = daddr;
 	fl4.saddr = saddr;
 	fl4.flowi4_uid = sock_net_uid(net, NULL);
-	err = fib_lookup(net, &fl4, &res, 0);
+	err = fib_lookup(net, &fl4, res, 0);
 	if (err != 0) {
 		if (!IN_DEV_FORWARD(in_dev))
 			err = -EHOSTUNREACH;
 		goto no_route;
 	}
 
-	if (res.type == RTN_BROADCAST)
+	if (res->type == RTN_BROADCAST)
 		goto brd_input;
 
-	if (res.type == RTN_LOCAL) {
+	if (res->type == RTN_LOCAL) {
 		err = fib_validate_source(skb, saddr, daddr, tos,
 					  0, dev, in_dev, &itag);
 		if (err < 0)
@@ -1943,10 +1943,10 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 		err = -EHOSTUNREACH;
 		goto no_route;
 	}
-	if (res.type != RTN_UNICAST)
+	if (res->type != RTN_UNICAST)
 		goto martian_destination;
 
-	err = ip_mkroute_input(skb, &res, in_dev, daddr, saddr, tos);
+	err = ip_mkroute_input(skb, res, in_dev, daddr, saddr, tos);
 out:	return err;
 
 brd_input:
@@ -1960,14 +1960,14 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 			goto martian_source;
 	}
 	flags |= RTCF_BROADCAST;
-	res.type = RTN_BROADCAST;
+	res->type = RTN_BROADCAST;
 	RT_CACHE_STAT_INC(in_brd);
 
 local_input:
 	do_cache = false;
-	if (res.fi) {
+	if (res->fi) {
 		if (!itag) {
-			rth = rcu_dereference(FIB_RES_NH(res).nh_rth_input);
+			rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input);
 			if (rt_cache_valid(rth)) {
 				skb_dst_set_noref(skb, &rth->dst);
 				err = 0;
@@ -1978,7 +1978,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	}
 
 	rth = rt_dst_alloc(l3mdev_master_dev_rcu(dev) ? : net->loopback_dev,
-			   flags | RTCF_LOCAL, res.type,
+			   flags | RTCF_LOCAL, res->type,
 			   IN_DEV_CONF_GET(in_dev, NOPOLICY), false, do_cache);
 	if (!rth)
 		goto e_nobufs;
@@ -1988,18 +1988,18 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	rth->dst.tclassid = itag;
 #endif
 	rth->rt_is_input = 1;
-	if (res.table)
-		rth->rt_table_id = res.table->tb_id;
+	if (res->table)
+		rth->rt_table_id = res->table->tb_id;
 
 	RT_CACHE_STAT_INC(in_slow_tot);
-	if (res.type == RTN_UNREACHABLE) {
+	if (res->type == RTN_UNREACHABLE) {
 		rth->dst.input= ip_error;
 		rth->dst.error= -err;
 		rth->rt_flags 	&= ~RTCF_LOCAL;
 	}
 
 	if (do_cache) {
-		struct fib_nh *nh = &FIB_RES_NH(res);
+		struct fib_nh *nh = &FIB_RES_NH(*res);
 
 		rth->dst.lwtstate = lwtstate_get(nh->nh_lwtstate);
 		if (lwtunnel_input_redirect(rth->dst.lwtstate)) {
@@ -2019,9 +2019,9 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
 no_route:
 	RT_CACHE_STAT_INC(in_no_route);
-	res.type = RTN_UNREACHABLE;
-	res.fi = NULL;
-	res.table = NULL;
+	res->type = RTN_UNREACHABLE;
+	res->fi = NULL;
+	res->table = NULL;
 	goto local_input;
 
 	/*
@@ -2051,11 +2051,22 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 			 u8 tos, struct net_device *dev)
 {
-	int res;
+	struct fib_result res;
+	int err;
 
 	tos &= IPTOS_RT_MASK;
 	rcu_read_lock();
+	err = ip_route_input_rcu(skb, daddr, saddr, tos, dev, &res);
+	rcu_read_unlock();
 
+	return err;
+}
+EXPORT_SYMBOL(ip_route_input_noref);
+
+/* called with rcu_read_lock held */
+int ip_route_input_rcu(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+		       u8 tos, struct net_device *dev, struct fib_result *res)
+{
 	/* Multicast recognition logic is moved from route cache to here.
 	   The problem was that too many Ethernet cards have broken/missing
 	   hardware multicast filters :-( As result the host on multicasting
@@ -2070,6 +2081,7 @@ int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 	if (ipv4_is_multicast(daddr)) {
 		struct in_device *in_dev = __in_dev_get_rcu(dev);
 		int our = 0;
+		int err = -EINVAL;
 
 		if (in_dev)
 			our = ip_check_mc_rcu(in_dev, daddr, saddr,
@@ -2085,7 +2097,6 @@ int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 						      ip_hdr(skb)->protocol);
 		}
 
-		res = -EINVAL;
 		if (our
 #ifdef CONFIG_IP_MROUTE
 			||
@@ -2093,17 +2104,14 @@ int ip_route_input_noref(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 		     IN_DEV_MFORWARD(in_dev))
 #endif
 		   ) {
-			res = ip_route_input_mc(skb, daddr, saddr,
+			err = ip_route_input_mc(skb, daddr, saddr,
 						tos, dev, our);
 		}
-		rcu_read_unlock();
-		return res;
+		return err;
 	}
-	res = ip_route_input_slow(skb, daddr, saddr, tos, dev);
-	rcu_read_unlock();
-	return res;
+
+	return ip_route_input_slow(skb, daddr, saddr, tos, dev, res);
 }
-EXPORT_SYMBOL(ip_route_input_noref);
 
 /* called with rcu_read_lock() */
 static struct rtable *__mkroute_output(const struct fib_result *res,
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next 1/8] net: ipv4: refactor __ip_route_output_key_hash
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-1-git-send-email-roopa@cumulusnetworks.com>

From: David Ahern <dsahern@gmail.com>

A later patch wants access to the fib result on an output route lookup
with the rcu lock held. Refactor __ip_route_output_key_hash, pushing
the logic between rcu_read_lock ... rcu_read_unlock into a new helper
that takes the fib_result as an input arg.

To keep the name length under control remove the leading underscores
from the name. _rcu is added to the name of the new helper indicating
it is called with the rcu read lock held.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 include/net/route.h |  7 ++++++-
 net/ipv4/icmp.c     |  2 +-
 net/ipv4/route.c    | 57 +++++++++++++++++++++++++++++++----------------------
 3 files changed, 40 insertions(+), 26 deletions(-)

diff --git a/include/net/route.h b/include/net/route.h
index 2cc0e14..5a92347 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -115,11 +115,16 @@ struct rt_cache_stat {
 void rt_flush_dev(struct net_device *dev);
 struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *flp,
 					  const struct sk_buff *skb);
+struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *flp,
+					const struct sk_buff *skb);
+struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *flp,
+					    const struct sk_buff *skb,
+					    struct fib_result *res);
 
 static inline struct rtable *__ip_route_output_key(struct net *net,
 						   struct flowi4 *flp)
 {
-	return __ip_route_output_key_hash(net, flp, NULL);
+	return ip_route_output_key_hash(net, flp, NULL);
 }
 
 struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 43318b5..5610971 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -489,7 +489,7 @@ static struct rtable *icmp_route_lookup(struct net *net,
 	fl4->flowi4_oif = l3mdev_master_ifindex(skb_dst(skb_in)->dev);
 
 	security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4));
-	rt = __ip_route_output_key_hash(net, fl4, skb_in);
+	rt = ip_route_output_key_hash(net, fl4, skb_in);
 	if (IS_ERR(rt))
 		return rt;
 
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 655d9ee..f787208 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2246,29 +2246,22 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
  * Major route resolver routine.
  */
 
-struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
-					  const struct sk_buff *skb)
+struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
+					    const struct sk_buff *skb,
+					    struct fib_result *res)
 {
 	struct net_device *dev_out = NULL;
+	int orig_oif = fl4->flowi4_oif;
 	__u8 tos = RT_FL_TOS(fl4);
 	unsigned int flags = 0;
-	struct fib_result res;
-	struct rtable *rth;
-	int orig_oif;
 	int err = -ENETUNREACH;
-
-	res.tclassid	= 0;
-	res.fi		= NULL;
-	res.table	= NULL;
-
-	orig_oif = fl4->flowi4_oif;
+	struct rtable *rth;
 
 	fl4->flowi4_iif = LOOPBACK_IFINDEX;
 	fl4->flowi4_tos = tos & IPTOS_RT_MASK;
 	fl4->flowi4_scope = ((tos & RTO_ONLINK) ?
 			 RT_SCOPE_LINK : RT_SCOPE_UNIVERSE);
 
-	rcu_read_lock();
 	if (fl4->saddr) {
 		rth = ERR_PTR(-EINVAL);
 		if (ipv4_is_multicast(fl4->saddr) ||
@@ -2354,15 +2347,15 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
 			fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK);
 		dev_out = net->loopback_dev;
 		fl4->flowi4_oif = LOOPBACK_IFINDEX;
-		res.type = RTN_LOCAL;
+		res->type = RTN_LOCAL;
 		flags |= RTCF_LOCAL;
 		goto make_route;
 	}
 
-	err = fib_lookup(net, fl4, &res, 0);
+	err = fib_lookup(net, fl4, res, 0);
 	if (err) {
-		res.fi = NULL;
-		res.table = NULL;
+		res->fi = NULL;
+		res->table = NULL;
 		if (fl4->flowi4_oif &&
 		    (ipv4_is_multicast(fl4->daddr) ||
 		    !netif_index_is_l3_master(net, fl4->flowi4_oif))) {
@@ -2387,17 +2380,17 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
 			if (fl4->saddr == 0)
 				fl4->saddr = inet_select_addr(dev_out, 0,
 							      RT_SCOPE_LINK);
-			res.type = RTN_UNICAST;
+			res->type = RTN_UNICAST;
 			goto make_route;
 		}
 		rth = ERR_PTR(err);
 		goto out;
 	}
 
-	if (res.type == RTN_LOCAL) {
+	if (res->type == RTN_LOCAL) {
 		if (!fl4->saddr) {
-			if (res.fi->fib_prefsrc)
-				fl4->saddr = res.fi->fib_prefsrc;
+			if (res->fi->fib_prefsrc)
+				fl4->saddr = res->fi->fib_prefsrc;
 			else
 				fl4->saddr = fl4->daddr;
 		}
@@ -2410,20 +2403,36 @@ struct rtable *__ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
 		goto make_route;
 	}
 
-	fib_select_path(net, &res, fl4, skb);
+	fib_select_path(net, res, fl4, skb);
 
-	dev_out = FIB_RES_DEV(res);
+	dev_out = FIB_RES_DEV(*res);
 	fl4->flowi4_oif = dev_out->ifindex;
 
 
 make_route:
-	rth = __mkroute_output(&res, fl4, orig_oif, dev_out, flags);
+	rth = __mkroute_output(res, fl4, orig_oif, dev_out, flags);
 
 out:
+	return rth;
+}
+
+struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
+					const struct sk_buff *skb)
+{
+	struct fib_result res;
+	struct rtable *rth;
+
+	res.tclassid	= 0;
+	res.fi		= NULL;
+	res.table	= NULL;
+
+	rcu_read_lock();
+	rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
 	rcu_read_unlock();
+
 	return rth;
 }
-EXPORT_SYMBOL_GPL(__ip_route_output_key_hash);
+EXPORT_SYMBOL_GPL(ip_route_output_key_hash);
 
 static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
 {
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next 3/8] net: ipv4: Remove event arg to rt_fill_info
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-1-git-send-email-roopa@cumulusnetworks.com>

From: David Ahern <dsahern@gmail.com>

rt_fill_info has 1 caller with the event set to RTM_NEWROUTE. Given that
remove the arg and use RTM_NEWROUTE directly in rt_fill_info.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 net/ipv4/route.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index fe7b765..9699e9b 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2536,7 +2536,7 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
 
 static int rt_fill_info(struct net *net,  __be32 dst, __be32 src, u32 table_id,
 			struct flowi4 *fl4, struct sk_buff *skb, u32 portid,
-			u32 seq, int event)
+			u32 seq)
 {
 	struct rtable *rt = skb_rtable(skb);
 	struct rtmsg *r;
@@ -2545,7 +2545,7 @@ static int rt_fill_info(struct net *net,  __be32 dst, __be32 src, u32 table_id,
 	u32 error;
 	u32 metrics[RTAX_MAX];
 
-	nlh = nlmsg_put(skb, portid, seq, event, sizeof(*r), 0);
+	nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*r), 0);
 	if (!nlh)
 		return -EMSGSIZE;
 
@@ -2745,8 +2745,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 		table_id = rt->rt_table_id;
 
 	err = rt_fill_info(net, dst, src, table_id, &fl4, skb,
-			   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq,
-			   RTM_NEWROUTE);
+			   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq);
 	if (err < 0)
 		goto errout_free;
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next 4/8] net: ipv4: Convert inet_rtm_getroute to rcu versions of route lookup
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-1-git-send-email-roopa@cumulusnetworks.com>

From: David Ahern <dsahern@gmail.com>

Convert inet_rtm_getroute to use ip_route_input_rcu and
ip_route_output_key_hash_rcu passing the fib_result arg to both.
The rcu lock is held through the creation of the response, so the
rtable/dst does not need to be attached to the skb and is passed
to rt_fill_info directly.

In converting from ip_route_output_key to ip_route_output_key_hash_rcu
the xfrm_lookup_route in ip_route_output_flow is dropped since
flowi4_proto is not set for a route get request.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 net/ipv4/route.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 9699e9b..6e0bd40 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2404,7 +2404,7 @@ struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *fl4,
 		}
 
 		/* L3 master device is the loopback for that domain */
-		dev_out = l3mdev_master_dev_rcu(FIB_RES_DEV(res)) ? :
+		dev_out = l3mdev_master_dev_rcu(FIB_RES_DEV(*res)) ? :
 			net->loopback_dev;
 		fl4->flowi4_oif = dev_out->ifindex;
 		flags |= RTCF_LOCAL;
@@ -2435,7 +2435,7 @@ struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
 	res.table	= NULL;
 
 	rcu_read_lock();
-	rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
+	rth = ip_route_output_key_hash_rcu(net, fl4, skb, &res);
 	rcu_read_unlock();
 
 	return rth;
@@ -2534,11 +2534,11 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4,
 }
 EXPORT_SYMBOL_GPL(ip_route_output_flow);
 
+/* called with rcu_read_lock held */
 static int rt_fill_info(struct net *net,  __be32 dst, __be32 src, u32 table_id,
 			struct flowi4 *fl4, struct sk_buff *skb, u32 portid,
-			u32 seq)
+			u32 seq, struct rtable *rt)
 {
-	struct rtable *rt = skb_rtable(skb);
 	struct rtmsg *r;
 	struct nlmsghdr *nlh;
 	unsigned long expires = 0;
@@ -2653,6 +2653,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	struct net *net = sock_net(in_skb->sk);
 	struct rtmsg *rtm;
 	struct nlattr *tb[RTA_MAX+1];
+	struct fib_result res = {};
 	struct rtable *rt = NULL;
 	struct flowi4 fl4;
 	__be32 dst = 0;
@@ -2709,10 +2710,12 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	fl4.flowi4_mark = mark;
 	fl4.flowi4_uid = uid;
 
+	rcu_read_lock();
+
 	if (iif) {
 		struct net_device *dev;
 
-		dev = __dev_get_by_index(net, iif);
+		dev = dev_get_by_index_rcu(net, iif);
 		if (!dev) {
 			err = -ENODEV;
 			goto errout_free;
@@ -2721,14 +2724,14 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 		skb->protocol	= htons(ETH_P_IP);
 		skb->dev	= dev;
 		skb->mark	= mark;
-		err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
+		err = ip_route_input_rcu(skb, dst, src, rtm->rtm_tos,
+					 dev, &res);
 
 		rt = skb_rtable(skb);
 		if (err == 0 && rt->dst.error)
 			err = -rt->dst.error;
 	} else {
-		rt = ip_route_output_key(net, &fl4);
-
+		rt = ip_route_output_key_hash_rcu(net, &fl4, skb, &res);
 		err = 0;
 		if (IS_ERR(rt))
 			err = PTR_ERR(rt);
@@ -2737,7 +2740,6 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	if (err)
 		goto errout_free;
 
-	skb_dst_set(skb, &rt->dst);
 	if (rtm->rtm_flags & RTM_F_NOTIFY)
 		rt->rt_flags |= RTCF_NOTIFY;
 
@@ -2745,15 +2747,18 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 		table_id = rt->rt_table_id;
 
 	err = rt_fill_info(net, dst, src, table_id, &fl4, skb,
-			   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq);
+			   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, rt);
 	if (err < 0)
 		goto errout_free;
 
+	rcu_read_unlock();
+
 	err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
 errout:
 	return err;
 
 errout_free:
+	rcu_read_unlock();
 	kfree_skb(skb);
 	goto errout;
 }
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next 6/8] net: ipv4: add new RTM_F_FIB_MATCH flag for use with RTM_GETROUTE
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-1-git-send-email-roopa@cumulusnetworks.com>

From: Roopa Prabhu <roopa@cumulusnetworks.com>

This flag when specified will return matched fib result in
response to a RTM_GETROUTE query.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 include/uapi/linux/rtnetlink.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 6487b21..564790e 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -278,6 +278,7 @@ enum rt_scope_t {
 #define RTM_F_EQUALIZE		0x400	/* Multipath equalizer: NI	*/
 #define RTM_F_PREFIX		0x800	/* Prefix addresses		*/
 #define RTM_F_LOOKUP_TABLE	0x1000	/* set rtm_table to FIB lookup result */
+#define RTM_F_FIB_MATCH	        0x2000	/* return full fib lookup match */
 
 /* Reserved table identifiers */
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next 8/8] net: ipv6: RTM_GETROUTE: return matched fib result when requested
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-1-git-send-email-roopa@cumulusnetworks.com>

From: Roopa Prabhu <roopa@cumulusnetworks.com>

This patch adds support to return matched fib result when RTM_F_FIB_MATCH
flag is specified in RTM_GETROUTE request. This is useful for user-space
applications/controllers wanting to query a matching route.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 net/ipv6/route.c | 36 +++++++++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 7 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 80bda31..c4d6da9 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -3612,6 +3612,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	struct rtmsg *rtm;
 	struct flowi6 fl6;
 	int err, iif = 0, oif = 0;
+	bool fibmatch;
 
 	err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy,
 			  extack);
@@ -3622,6 +3623,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	memset(&fl6, 0, sizeof(fl6));
 	rtm = nlmsg_data(nlh);
 	fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
+	fibmatch = (rtm->rtm_flags & RTM_F_FIB_MATCH) ? true : false;
 
 	if (tb[RTA_SRC]) {
 		if (nla_len(tb[RTA_SRC]) < sizeof(struct in6_addr))
@@ -3667,12 +3669,27 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 		if (!ipv6_addr_any(&fl6.saddr))
 			flags |= RT6_LOOKUP_F_HAS_SADDR;
 
-		rt = (struct rt6_info *)ip6_route_input_lookup(net, dev, &fl6,
-							       flags);
+		if (!fibmatch)
+			rt = (struct rt6_info *)ip6_route_input_lookup(net, dev,
+								       &fl6,
+								       flags);
 	} else {
 		fl6.flowi6_oif = oif;
 
-		rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6);
+		if (!fibmatch)
+			rt = (struct rt6_info *)ip6_route_output_flags(net,
+								       NULL,
+								       &fl6, 0);
+	}
+
+	if (fibmatch) {
+		rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, 0);
+		if (rt->dst.error) {
+			err = rt->dst.error;
+			ip6_rt_put(rt);
+			goto errout;
+		}
+
 	}
 
 	if (rt == net->ipv6.ip6_null_entry) {
@@ -3689,10 +3706,15 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	}
 
 	skb_dst_set(skb, &rt->dst);
-
-	err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
-			    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
-			    nlh->nlmsg_seq, 0);
+	if (fibmatch) {
+		err = rt6_fill_node(net, skb, rt, NULL, NULL, iif,
+				    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
+				    nlh->nlmsg_seq, 0);
+	} else {
+		err = rt6_fill_node(net, skb, rt, &fl6.daddr, &fl6.saddr, iif,
+				    RTM_NEWROUTE, NETLINK_CB(in_skb).portid,
+				    nlh->nlmsg_seq, 0);
+	}
 	if (err < 0) {
 		kfree_skb(skb);
 		goto errout;
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next 5/8] net: ipv4: Save trie prefix to fib lookup result
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-1-git-send-email-roopa@cumulusnetworks.com>

From: David Ahern <dsahern@gmail.com>

Prefix is needed for returning matching route spec on get route request.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 include/net/ip_fib.h | 1 +
 net/ipv4/fib_trie.c  | 1 +
 2 files changed, 2 insertions(+)

diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 42e8b8f..25f5c51 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -136,6 +136,7 @@ struct fib_info {
 
 struct fib_table;
 struct fib_result {
+	__be32		prefix;
 	unsigned char	prefixlen;
 	unsigned char	nh_sel;
 	unsigned char	type;
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 6d0f6c79..6e9df7d 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1452,6 +1452,7 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
 			if (!(fib_flags & FIB_LOOKUP_NOREF))
 				atomic_inc(&fi->fib_clntref);
 
+			res->prefix = htonl(n->key);
 			res->prefixlen = KEYLENGTH - fa->fa_slen;
 			res->nh_sel = nhsel;
 			res->type = fa->fa_type;
-- 
1.9.1

^ permalink raw reply related

* [PATCH net-next 7/8] net: ipv4: RTM_GETROUTE: return matched fib result when requested
From: Roopa Prabhu @ 2017-05-24 18:19 UTC (permalink / raw)
  To: davem; +Cc: netdev, dsahern, nikolay
In-Reply-To: <1495649951-30417-1-git-send-email-roopa@cumulusnetworks.com>

From: Roopa Prabhu <roopa@cumulusnetworks.com>

This patch adds support to return matched fib result when RTM_F_FIB_MATCH
flag is specified in RTM_GETROUTE request. This is useful for user-space
applications/controllers wanting to query a matching route.

Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
---
 net/ipv4/route.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 6e0bd40..419bdba 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -114,6 +114,8 @@
 #include <net/ip_tunnels.h>
 #include <net/l3mdev.h>
 
+#include "fib_lookup.h"
+
 #define RT_FL_TOS(oldflp4) \
 	((oldflp4)->flowi4_tos & (IPTOS_RT_MASK | RTO_ONLINK))
 
@@ -2746,8 +2748,15 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
 	if (rtm->rtm_flags & RTM_F_LOOKUP_TABLE)
 		table_id = rt->rt_table_id;
 
-	err = rt_fill_info(net, dst, src, table_id, &fl4, skb,
-			   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, rt);
+	if (rtm->rtm_flags & RTM_F_FIB_MATCH)
+		err = fib_dump_info(skb, NETLINK_CB(in_skb).portid,
+				    nlh->nlmsg_seq, RTM_NEWROUTE, table_id,
+				    rt->rt_type, res.prefix, res.prefixlen,
+				    fl4.flowi4_tos, res.fi, 0);
+	else
+		err = rt_fill_info(net, dst, src, table_id, &fl4, skb,
+				   NETLINK_CB(in_skb).portid, nlh->nlmsg_seq,
+				   rt);
 	if (err < 0)
 		goto errout_free;
 
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH 2/2] at803x: double check SGMII side autoneg
From: Timur Tabi @ 2017-05-24 18:58 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Matthias May, Zefir Kurtisi, netdev, f.fainelli, David Miller,
	Manoj Iyer, jhugo
In-Reply-To: <20170524140929.GC26577@lunn.ch>

On 05/24/2017 09:09 AM, Andrew Lunn wrote:
> It could be, the copper side is up, but the SGMII side is down, at the
> point at803x_aneg_done() is called. So it is correctly returning
> 0. Sometime later the SGMII side goes up, but there is not a second
> interrupt. Hence the phy core does not know that the full, 2 stage MAC
> to PHY to peer PHY link is now up.

Ok, I'm going to debug this some more.  It turns out that the MAC side of
the SGMII link can send an interrupt when it thinks that auto-negotiation is
done.  I might be able to use this.

What function should my MAC driver call when it wants the phy core to call
at803x_aneg_done again to see if autonegotiation is done?

Also, is there a way for the MAC driver to know that at803x_aneg_done()
previously returned 0, and that it needs to tell the phy core to check again?

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* Re: [PATCH v2 net-next 00/11] qed/qede: Mostly-cleanup series
From: David Miller @ 2017-05-24 19:18 UTC (permalink / raw)
  To: Yuval.Mintz; +Cc: netdev
In-Reply-To: <1495521688-27669-1-git-send-email-Yuval.Mintz@cavium.com>

From: Yuval Mintz <Yuval.Mintz@cavium.com>
Date: Tue, 23 May 2017 09:41:17 +0300

> This series contains some cleanup of the qed and qede code:
>  - #1 contains mostly static/endian changes in order to allow qede to
>    pass sparse compilation cleanly.
>  - #2, #5 and #6 are either semantic or remove dead-code from driver.
>  - #9, #10 and #11 relate to printing and slightly change some APIs
>    between qed and the protocol drivers for that end [sharing the
>    interface names and information regarding device].
> 
> The rest of the patches are minor changes/fixes to various flows
> in qed.

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next] geneve: fix fill_info when using collect_metadata
From: Pravin Shelar @ 2017-05-24 19:20 UTC (permalink / raw)
  To: Eric Garver; +Cc: Linux Kernel Network Developers
In-Reply-To: <20170523223727.15307-1-e@erig.me>

On Tue, May 23, 2017 at 3:37 PM, Eric Garver <e@erig.me> wrote:
> Since 9b4437a5b870 ("geneve: Unify LWT and netdev handling.") fill_info
> does not return UDP_ZERO_CSUM6_RX when using COLLECT_METADATA. This is
> because it uses ip_tunnel_info_af() with the device level info, which is
> not valid for COLLECT_METADATA.
>
> Fix by checking for the presence of the actual sockets.
>
> Fixes: 9b4437a5b870 ("geneve: Unify LWT and netdev handling.")
> Signed-off-by: Eric Garver <e@erig.me>
Thanks for the patch.

Acked-by: Pravin B Shelar <pshelar@ovn.org>


I noticed that the MTU and encal_len calculation in geneve_configure()
also needs to be fixed for collect metadata case. Can you send patch
to fix it?

^ permalink raw reply

* Re: [PATCH net 0/2] sctp: a bunch of fixes for processing dupcookie
From: David Miller @ 2017-05-24 19:22 UTC (permalink / raw)
  To: lucien.xin; +Cc: netdev, linux-sctp, marcelo.leitner, nhorman
In-Reply-To: <cover.1495517205.git.lucien.xin@gmail.com>

From: Xin Long <lucien.xin@gmail.com>
Date: Tue, 23 May 2017 13:28:53 +0800

> After introducing transport hashtable and per stream info into sctp,
> some regressions were caused when processing dupcookie, this patchset
> is to fix them.

Series applied, thanks.

^ permalink raw reply

* Re: [PATCH net-next 2/4] nfp: register ports as devlink ports
From: Jakub Kicinski @ 2017-05-24 19:24 UTC (permalink / raw)
  To: Jiri Pirko; +Cc: netdev, oss-drivers
In-Reply-To: <20170524123514.GB1908@nanopsycho>

On Wed, 24 May 2017 14:35:14 +0200, Jiri Pirko wrote:
> >+void nfp_devlink_port_unregister(struct nfp_port *port)
> >+{
> >+	/* Due to unpleasant lock ordering we may see the port go away before
> >+	 * we have fully probed.  
> 
> Could you elaborate on this a bit more please?

It's partially due to peculiarities of the management FW more than
kernel stuff.  Unfortunately some ethtool media config requires reboot
to be applied, so we print a friendly message to the logs and
unregister the associated netdevs.  Which means once netdevs get
registered ports may go away.

Enter devlink, I need the ability to grab the adapater lock in
split/unsplit callbacks to find the ports, which implies having to drop
that lock before I register devlink.  And only after I register devlink
can I register the ports.

I could do init without registering anything, drop the adapter lock,
register devlink, and then grab the adapter lock back and register
devlink ports and netdevs.  But there is another issue...

Since I look for ports on a list maintained in the adapter struct,
driver code doesn't care if devlink_port has been registered or not.
The moment devlink is registered, split/unsplit requests will be
accepted - potentially trying to unregister devlink_port before the
register could happen.

Further down the line, also, the eswitch mode setting is coming.  Which
means the moment I register devlink itself ports will get shuffled (due
to the plan of registering VFs as ports :)). 

I feel like registering devlink should be the last action of the
driver, really.  My plan was to keep that simple if() for now, and once
we get to extending devlink with SR-IOV stuff also add the ability to
pre-register ports.  Allow registering ports on not-yet-registered
devlink (probably put them on a private list within struct devlink).
This would make devlink_register() a single point when everything
devlink becomes visible, atomically, instead of devlink itself coming
first and then ports following.

Does that make sense?  Am I misreading the code (again :S)?

^ permalink raw reply

* Re: [PATCH v2] net: fec: add post PHY reset delay DT property
From: David Miller @ 2017-05-24 19:25 UTC (permalink / raw)
  To: quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
  Cc: fugang.duan-3arQi8VN3Tc, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	mark.rutland-5wv7dgnIgG8, netdev-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8
In-Reply-To: <20170523094808.11102-1-quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

From: Quentin Schulz <quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Date: Tue, 23 May 2017 11:48:08 +0200

> Some PHY require to wait for a bit after the reset GPIO has been
> toggled. This adds support for the DT property `phy-reset-post-delay`
> which gives the delay in milliseconds to wait after reset.
> 
> If the DT property is not given, no delay is observed. Post reset delay
> greater than 1000ms are invalid.
> 
> Signed-off-by: Quentin Schulz <quentin.schulz-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Applied, thanks.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH] net: rtnetlink: bail out from rtnl_fdb_dump() on parse error
From: Greg Rose @ 2017-05-24 19:29 UTC (permalink / raw)
  To: Alexander Potapenko; +Cc: dvyukov, kcc, edumazet, davem, linux-kernel, netdev
In-Reply-To: <20170523112028.132630-1-glider@google.com>

On Tue, 2017-05-23 at 13:20 +0200, Alexander Potapenko wrote:
> rtnl_fdb_dump() failed to check the result of nlmsg_parse(), which led
> to contents of |ifm| being uninitialized because nlh->nlmsglen was too
> small to accommodate |ifm|. The uninitialized data may affect some
> branches and result in unwanted effects, although kernel data doesn't
> seem to leak to the userspace directly.
> 
> The bug has been detected with KMSAN and syzkaller.
> 
> Signed-off-by: Alexander Potapenko <glider@google.com>
> ---
> For the record, here is the KMSAN report:
> 
> ==================================================================
> BUG: KMSAN: use of unitialized memory in rtnl_fdb_dump+0x5dc/0x1000
> CPU: 0 PID: 1039 Comm: probe Not tainted 4.11.0-rc5+ #2727
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
> Call Trace:
>  __dump_stack lib/dump_stack.c:16
>  dump_stack+0x143/0x1b0 lib/dump_stack.c:52
>  kmsan_report+0x12a/0x180 mm/kmsan/kmsan.c:1007
>  __kmsan_warning_32+0x66/0xb0 mm/kmsan/kmsan_instr.c:491
>  rtnl_fdb_dump+0x5dc/0x1000 net/core/rtnetlink.c:3230
>  netlink_dump+0x84f/0x1190 net/netlink/af_netlink.c:2168
>  __netlink_dump_start+0xc97/0xe50 net/netlink/af_netlink.c:2258
>  netlink_dump_start ./include/linux/netlink.h:165
>  rtnetlink_rcv_msg+0xae9/0xb40 net/core/rtnetlink.c:4094
>  netlink_rcv_skb+0x339/0x5a0 net/netlink/af_netlink.c:2339
>  rtnetlink_rcv+0x83/0xa0 net/core/rtnetlink.c:4110
>  netlink_unicast_kernel net/netlink/af_netlink.c:1272
>  netlink_unicast+0x13b7/0x1480 net/netlink/af_netlink.c:1298
>  netlink_sendmsg+0x10b8/0x10f0 net/netlink/af_netlink.c:1844
>  sock_sendmsg_nosec net/socket.c:633
>  sock_sendmsg net/socket.c:643
>  ___sys_sendmsg+0xd4b/0x10f0 net/socket.c:1997
>  __sys_sendmsg net/socket.c:2031
>  SYSC_sendmsg+0x2c6/0x3f0 net/socket.c:2042
>  SyS_sendmsg+0x87/0xb0 net/socket.c:2038
>  do_syscall_64+0x102/0x150 arch/x86/entry/common.c:285
>  entry_SYSCALL64_slow_path+0x25/0x25 arch/x86/entry/entry_64.S:246
> RIP: 0033:0x401300
> RSP: 002b:00007ffc3b0e6d58 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
> RAX: ffffffffffffffda RBX: 00000000004002b0 RCX: 0000000000401300
> RDX: 0000000000000000 RSI: 00007ffc3b0e6d80 RDI: 0000000000000003
> RBP: 00007ffc3b0e6e00 R08: 000000000000000b R09: 0000000000000004
> R10: 000000000000000d R11: 0000000000000246 R12: 0000000000000000
> R13: 00000000004065a0 R14: 0000000000406630 R15: 0000000000000000
> origin: 000000008fe00056
>  save_stack_trace+0x59/0x60 arch/x86/kernel/stacktrace.c:59
>  kmsan_save_stack_with_flags mm/kmsan/kmsan.c:352
>  kmsan_internal_poison_shadow+0xb1/0x1a0 mm/kmsan/kmsan.c:247
>  kmsan_poison_shadow+0x6d/0xc0 mm/kmsan/kmsan.c:260
>  slab_alloc_node mm/slub.c:2743
>  __kmalloc_node_track_caller+0x1f4/0x390 mm/slub.c:4349
>  __kmalloc_reserve net/core/skbuff.c:138
>  __alloc_skb+0x2cd/0x740 net/core/skbuff.c:231
>  alloc_skb ./include/linux/skbuff.h:933
>  netlink_alloc_large_skb net/netlink/af_netlink.c:1144
>  netlink_sendmsg+0x934/0x10f0 net/netlink/af_netlink.c:1819
>  sock_sendmsg_nosec net/socket.c:633
>  sock_sendmsg net/socket.c:643
>  ___sys_sendmsg+0xd4b/0x10f0 net/socket.c:1997
>  __sys_sendmsg net/socket.c:2031
>  SYSC_sendmsg+0x2c6/0x3f0 net/socket.c:2042
>  SyS_sendmsg+0x87/0xb0 net/socket.c:2038
>  do_syscall_64+0x102/0x150 arch/x86/entry/common.c:285
>  return_from_SYSCALL_64+0x0/0x6a arch/x86/entry/entry_64.S:246
> ==================================================================
> 
> and the reproducer:
> 
> ==================================================================
>   #include <sys/socket.h>
>   #include <net/if_arp.h>
>   #include <linux/netlink.h>
>   #include <stdint.h>
>   
>   int main()
>   {
>     int sock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_NONBLOCK, 0);
>     struct msghdr msg;
>     memset(&msg, 0, sizeof(msg));
>     char nlmsg_buf[32];
>     memset(nlmsg_buf, 0, sizeof(nlmsg_buf));
>     struct nlmsghdr *nlmsg = nlmsg_buf;
>     nlmsg->nlmsg_len = 0x11;
>     nlmsg->nlmsg_type = 0x1e; // RTM_NEWROUTE = RTM_BASE + 0x0e
>     // type = 0x0e = 1110b
>     // kind = 2
>     nlmsg->nlmsg_flags = 0x101; // NLM_F_ROOT | NLM_F_REQUEST
>     nlmsg->nlmsg_seq = 0;
>     nlmsg->nlmsg_pid = 0;
>     nlmsg_buf[16] = (char)7;
>     struct iovec iov;
>     iov.iov_base = nlmsg_buf;
>     iov.iov_len = 17;
>     msg.msg_iov = &iov;
>     msg.msg_iovlen = 1;
>     sendmsg(sock, &msg, 0);
>     return 0;
>   }
> ==================================================================
> ---
>  net/core/rtnetlink.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 49a279a7cc15..9e2c0a7cb325 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -3231,8 +3231,11 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
>  	int err = 0;
>  	int fidx = 0;
>  
> -	if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb,
> -			IFLA_MAX, ifla_policy, NULL) == 0) {
> +	err = nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb,
> +			  IFLA_MAX, ifla_policy, NULL);
> +	if (err < 0) {
> +		return -EINVAL;
> +	} else if (err == 0) {
>  		if (tb[IFLA_MASTER])
>  			br_idx = nla_get_u32(tb[IFLA_MASTER]);
>  	}

Fix looks right to me.

Reviewed-by: Greg Rose <gvrose8192@gmail.com>

^ permalink raw reply

* Re: [PATCH] net: rtnetlink: bail out from rtnl_fdb_dump() on parse error
From: David Miller @ 2017-05-24 19:32 UTC (permalink / raw)
  To: glider; +Cc: dvyukov, kcc, edumazet, linux-kernel, netdev
In-Reply-To: <20170523112028.132630-1-glider@google.com>

From: Alexander Potapenko <glider@google.com>
Date: Tue, 23 May 2017 13:20:28 +0200

> rtnl_fdb_dump() failed to check the result of nlmsg_parse(), which led
> to contents of |ifm| being uninitialized because nlh->nlmsglen was too
> small to accommodate |ifm|. The uninitialized data may affect some
> branches and result in unwanted effects, although kernel data doesn't
> seem to leak to the userspace directly.
> 
> The bug has been detected with KMSAN and syzkaller.
> 
> Signed-off-by: Alexander Potapenko <glider@google.com>

Applied, thanks.

^ permalink raw reply

* Re: pull-request: mac80211 2017-05-23
From: David Miller @ 2017-05-24 19:32 UTC (permalink / raw)
  To: johannes; +Cc: netdev, linux-wireless
In-Reply-To: <20170523124256.23463-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes@sipsolutions.net>
Date: Tue, 23 May 2017 14:42:55 +0200

> I have just two fixes here, one of the scheduled scan issue that
> Sander Eikelenboom found, and the other properly makes mesh more
> strictly check its extension headers.
> 
> Please pull and let me know if there's any problem.

Pulled, thanks Johannes.

^ permalink raw reply

* RE: [PATCH net-next 1/8] net: ipv4: refactor __ip_route_output_key_hash
From: Rosen, Rami @ 2017-05-24 19:33 UTC (permalink / raw)
  To: Roopa Prabhu, davem@davemloft.net
  Cc: netdev@vger.kernel.org, dsahern@gmail.com,
	nikolay@cumulusnetworks.com
In-Reply-To: <1495649951-30417-2-git-send-email-roopa@cumulusnetworks.com>

Hi, Rupa /David Ahern,

First, thanks for this patch set!

Second, it seems to me that something might be incorrect here.

You have these additions in this patch  (1/8):
...
+struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *flp,
+					    const struct sk_buff *skb,
+					    struct fib_result *res);
...
+struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *fl4,
+					const struct sk_buff *skb)
+{
+	struct fib_result res;
+	struct rtable *rth;
+
+	res.tclassid	= 0;
+	res.fi		= NULL;
+	res.table	= NULL;
+
+	rcu_read_lock();
+	rth = ip_route_output_key_hash_rcu(net, fl4, &res, mp_hash);
 	rcu_read_unlock();
+
 	return rth;
 }
-EXPORT_SYMBOL_GPL(__ip_route_output_key_hash);
+EXPORT_SYMBOL_GPL(ip_route_output_key_hash);
 

So the third parameter to ip_route_output_key_hash_rcu() should be skb*, and the fourth parameter should be fib_result *. However, you do not pass the skb parameter 
when calling ip_route_output_key_hash_rcu() in 
ip_route_output_key_hash()  (in fact you don't use it at all),  and you pass mp_hash as the fourth parameter.

Regards,
Rami Rosen
Intel Corporation

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox