lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 10 Apr 2017 15:22:01 +0100
From:   Robert Shearman <rshearma@...cade.com>
To:     <davem@...emloft.net>
CC:     <netdev@...r.kernel.org>, David Ahern <dsa@...ulusnetworks.com>,
        "Robert Shearman" <rshearma@...cade.com>
Subject: [PATCH net-next 2/3] ipv4: Fix route handling when using l3mdev set to main table

If an l3mdev is set to use the main table then the use of the local
table is overridden. This means that when split local/main table is in
effect then local routes aren't added to the local table and so don't
respect the order of ip rules.

Fix this by assuming that no if no l3mdev is present then defaulting
to RT_TABLE_MAIN and then subsequently doing a translation from
RT_TABLE_MAIN to RT_TABLE_LOCAL.

Signed-off-by: Robert Shearman <rshearma@...cade.com>
---
 net/ipv4/af_inet.c      |  4 +++-
 net/ipv4/fib_frontend.c | 14 +++++++++-----
 net/ipv4/raw.c          |  5 ++++-
 3 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index d1a11707a126..83d54fab03f0 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -436,7 +436,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	struct net *net = sock_net(sk);
 	unsigned short snum;
 	int chk_addr_ret;
-	u32 tb_id = RT_TABLE_LOCAL;
+	u32 tb_id = RT_TABLE_MAIN;
 	int err;
 
 	/* If the socket has its own bind function then use it. (RAW) */
@@ -459,6 +459,8 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 	}
 
 	tb_id = l3mdev_fib_table_by_index(net, sk->sk_bound_dev_if) ? : tb_id;
+	if (tb_id == RT_TABLE_MAIN)
+		tb_id = RT_TABLE_LOCAL;
 	chk_addr_ret = inet_addr_type_table(net, addr->sin_addr.s_addr, tb_id);
 
 	/* Not specified by any standard per-se, however it breaks too
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 8f2133ffc2ff..1782c35dbac0 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -248,8 +248,10 @@ EXPORT_SYMBOL(inet_addr_type);
 unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev,
 				__be32 addr)
 {
-	u32 rt_table = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL;
+	u32 rt_table = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
 
+	if (rt_table == RT_TABLE_MAIN)
+		rt_table = RT_TABLE_LOCAL;
 	return __inet_dev_addr_type(net, dev, addr, rt_table);
 }
 EXPORT_SYMBOL(inet_dev_addr_type);
@@ -261,8 +263,10 @@ unsigned int inet_addr_type_dev_table(struct net *net,
 				      const struct net_device *dev,
 				      __be32 addr)
 {
-	u32 rt_table = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL;
+	u32 rt_table = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
 
+	if (rt_table == RT_TABLE_MAIN)
+		rt_table = RT_TABLE_LOCAL;
 	return __inet_dev_addr_type(net, NULL, addr, rt_table);
 }
 EXPORT_SYMBOL(inet_addr_type_dev_table);
@@ -805,7 +809,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
 static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifaddr *ifa)
 {
 	struct net *net = dev_net(ifa->ifa_dev->dev);
-	u32 tb_id = l3mdev_fib_table(ifa->ifa_dev->dev);
+	u32 tb_id = l3mdev_fib_table(ifa->ifa_dev->dev) ? : RT_TABLE_MAIN;
 	struct fib_table *tb;
 	struct fib_config cfg = {
 		.fc_protocol = RTPROT_KERNEL,
@@ -820,8 +824,8 @@ static void fib_magic(int cmd, int type, __be32 dst, int dst_len, struct in_ifad
 		},
 	};
 
-	if (!tb_id)
-		tb_id = (type == RTN_UNICAST) ? RT_TABLE_MAIN : RT_TABLE_LOCAL;
+	if (tb_id == RT_TABLE_MAIN && type != RTN_UNICAST)
+		tb_id = RT_TABLE_LOCAL;
 
 	tb = fib_new_table(net, tb_id);
 	if (!tb)
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 8119e1f66e03..2dd7022681e6 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -699,7 +699,7 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
-	u32 tb_id = RT_TABLE_LOCAL;
+	u32 tb_id = RT_TABLE_MAIN;
 	int ret = -EINVAL;
 	int chk_addr_ret;
 
@@ -710,6 +710,9 @@ static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 		tb_id = l3mdev_fib_table_by_index(sock_net(sk),
 						 sk->sk_bound_dev_if) ? : tb_id;
 
+	if (tb_id == RT_TABLE_MAIN)
+		tb_id = RT_TABLE_LOCAL;
+
 	chk_addr_ret = inet_addr_type_table(sock_net(sk), addr->sin_addr.s_addr,
 					    tb_id);
 
-- 
2.1.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ