All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2
@ 2018-09-27 17:58 Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 1/7] " Christian Brauner
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 17:58 UTC (permalink / raw)
  To: jbenc, davem, dsahern, stephen, netdev, linux-kernel; +Cc: Christian Brauner

Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
requests with struct ifinfomsg. This is wrong and should have been
struct ifaddrmsg all along as mandated by the manpages. However, dump
requests so far didn't parse the netlink message that was sent and
succeeded even when a wrong struct was passed along.

Currently, the message is parsed under the assumption that the correct
struct ifaddrmsg is sent down. If the parsing fails the kernel will
still fulfill the request to preserve backwards compatability but a
rate-limited message that there were leftover bytes after parsing the
message is recorded in dmesg. It has been argued that this is
unacceptable [1].

But various new features that got and will get added to RTM_GETADDR make
it necessary to definitely know what header was passed along.
This is currently not possible without resorting to (likely unreliable)
hacks such as introducing a nested attribute that ensures that
RTM_GETADDR which pass along properties such as IFA_TARGET_NETNSID
always exceed RTM_GETADDR requests that send down the wrong struct
ifinfomsg [2]. Basically, multiple approaches to solve this have been
shut down. Furthermore, the API expressed via RTM_GETADDR is apparently
frozen [3] so the wiggle room at this point seems very much zero.

The correct solution at this point seems to me to introduce a new
RTM_GETADDR2 request. This way we can parse the message and fail hard if
the struct is not struct ifaddrmsg and can safely extend it in the
future. Userspace tools that rely on the buggy RTM_GETADDR API will
still keep working without even having to see any log messages and new
userspace tools that want to make user of new features can make use of
the new RTM_GETADDR2 requests.

[1]: https://lists.openwall.net/netdev/2018/09/25/59
[2]: https://lists.openwall.net/netdev/2018/09/25/75
[3]: https://lists.openwall.net/netdev/2018/09/26/166

Signed-off-by: Christian Brauner <christian@brauner.io>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>

Christian Brauner (7):
  rtnetlink: add RTM_GETADDR2
  ipv4: add RTM_GETADDR2
  ipv6: add RTM_GETADDR2
  decnet: add RTM_GETADDR2
  phonet: add RTM_GETADDR2
  selinux: add RTM_GETADDR2
  rtnetlink: enable RTM_GETADDR2

 include/uapi/linux/rtnetlink.h |  3 +++
 net/core/rtnetlink.c           |  1 +
 net/decnet/dn_dev.c            | 25 +++++++++++++++++++++++--
 net/ipv4/devinet.c             | 24 +++++++++++++++++++++---
 net/ipv6/addrconf.c            | 30 ++++++++++++++++++++++++------
 net/phonet/pn_netlink.c        | 25 +++++++++++++++++++++++--
 security/selinux/nlmsgtab.c    |  3 ++-
 7 files changed, 97 insertions(+), 14 deletions(-)

-- 
2.17.1


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH net-next 1/7] rtnetlink: add RTM_GETADDR2
  2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
@ 2018-09-27 17:58 ` Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 2/7] ipv4: " Christian Brauner
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 17:58 UTC (permalink / raw)
  To: jbenc, davem, dsahern, stephen, netdev, linux-kernel; +Cc: Christian Brauner

Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
requests with struct ifinfomsg. This is wrong and should have been
struct ifaddrmsg all along as mandated by the manpages. However, dump
requests so far didn't parse the netlink message that was sent and
succeeded even when a wrong struct was passed along.

Currently, the message is parsed under the assumption that the correct
struct ifaddrmsg is sent down. If the parsing fails the kernel will
still fulfill the request to preserve backwards compatability but a
rate-limited message that there were leftover bytes after parsing the
message is recorded in dmesg. It has been argued that this is
unacceptable [1].

But various new features that got and will get added to RTM_GETADDR make
it necessary to definitely know what header was passed along.
This is currently not possible without resorting to (likely unreliable)
hacks such as introducing a nested attribute that ensures that
RTM_GETADDR which pass along properties such as IFA_TARGET_NETNSID
always exceed RTM_GETADDR requests that send down the wrong struct
ifinfomsg [2]. Basically, multiple approaches to solve this have been
shut down. Furthermore, the API expressed via RTM_GETADDR is apparently
frozen [3] so the wiggle room at this point seems very much zero.

The correct solution at this point seems to me to introduce a new
RTM_GETADDR2 request. This way we can parse the message and fail hard if
the struct is not struct ifaddrmsg and can safely extend it in the
future. Userspace tools that rely on the buggy RTM_GETADDR API will
still keep working without even having to see any log messages and new
userspace tools that want to make user of new features can make use of
the new RTM_GETADDR2 requests.

[1]: https://lists.openwall.net/netdev/2018/09/25/59
[2]: https://lists.openwall.net/netdev/2018/09/25/75
[3]: https://lists.openwall.net/netdev/2018/09/26/166

Signed-off-by: Christian Brauner <christian@brauner.io>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
---
 include/uapi/linux/rtnetlink.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index 46399367627f..e167f90c3d7a 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -157,6 +157,9 @@ enum {
 	RTM_GETCHAIN,
 #define RTM_GETCHAIN RTM_GETCHAIN
 
+	RTM_GETADDR2 = 106,
+#define RTM_GETADDR2  RTM_GETADDR2
+
 	__RTM_MAX,
 #define RTM_MAX		(((__RTM_MAX + 3) & ~3) - 1)
 };
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 2/7] ipv4: add RTM_GETADDR2
  2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 1/7] " Christian Brauner
@ 2018-09-27 17:58 ` Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 3/7] ipv6: " Christian Brauner
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 17:58 UTC (permalink / raw)
  To: jbenc, davem, dsahern, stephen, netdev, linux-kernel; +Cc: Christian Brauner

Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
requests with struct ifinfomsg. This is wrong and should have been
struct ifaddrmsg all along as mandated by the manpages. However, dump
requests so far didn't parse the netlink message that was sent and
succeeded even when a wrong struct was passed along.

Currently, the message is parsed under the assumption that the correct
struct ifaddrmsg is sent down. If the parsing fails the kernel will
still fulfill the request to preserve backwards compatability but a
rate-limited message that there were leftover bytes after parsing the
message is recorded in dmesg. It has been argued that this is
unacceptable [1].

But various new features that got and will get added to RTM_GETADDR make
it necessary to definitely know what header was passed along.
This is currently not possible without resorting to (likely unreliable)
hacks such as introducing a nested attribute that ensures that
RTM_GETADDR which pass along properties such as IFA_TARGET_NETNSID
always exceed RTM_GETADDR requests that send down the wrong struct
ifinfomsg [2]. Basically, multiple approaches to solve this have been
shut down. Furthermore, the API expressed via RTM_GETADDR is apparently
frozen [3] so the wiggle room at this point seems very much zero.

The correct solution at this point seems to me to introduce a new
RTM_GETADDR2 request. This way we can parse the message and fail hard if
the struct is not struct ifaddrmsg and can safely extend it in the
future. Userspace tools that rely on the buggy RTM_GETADDR API will
still keep working without even having to see any log messages and new
userspace tools that want to make user of new features can make use of
the new RTM_GETADDR2 requests.

[1]: https://lists.openwall.net/netdev/2018/09/25/59
[2]: https://lists.openwall.net/netdev/2018/09/25/75
[3]: https://lists.openwall.net/netdev/2018/09/26/166

Signed-off-by: Christian Brauner <christian@brauner.io>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
---
 net/ipv4/devinet.c | 24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 44d931a3cd50..3ac004ba67b0 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1659,7 +1659,8 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
 	return -EMSGSIZE;
 }
 
-static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+static int inet_dump_ifaddr_common(struct sk_buff *skb,
+				   struct netlink_callback *cb, int rtm_type)
 {
 	struct inet_fill_args fillargs = {
 		.portid = NETLINK_CB(cb->skb).portid,
@@ -1683,8 +1684,14 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 	s_idx = idx = cb->args[1];
 	s_ip_idx = ip_idx = cb->args[2];
 
-	if (nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb, IFA_MAX,
-			ifa_ipv4_policy, NULL) >= 0) {
+	if (rtm_type == RTM_GETADDR2) {
+		int err;
+
+		err = nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb,
+				  IFA_MAX, ifa_ipv4_policy, NULL);
+		if (err < 0)
+			return err;
+
 		if (tb[IFA_TARGET_NETNSID]) {
 			fillargs.netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]);
 
@@ -1736,6 +1743,16 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	return inet_dump_ifaddr_common(skb, cb, RTM_GETADDR);
+}
+
+static int inet_dump_ifaddr2(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	return inet_dump_ifaddr_common(skb, cb, RTM_GETADDR2);
+}
+
 static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
 		      u32 portid)
 {
@@ -2564,6 +2581,7 @@ void __init devinet_init(void)
 	rtnl_register(PF_INET, RTM_NEWADDR, inet_rtm_newaddr, NULL, 0);
 	rtnl_register(PF_INET, RTM_DELADDR, inet_rtm_deladdr, NULL, 0);
 	rtnl_register(PF_INET, RTM_GETADDR, NULL, inet_dump_ifaddr, 0);
+	rtnl_register(PF_INET, RTM_GETADDR2, NULL, inet_dump_ifaddr2, 0);
 	rtnl_register(PF_INET, RTM_GETNETCONF, inet_netconf_get_devconf,
 		      inet_netconf_dump_devconf, 0);
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 3/7] ipv6: add RTM_GETADDR2
  2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 1/7] " Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 2/7] ipv4: " Christian Brauner
@ 2018-09-27 17:58 ` Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 4/7] decnet: " Christian Brauner
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 17:58 UTC (permalink / raw)
  To: jbenc, davem, dsahern, stephen, netdev, linux-kernel; +Cc: Christian Brauner

Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
requests with struct ifinfomsg. This is wrong and should have been
struct ifaddrmsg all along as mandated by the manpages. However, dump
requests so far didn't parse the netlink message that was sent and
succeeded even when a wrong struct was passed along.

Currently, the message is parsed under the assumption that the correct
struct ifaddrmsg is sent down. If the parsing fails the kernel will
still fulfill the request to preserve backwards compatability but a
rate-limited message that there were leftover bytes after parsing the
message is recorded in dmesg. It has been argued that this is
unacceptable [1].

But various new features that got and will get added to RTM_GETADDR make
it necessary to definitely know what header was passed along.
This is currently not possible without resorting to (likely unreliable)
hacks such as introducing a nested attribute that ensures that
RTM_GETADDR which pass along properties such as IFA_TARGET_NETNSID
always exceed RTM_GETADDR requests that send down the wrong struct
ifinfomsg [2]. Basically, multiple approaches to solve this have been
shut down. Furthermore, the API expressed via RTM_GETADDR is apparently
frozen [3] so the wiggle room at this point seems very much zero.

The correct solution at this point seems to me to introduce a new
RTM_GETADDR2 request. This way we can parse the message and fail hard if
the struct is not struct ifaddrmsg and can safely extend it in the
future. Userspace tools that rely on the buggy RTM_GETADDR API will
still keep working without even having to see any log messages and new
userspace tools that want to make user of new features can make use of
the new RTM_GETADDR2 requests.

[1]: https://lists.openwall.net/netdev/2018/09/25/59
[2]: https://lists.openwall.net/netdev/2018/09/25/75
[3]: https://lists.openwall.net/netdev/2018/09/26/166

Signed-off-by: Christian Brauner <christian@brauner.io>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
---
 net/ipv6/addrconf.c | 30 ++++++++++++++++++++++++------
 1 file changed, 24 insertions(+), 6 deletions(-)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index a9a317322388..6e76e5cc76c4 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -5003,7 +5003,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
 }
 
 static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
-			   enum addr_type_t type)
+			   enum addr_type_t type, int rtm_version)
 {
 	struct net *net = sock_net(skb->sk);
 	struct nlattr *tb[IFA_MAX+1];
@@ -5020,8 +5020,14 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
 	s_idx = idx = cb->args[1];
 	s_ip_idx = ip_idx = cb->args[2];
 
-	if (nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb, IFA_MAX,
-			ifa_ipv6_policy, NULL) >= 0) {
+	if (rtm_version == RTM_GETADDR2) {
+		int err;
+
+		err = nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb,
+				  IFA_MAX, ifa_ipv6_policy, NULL);
+		if (err < 0)
+			return err;
+
 		if (tb[IFA_TARGET_NETNSID]) {
 			netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]);
 
@@ -5068,14 +5074,21 @@ static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	enum addr_type_t type = UNICAST_ADDR;
 
-	return inet6_dump_addr(skb, cb, type);
+	return inet6_dump_addr(skb, cb, type, RTM_GETADDR);
+}
+
+static int inet6_dump_ifaddr2(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	enum addr_type_t type = UNICAST_ADDR;
+
+	return inet6_dump_addr(skb, cb, type, RTM_GETADDR2);
 }
 
 static int inet6_dump_ifmcaddr(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	enum addr_type_t type = MULTICAST_ADDR;
 
-	return inet6_dump_addr(skb, cb, type);
+	return inet6_dump_addr(skb, cb, type, RTM_GETMULTICAST);
 }
 
 
@@ -5083,7 +5096,7 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
 {
 	enum addr_type_t type = ANYCAST_ADDR;
 
-	return inet6_dump_addr(skb, cb, type);
+	return inet6_dump_addr(skb, cb, type, RTM_GETANYCAST);
 }
 
 static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
@@ -6833,6 +6846,11 @@ int __init addrconf_init(void)
 				   RTNL_FLAG_DOIT_UNLOCKED);
 	if (err < 0)
 		goto errout;
+	err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETADDR2,
+				   inet6_rtm_getaddr, inet6_dump_ifaddr2,
+				   RTNL_FLAG_DOIT_UNLOCKED);
+	if (err < 0)
+		goto errout;
 	err = rtnl_register_module(THIS_MODULE, PF_INET6, RTM_GETMULTICAST,
 				   NULL, inet6_dump_ifmcaddr, 0);
 	if (err < 0)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 4/7] decnet: add RTM_GETADDR2
  2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
                   ` (2 preceding siblings ...)
  2018-09-27 17:58 ` [PATCH net-next 3/7] ipv6: " Christian Brauner
@ 2018-09-27 17:58 ` Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 5/7] phonet: " Christian Brauner
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 17:58 UTC (permalink / raw)
  To: jbenc, davem, dsahern, stephen, netdev, linux-kernel; +Cc: Christian Brauner

Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
requests with struct ifinfomsg. This is wrong and should have been
struct ifaddrmsg all along as mandated by the manpages. However, dump
requests so far didn't parse the netlink message that was sent and
succeeded even when a wrong struct was passed along.

Currently, the message is parsed under the assumption that the correct
struct ifaddrmsg is sent down. If the parsing fails the kernel will
still fulfill the request to preserve backwards compatability but a
rate-limited message that there were leftover bytes after parsing the
message is recorded in dmesg. It has been argued that this is
unacceptable [1].

But various new features that got and will get added to RTM_GETADDR make
it necessary to definitely know what header was passed along.
This is currently not possible without resorting to (likely unreliable)
hacks such as introducing a nested attribute that ensures that
RTM_GETADDR which pass along properties such as IFA_TARGET_NETNSID
always exceed RTM_GETADDR requests that send down the wrong struct
ifinfomsg [2]. Basically, multiple approaches to solve this have been
shut down. Furthermore, the API expressed via RTM_GETADDR is apparently
frozen [3] so the wiggle room at this point seems very much zero.

The correct solution at this point seems to me to introduce a new
RTM_GETADDR2 request. This way we can parse the message and fail hard if
the struct is not struct ifaddrmsg and can safely extend it in the
future. Userspace tools that rely on the buggy RTM_GETADDR API will
still keep working without even having to see any log messages and new
userspace tools that want to make user of new features can make use of
the new RTM_GETADDR2 requests.

[1]: https://lists.openwall.net/netdev/2018/09/25/59
[2]: https://lists.openwall.net/netdev/2018/09/25/75
[3]: https://lists.openwall.net/netdev/2018/09/26/166

Signed-off-by: Christian Brauner <christian@brauner.io>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
---
 net/decnet/dn_dev.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
index d0b3e69c6b39..8da6ca154c08 100644
--- a/net/decnet/dn_dev.c
+++ b/net/decnet/dn_dev.c
@@ -738,10 +738,12 @@ static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
 		rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_IFADDR, err);
 }
 
-static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+static int dn_nl_dump_ifaddr_common(struct sk_buff *skb,
+				    struct netlink_callback *cb, int rtm_type)
 {
 	struct net *net = sock_net(skb->sk);
-	int idx, dn_idx = 0, skip_ndevs, skip_naddr;
+	int err, idx, dn_idx = 0, skip_ndevs, skip_naddr;
+	struct nlattr *tb[IFA_MAX+1];
 	struct net_device *dev;
 	struct dn_dev *dn_db;
 	struct dn_ifaddr *ifa;
@@ -749,6 +751,13 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 	if (!net_eq(net, &init_net))
 		return 0;
 
+	if (rtm_type == RTM_GETADDR2) {
+		err = nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb, IFA_MAX,
+				dn_ifa_policy, NULL);
+		if (err < 0)
+			return err;
+	}
+
 	skip_ndevs = cb->args[0];
 	skip_naddr = cb->args[1];
 
@@ -787,6 +796,16 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	return dn_nl_dump_ifaddr_common(skb, cb, RTM_GETADDR);
+}
+
+static int dn_nl_dump_ifaddr2(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	return dn_nl_dump_ifaddr_common(skb, cb, RTM_GETADDR2);
+}
+
 static int dn_dev_get_first(struct net_device *dev, __le16 *addr)
 {
 	struct dn_dev *dn_db;
@@ -1410,6 +1429,8 @@ void __init dn_dev_init(void)
 			     dn_nl_deladdr, NULL, 0);
 	rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_GETADDR,
 			     NULL, dn_nl_dump_ifaddr, 0);
+	rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_GETADDR2,
+			     NULL, dn_nl_dump_ifaddr2, 0);
 
 	proc_create_seq("decnet_dev", 0444, init_net.proc_net, &dn_dev_seq_ops);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 5/7] phonet: add RTM_GETADDR2
  2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
                   ` (3 preceding siblings ...)
  2018-09-27 17:58 ` [PATCH net-next 4/7] decnet: " Christian Brauner
@ 2018-09-27 17:58 ` Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 6/7] selinux: " Christian Brauner
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 17:58 UTC (permalink / raw)
  To: jbenc, davem, dsahern, stephen, netdev, linux-kernel; +Cc: Christian Brauner

Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
requests with struct ifinfomsg. This is wrong and should have been
struct ifaddrmsg all along as mandated by the manpages. However, dump
requests so far didn't parse the netlink message that was sent and
succeeded even when a wrong struct was passed along.

Currently, the message is parsed under the assumption that the correct
struct ifaddrmsg is sent down. If the parsing fails the kernel will
still fulfill the request to preserve backwards compatability but a
rate-limited message that there were leftover bytes after parsing the
message is recorded in dmesg. It has been argued that this is
unacceptable [1].

But various new features that got and will get added to RTM_GETADDR make
it necessary to definitely know what header was passed along.
This is currently not possible without resorting to (likely unreliable)
hacks such as introducing a nested attribute that ensures that
RTM_GETADDR which pass along properties such as IFA_TARGET_NETNSID
always exceed RTM_GETADDR requests that send down the wrong struct
ifinfomsg [2]. Basically, multiple approaches to solve this have been
shut down. Furthermore, the API expressed via RTM_GETADDR is apparently
frozen [3] so the wiggle room at this point seems very much zero.

The correct solution at this point seems to me to introduce a new
RTM_GETADDR2 request. This way we can parse the message and fail hard if
the struct is not struct ifaddrmsg and can safely extend it in the
future. Userspace tools that rely on the buggy RTM_GETADDR API will
still keep working without even having to see any log messages and new
userspace tools that want to make user of new features can make use of
the new RTM_GETADDR2 requests.

[1]: https://lists.openwall.net/netdev/2018/09/25/59
[2]: https://lists.openwall.net/netdev/2018/09/25/75
[3]: https://lists.openwall.net/netdev/2018/09/26/166

Signed-off-by: Christian Brauner <christian@brauner.io>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
---
 net/phonet/pn_netlink.c | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)

diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c
index 871eaf2cb85e..acba4fe9a612 100644
--- a/net/phonet/pn_netlink.c
+++ b/net/phonet/pn_netlink.c
@@ -131,13 +131,22 @@ static int fill_addr(struct sk_buff *skb, struct net_device *dev, u8 addr,
 	return -EMSGSIZE;
 }
 
-static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+static int getaddr_dumpit_common(struct sk_buff *skb,
+				 struct netlink_callback *cb, int rtm_type)
 {
 	struct phonet_device_list *pndevs;
+	struct nlattr *tb[IFA_MAX+1];
 	struct phonet_device *pnd;
-	int dev_idx = 0, dev_start_idx = cb->args[0];
+	int err, dev_idx = 0, dev_start_idx = cb->args[0];
 	int addr_idx = 0, addr_start_idx = cb->args[1];
 
+	if (rtm_type == RTM_GETADDR2) {
+		err = nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb,
+				  IFA_MAX, ifa_phonet_policy, NULL);
+		if (err < 0)
+			return err;
+	}
+
 	pndevs = phonet_device_list(sock_net(skb->sk));
 	rcu_read_lock();
 	list_for_each_entry_rcu(pnd, &pndevs->list, list) {
@@ -168,6 +177,16 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 	return skb->len;
 }
 
+static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	return getaddr_dumpit_common(skb, cb, RTM_GETADDR);
+}
+
+static int getaddr_dumpit2(struct sk_buff *skb, struct netlink_callback *cb)
+{
+	return getaddr_dumpit_common(skb, cb, RTM_GETADDR2);
+}
+
 /* Routes handling */
 
 static int fill_route(struct sk_buff *skb, struct net_device *dev, u8 dst,
@@ -309,6 +328,8 @@ int __init phonet_netlink_register(void)
 			     addr_doit, NULL, 0);
 	rtnl_register_module(THIS_MODULE, PF_PHONET, RTM_GETADDR,
 			     NULL, getaddr_dumpit, 0);
+	rtnl_register_module(THIS_MODULE, PF_PHONET, RTM_GETADDR2,
+			     NULL, getaddr_dumpit2, 0);
 	rtnl_register_module(THIS_MODULE, PF_PHONET, RTM_NEWROUTE,
 			     route_doit, NULL, 0);
 	rtnl_register_module(THIS_MODULE, PF_PHONET, RTM_DELROUTE,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 6/7] selinux: add RTM_GETADDR2
  2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
                   ` (4 preceding siblings ...)
  2018-09-27 17:58 ` [PATCH net-next 5/7] phonet: " Christian Brauner
@ 2018-09-27 17:58 ` Christian Brauner
  2018-09-27 17:58 ` [PATCH net-next 7/7] rtnetlink: enable RTM_GETADDR2 Christian Brauner
  2018-09-27 20:24 ` [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 David Ahern
  7 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 17:58 UTC (permalink / raw)
  To: jbenc, davem, dsahern, stephen, netdev, linux-kernel; +Cc: Christian Brauner

Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
requests with struct ifinfomsg. This is wrong and should have been
struct ifaddrmsg all along as mandated by the manpages. However, dump
requests so far didn't parse the netlink message that was sent and
succeeded even when a wrong struct was passed along.

Currently, the message is parsed under the assumption that the correct
struct ifaddrmsg is sent down. If the parsing fails the kernel will
still fulfill the request to preserve backwards compatability but a
rate-limited message that there were leftover bytes after parsing the
message is recorded in dmesg. It has been argued that this is
unacceptable [1].

But various new features that got and will get added to RTM_GETADDR make
it necessary to definitely know what header was passed along.
This is currently not possible without resorting to (likely unreliable)
hacks such as introducing a nested attribute that ensures that
RTM_GETADDR which pass along properties such as IFA_TARGET_NETNSID
always exceed RTM_GETADDR requests that send down the wrong struct
ifinfomsg [2]. Basically, multiple approaches to solve this have been
shut down. Furthermore, the API expressed via RTM_GETADDR is apparently
frozen [3] so the wiggle room at this point seems very much zero.

The correct solution at this point seems to me to introduce a new
RTM_GETADDR2 request. This way we can parse the message and fail hard if
the struct is not struct ifaddrmsg and can safely extend it in the
future. Userspace tools that rely on the buggy RTM_GETADDR API will
still keep working without even having to see any log messages and new
userspace tools that want to make user of new features can make use of
the new RTM_GETADDR2 requests.

[1]: https://lists.openwall.net/netdev/2018/09/25/59
[2]: https://lists.openwall.net/netdev/2018/09/25/75
[3]: https://lists.openwall.net/netdev/2018/09/26/166

Signed-off-by: Christian Brauner <christian@brauner.io>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
---
 security/selinux/nlmsgtab.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c
index 74b951f55608..3c45f50e987d 100644
--- a/security/selinux/nlmsgtab.c
+++ b/security/selinux/nlmsgtab.c
@@ -80,6 +80,7 @@ static const struct nlmsg_perm nlmsg_route_perms[] =
 	{ RTM_NEWSTATS,		NETLINK_ROUTE_SOCKET__NLMSG_READ },
 	{ RTM_GETSTATS,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
 	{ RTM_NEWCACHEREPORT,	NETLINK_ROUTE_SOCKET__NLMSG_READ },
+	{ RTM_GETADDR2,		NETLINK_ROUTE_SOCKET__NLMSG_READ  },
 };
 
 static const struct nlmsg_perm nlmsg_tcpdiag_perms[] =
@@ -159,7 +160,7 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
 	switch (sclass) {
 	case SECCLASS_NETLINK_ROUTE_SOCKET:
 		/* RTM_MAX always point to RTM_SETxxxx, ie RTM_NEWxxx + 3 */
-		BUILD_BUG_ON(RTM_MAX != (RTM_NEWCHAIN + 3));
+		BUILD_BUG_ON(RTM_MAX != (RTM_GETADDR2 + 1));
 		err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
 				 sizeof(nlmsg_route_perms));
 		break;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH net-next 7/7] rtnetlink: enable RTM_GETADDR2
  2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
                   ` (5 preceding siblings ...)
  2018-09-27 17:58 ` [PATCH net-next 6/7] selinux: " Christian Brauner
@ 2018-09-27 17:58 ` Christian Brauner
  2018-09-27 20:24 ` [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 David Ahern
  7 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 17:58 UTC (permalink / raw)
  To: jbenc, davem, dsahern, stephen, netdev, linux-kernel; +Cc: Christian Brauner

Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
requests with struct ifinfomsg. This is wrong and should have been
struct ifaddrmsg all along as mandated by the manpages. However, dump
requests so far didn't parse the netlink message that was sent and
succeeded even when a wrong struct was passed along.

Currently, the message is parsed under the assumption that the correct
struct ifaddrmsg is sent down. If the parsing fails the kernel will
still fulfill the request to preserve backwards compatability but a
rate-limited message that there were leftover bytes after parsing the
message is recorded in dmesg. It has been argued that this is
unacceptable [1].

But various new features that got and will get added to RTM_GETADDR make
it necessary to definitely know what header was passed along.
This is currently not possible without resorting to (likely unreliable)
hacks such as introducing a nested attribute that ensures that
RTM_GETADDR which pass along properties such as IFA_TARGET_NETNSID
always exceed RTM_GETADDR requests that send down the wrong struct
ifinfomsg [2]. Basically, multiple approaches to solve this have been
shut down. Furthermore, the API expressed via RTM_GETADDR is apparently
frozen [3] so the wiggle room at this point seems very much zero.

The correct solution at this point seems to me to introduce a new
RTM_GETADDR2 request. This way we can parse the message and fail hard if
the struct is not struct ifaddrmsg and can safely extend it in the
future. Userspace tools that rely on the buggy RTM_GETADDR API will
still keep working without even having to see any log messages and new
userspace tools that want to make user of new features can make use of
the new RTM_GETADDR2 requests.

[1]: https://lists.openwall.net/netdev/2018/09/25/59
[2]: https://lists.openwall.net/netdev/2018/09/25/75
[3]: https://lists.openwall.net/netdev/2018/09/26/166

Signed-off-by: Christian Brauner <christian@brauner.io>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Benc <jbenc@redhat.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
---
 net/core/rtnetlink.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 35162e1b06ad..2ec020236053 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -4835,6 +4835,7 @@ void __init rtnetlink_init(void)
 	rtnl_register(PF_UNSPEC, RTM_DELLINK, rtnl_dellink, NULL, 0);
 
 	rtnl_register(PF_UNSPEC, RTM_GETADDR, NULL, rtnl_dump_all, 0);
+	rtnl_register(PF_UNSPEC, RTM_GETADDR2, NULL, rtnl_dump_all, 0);
 	rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all, 0);
 	rtnl_register(PF_UNSPEC, RTM_GETNETCONF, NULL, rtnl_dump_all, 0);
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2
  2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
                   ` (6 preceding siblings ...)
  2018-09-27 17:58 ` [PATCH net-next 7/7] rtnetlink: enable RTM_GETADDR2 Christian Brauner
@ 2018-09-27 20:24 ` David Ahern
  2018-09-27 20:31   ` Christian Brauner
  7 siblings, 1 reply; 10+ messages in thread
From: David Ahern @ 2018-09-27 20:24 UTC (permalink / raw)
  To: Christian Brauner, jbenc, davem, stephen, netdev, linux-kernel

On 9/27/18 11:58 AM, Christian Brauner wrote:
> Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
> requests with struct ifinfomsg. This is wrong and should have been
> struct ifaddrmsg all along as mandated by the manpages. However, dump
> requests so far didn't parse the netlink message that was sent and
> succeeded even when a wrong struct was passed along.

...

> The correct solution at this point seems to me to introduce a new
> RTM_GETADDR2 request. This way we can parse the message and fail hard if
> the struct is not struct ifaddrmsg and can safely extend it in the
> future. Userspace tools that rely on the buggy RTM_GETADDR API will
> still keep working without even having to see any log messages and new
> userspace tools that want to make user of new features can make use of
> the new RTM_GETADDR2 requests.

First, I think this is the wrong precedent when all we need is a single
bit flag that userspace can use to tell the kernel "I have a clue and I
am passing in the proper header for this dump request".

Second, you are not addressing the problems of the past by requiring the
proper header and checking values passed in it.

I have another idea. I'll send an RFC patch soon.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2
  2018-09-27 20:24 ` [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 David Ahern
@ 2018-09-27 20:31   ` Christian Brauner
  0 siblings, 0 replies; 10+ messages in thread
From: Christian Brauner @ 2018-09-27 20:31 UTC (permalink / raw)
  To: David Ahern, jbenc, davem, stephen, netdev, linux-kernel

On September 27, 2018 10:24:36 PM GMT+02:00, David Ahern <dsahern@gmail.com> wrote:
>On 9/27/18 11:58 AM, Christian Brauner wrote:
>> Various userspace programs (e.g. iproute2) have sent RTM_GETADDR
>> requests with struct ifinfomsg. This is wrong and should have been
>> struct ifaddrmsg all along as mandated by the manpages. However, dump
>> requests so far didn't parse the netlink message that was sent and
>> succeeded even when a wrong struct was passed along.
>
>...
>
>> The correct solution at this point seems to me to introduce a new
>> RTM_GETADDR2 request. This way we can parse the message and fail hard
>if
>> the struct is not struct ifaddrmsg and can safely extend it in the
>> future. Userspace tools that rely on the buggy RTM_GETADDR API will
>> still keep working without even having to see any log messages and
>new
>> userspace tools that want to make user of new features can make use
>of
>> the new RTM_GETADDR2 requests.
>
>First, I think this is the wrong precedent when all we need is a single
>bit flag that userspace can use to tell the kernel "I have a clue and I
>am passing in the proper header for this dump request".

That had been NAKed previously but if you have an idea that will be accepted all the more power to you.

>
>Second, you are not addressing the problems of the past by requiring
>the
>proper header and checking values passed in it.

I don't follow. RTM_GETADDR requests are absolutely unchanged. The full legacy behavior is restored by this patchset.

And requiring that RTM_GETADDR2 requests always pass the correct header is absolutely fine. We don't want built invalid legacy behavior into a new request  type.

>
>I have another idea. I'll send an RFC patch soon.


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-09-27 20:31 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-27 17:58 [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 Christian Brauner
2018-09-27 17:58 ` [PATCH net-next 1/7] " Christian Brauner
2018-09-27 17:58 ` [PATCH net-next 2/7] ipv4: " Christian Brauner
2018-09-27 17:58 ` [PATCH net-next 3/7] ipv6: " Christian Brauner
2018-09-27 17:58 ` [PATCH net-next 4/7] decnet: " Christian Brauner
2018-09-27 17:58 ` [PATCH net-next 5/7] phonet: " Christian Brauner
2018-09-27 17:58 ` [PATCH net-next 6/7] selinux: " Christian Brauner
2018-09-27 17:58 ` [PATCH net-next 7/7] rtnetlink: enable RTM_GETADDR2 Christian Brauner
2018-09-27 20:24 ` [PATCH net-next 0/7] rtnetlink: add RTM_GETADDR2 David Ahern
2018-09-27 20:31   ` Christian Brauner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.