All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net 0/4] mpls: fixes for nexthops without via addresses
@ 2015-12-10 19:30 Robert Shearman
  2015-12-10 19:30 ` [PATCH net 1/4] mpls: validate L2 via address length Robert Shearman
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Robert Shearman @ 2015-12-10 19:30 UTC (permalink / raw)
  To: ebiederm, roopa; +Cc: davem, netdev, sam.h.russell, Robert Shearman

These four fixes all apply to the case of having an mpls route with an
output device, but without a nexthop.

Patches 2 and 3 could really have been combined in one patch, but I
wanted to separate the fix for some recent breakage from the fix for a
day-1 issue.

Robert Shearman (4):
  mpls: validate L2 via address length
  mpls: don't dump RTA_VIA attribute if not specified
  mpls: fix out-of-bounds access when via address not specified
  mpls: make via address optional for multipath routes

 net/mpls/af_mpls.c | 43 +++++++++++++++++++++++++++++++------------
 1 file changed, 31 insertions(+), 12 deletions(-)

-- 
2.1.4

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

* [PATCH net 1/4] mpls: validate L2 via address length
  2015-12-10 19:30 [PATCH net 0/4] mpls: fixes for nexthops without via addresses Robert Shearman
@ 2015-12-10 19:30 ` Robert Shearman
  2015-12-11 22:51   ` roopa
  2015-12-10 19:30 ` [PATCH net 2/4] mpls: don't dump RTA_VIA attribute if not specified Robert Shearman
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 8+ messages in thread
From: Robert Shearman @ 2015-12-10 19:30 UTC (permalink / raw)
  To: ebiederm, roopa; +Cc: davem, netdev, sam.h.russell, Robert Shearman

If an L2 via address for an mpls nexthop is specified, the length of
the L2 address must match that expected by the output device,
otherwise it could access memory beyond the end of the via address
buffer in the route.

This check was present prior to commit f8efb73c97e2 ("mpls: multipath
route support"), but got lost in the refactoring, so add it back,
applying it to all nexthops in multipath routes.

Fixes: f8efb73c97e2 ("mpls: multipath route support")
Signed-off-by: Robert Shearman <rshearma@brocade.com>
---
 net/mpls/af_mpls.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index c70d750148b6..3be29cb1f658 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -534,6 +534,10 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt,
 	if (!mpls_dev_get(dev))
 		goto errout;
 
+	if ((nh->nh_via_table == NEIGH_LINK_TABLE) &&
+	    (dev->addr_len != nh->nh_via_alen))
+		goto errout;
+
 	RCU_INIT_POINTER(nh->nh_dev, dev);
 
 	return 0;
-- 
2.1.4

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

* [PATCH net 2/4] mpls: don't dump RTA_VIA attribute if not specified
  2015-12-10 19:30 [PATCH net 0/4] mpls: fixes for nexthops without via addresses Robert Shearman
  2015-12-10 19:30 ` [PATCH net 1/4] mpls: validate L2 via address length Robert Shearman
@ 2015-12-10 19:30 ` Robert Shearman
  2015-12-10 19:30 ` [PATCH net 3/4] mpls: fix out-of-bounds access when via address " Robert Shearman
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Robert Shearman @ 2015-12-10 19:30 UTC (permalink / raw)
  To: ebiederm, roopa; +Cc: davem, netdev, sam.h.russell, Robert Shearman

The problem seen is that when adding a route with a nexthop with no
via address specified, iproute2 generates bogus output:

  # ip -f mpls route add 100 dev lo
  # ip -f mpls route list
  100 via inet 0.0.8.0 dev lo

The reason for this is that the kernel generates an RTA_VIA attribute
with the family set to AF_INET, but the via address data having zero
length. The cause of family being AF_INET is that on route insert
cfg->rc_via_table is left set to 0, which just happens to be
NEIGH_ARP_TABLE which is then translated into AF_INET.

iproute2 doesn't validate the length prior to printing and so prints
garbage. Although it could be fixed to do the validation, I would
argue that AF_INET addresses should always be exactly 4 bytes so the
kernel is really giving userspace bogus data.

Therefore, avoid generating the RTA_VIA attribute when dumping the
route if the via address wasn't specified on add/modify. This is
indicated by NEIGH_ARP_TABLE and a zero via address length - if the
user specified a via address the address length would have been
validated such that it was 4 bytes. Although this is a change in
behaviour that is visible to userspace, I believe that what was
generated before was invalid and as such userspace wouldn't be
expecting it.

Signed-off-by: Robert Shearman <rshearma@brocade.com>
---
 net/mpls/af_mpls.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 3be29cb1f658..ac1c116abaac 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -1235,7 +1235,9 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
 		    nla_put_labels(skb, RTA_NEWDST, nh->nh_labels,
 				   nh->nh_label))
 			goto nla_put_failure;
-		if (nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
+		if ((nh->nh_via_table != NEIGH_ARP_TABLE ||
+		     nh->nh_via_alen != 0) &&
+		    nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
 				nh->nh_via_alen))
 			goto nla_put_failure;
 		dev = rtnl_dereference(nh->nh_dev);
@@ -1323,7 +1325,9 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt)
 
 		if (nh->nh_dev)
 			payload += nla_total_size(4); /* RTA_OIF */
-		payload += nla_total_size(2 + nh->nh_via_alen); /* RTA_VIA */
+		if (nh->nh_via_table != NEIGH_ARP_TABLE ||
+		    nh->nh_via_alen != 0) /* RTA_VIA */
+			payload += nla_total_size(2 + nh->nh_via_alen);
 		if (nh->nh_labels) /* RTA_NEWDST */
 			payload += nla_total_size(nh->nh_labels * 4);
 	} else {
-- 
2.1.4

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

* [PATCH net 3/4] mpls: fix out-of-bounds access when via address not specified
  2015-12-10 19:30 [PATCH net 0/4] mpls: fixes for nexthops without via addresses Robert Shearman
  2015-12-10 19:30 ` [PATCH net 1/4] mpls: validate L2 via address length Robert Shearman
  2015-12-10 19:30 ` [PATCH net 2/4] mpls: don't dump RTA_VIA attribute if not specified Robert Shearman
@ 2015-12-10 19:30 ` Robert Shearman
  2015-12-10 19:30 ` [PATCH net 4/4] mpls: make via address optional for multipath routes Robert Shearman
  2015-12-12  5:44 ` [PATCH net 0/4] mpls: fixes for nexthops without via addresses David Miller
  4 siblings, 0 replies; 8+ messages in thread
From: Robert Shearman @ 2015-12-10 19:30 UTC (permalink / raw)
  To: ebiederm, roopa; +Cc: davem, netdev, sam.h.russell, Robert Shearman

When a via address isn't specified, the via table is left initialised
to 0 (NEIGH_ARP_TABLE), and the via address length also left
initialised to 0. This results in a via address array of length 0
being allocated (contiguous with route and nexthop array), meaning
that when a packet is sent using neigh_xmit the neighbour lookup and
creation will cause an out-of-bounds access when accessing the 4 bytes
of the IPv4 address it assumes it has been given a pointer to.

This could be fixed by allocating the 4 bytes of via address necessary
and leaving it as all zeroes. However, it seems wrong to me to use an
ipv4 nexthop (including possibly ARPing for 0.0.0.0) when the user
didn't specify to do so.

Instead, set the via address table to NEIGH_NR_TABLES to signify it
hasn't been specified and use this at forwarding time to signify a
neigh_xmit using an L2 address consisting of the device address. This
mechanism is the same as that used for both ARP and ND for loopback
interfaces and those flagged as no-arp, which are all we can really
support in this case.

Fixes: cf4b24f0024f ("mpls: reduce memory usage of routes")
Signed-off-by: Robert Shearman <rshearma@brocade.com>
---
 net/mpls/af_mpls.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index ac1c116abaac..7bfc85f52ca8 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -27,6 +27,8 @@
  */
 #define MAX_MP_SELECT_LABELS 4
 
+#define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
+
 static int zero = 0;
 static int label_limit = (1 << 20) - 1;
 
@@ -317,7 +319,13 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
 		}
 	}
 
-	err = neigh_xmit(nh->nh_via_table, out_dev, mpls_nh_via(rt, nh), skb);
+	/* If via wasn't specified then send out using device address */
+	if (nh->nh_via_table == MPLS_NEIGH_TABLE_UNSPEC)
+		err = neigh_xmit(NEIGH_LINK_TABLE, out_dev,
+				 out_dev->dev_addr, skb);
+	else
+		err = neigh_xmit(nh->nh_via_table, out_dev,
+				 mpls_nh_via(rt, nh), skb);
 	if (err)
 		net_dbg_ratelimited("%s: packet transmission failed: %d\n",
 				    __func__, err);
@@ -1122,6 +1130,7 @@ static int rtm_to_route_config(struct sk_buff *skb,  struct nlmsghdr *nlh,
 
 	cfg->rc_label		= LABEL_NOT_SPECIFIED;
 	cfg->rc_protocol	= rtm->rtm_protocol;
+	cfg->rc_via_table	= MPLS_NEIGH_TABLE_UNSPEC;
 	cfg->rc_nlflags		= nlh->nlmsg_flags;
 	cfg->rc_nlinfo.portid	= NETLINK_CB(skb).portid;
 	cfg->rc_nlinfo.nlh	= nlh;
@@ -1235,8 +1244,7 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
 		    nla_put_labels(skb, RTA_NEWDST, nh->nh_labels,
 				   nh->nh_label))
 			goto nla_put_failure;
-		if ((nh->nh_via_table != NEIGH_ARP_TABLE ||
-		     nh->nh_via_alen != 0) &&
+		if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC &&
 		    nla_put_via(skb, nh->nh_via_table, mpls_nh_via(rt, nh),
 				nh->nh_via_alen))
 			goto nla_put_failure;
@@ -1325,8 +1333,7 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt)
 
 		if (nh->nh_dev)
 			payload += nla_total_size(4); /* RTA_OIF */
-		if (nh->nh_via_table != NEIGH_ARP_TABLE ||
-		    nh->nh_via_alen != 0) /* RTA_VIA */
+		if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC) /* RTA_VIA */
 			payload += nla_total_size(2 + nh->nh_via_alen);
 		if (nh->nh_labels) /* RTA_NEWDST */
 			payload += nla_total_size(nh->nh_labels * 4);
-- 
2.1.4

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

* [PATCH net 4/4] mpls: make via address optional for multipath routes
  2015-12-10 19:30 [PATCH net 0/4] mpls: fixes for nexthops without via addresses Robert Shearman
                   ` (2 preceding siblings ...)
  2015-12-10 19:30 ` [PATCH net 3/4] mpls: fix out-of-bounds access when via address " Robert Shearman
@ 2015-12-10 19:30 ` Robert Shearman
  2015-12-12  5:44 ` [PATCH net 0/4] mpls: fixes for nexthops without via addresses David Miller
  4 siblings, 0 replies; 8+ messages in thread
From: Robert Shearman @ 2015-12-10 19:30 UTC (permalink / raw)
  To: ebiederm, roopa; +Cc: davem, netdev, sam.h.russell, Robert Shearman

The via address is optional for a single path route, yet is mandatory
when the multipath attribute is used:

  # ip -f mpls route add 100 dev lo
  # ip -f mpls route add 101 nexthop dev lo
  RTNETLINK answers: Invalid argument

Make them consistent by making the via address optional when the
RTA_MULTIPATH attribute is being parsed so that both forms of
specifying the route work.

Signed-off-by: Robert Shearman <rshearma@brocade.com>
---
 net/mpls/af_mpls.c | 22 +++++++++++++---------
 1 file changed, 13 insertions(+), 9 deletions(-)

diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
index 7bfc85f52ca8..c32fc411a911 100644
--- a/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -604,10 +604,14 @@ static int mpls_nh_build(struct net *net, struct mpls_route *rt,
 			goto errout;
 	}
 
-	err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table,
-			  __mpls_nh_via(rt, nh));
-	if (err)
-		goto errout;
+	if (via) {
+		err = nla_get_via(via, &nh->nh_via_alen, &nh->nh_via_table,
+				  __mpls_nh_via(rt, nh));
+		if (err)
+			goto errout;
+	} else {
+		nh->nh_via_table = MPLS_NEIGH_TABLE_UNSPEC;
+	}
 
 	err = mpls_nh_assign_dev(net, rt, nh, oif);
 	if (err)
@@ -689,9 +693,6 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg,
 			nla_newdst = nla_find(attrs, attrlen, RTA_NEWDST);
 		}
 
-		if (!nla_via)
-			goto errout;
-
 		err = mpls_nh_build(cfg->rc_nlinfo.nl_net, rt, nh,
 				    rtnh->rtnh_ifindex, nla_via,
 				    nla_newdst);
@@ -1271,7 +1272,8 @@ static int mpls_dump_route(struct sk_buff *skb, u32 portid, u32 seq, int event,
 							    nh->nh_labels,
 							    nh->nh_label))
 				goto nla_put_failure;
-			if (nla_put_via(skb, nh->nh_via_table,
+			if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC &&
+			    nla_put_via(skb, nh->nh_via_table,
 					mpls_nh_via(rt, nh),
 					nh->nh_via_alen))
 				goto nla_put_failure;
@@ -1343,7 +1345,9 @@ static inline size_t lfib_nlmsg_size(struct mpls_route *rt)
 
 		for_nexthops(rt) {
 			nhsize += nla_total_size(sizeof(struct rtnexthop));
-			nhsize += nla_total_size(2 + nh->nh_via_alen);
+			/* RTA_VIA */
+			if (nh->nh_via_table != MPLS_NEIGH_TABLE_UNSPEC)
+				nhsize += nla_total_size(2 + nh->nh_via_alen);
 			if (nh->nh_labels)
 				nhsize += nla_total_size(nh->nh_labels * 4);
 		} endfor_nexthops(rt);
-- 
2.1.4

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

* Re: [PATCH net 1/4] mpls: validate L2 via address length
  2015-12-10 19:30 ` [PATCH net 1/4] mpls: validate L2 via address length Robert Shearman
@ 2015-12-11 22:51   ` roopa
  2015-12-12  0:08     ` roopa
  0 siblings, 1 reply; 8+ messages in thread
From: roopa @ 2015-12-11 22:51 UTC (permalink / raw)
  To: Robert Shearman; +Cc: ebiederm, davem, netdev, sam.h.russell

On 12/10/15, 11:30 AM, Robert Shearman wrote:
> If an L2 via address for an mpls nexthop is specified, the length of
> the L2 address must match that expected by the output device,
> otherwise it could access memory beyond the end of the via address
> buffer in the route.
>
> This check was present prior to commit f8efb73c97e2 ("mpls: multipath
> route support"), but got lost in the refactoring, so add it back,
> applying it to all nexthops in multipath routes.
>
> Fixes: f8efb73c97e2 ("mpls: multipath route support")
> Signed-off-by: Robert Shearman <rshearma@brocade.com>
> ---
>  net/mpls/af_mpls.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
> index c70d750148b6..3be29cb1f658 100644
> --- a/net/mpls/af_mpls.c
> +++ b/net/mpls/af_mpls.c
> @@ -534,6 +534,10 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt,
>  	if (!mpls_dev_get(dev))
>  		goto errout;
>  
> +	if ((nh->nh_via_table == NEIGH_LINK_TABLE) &&
> +	    (dev->addr_len != nh->nh_via_alen))
> +		goto errout;
> +
>
Robert, seems like the right place for this check is nla_get_via ?

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

* Re: [PATCH net 1/4] mpls: validate L2 via address length
  2015-12-11 22:51   ` roopa
@ 2015-12-12  0:08     ` roopa
  0 siblings, 0 replies; 8+ messages in thread
From: roopa @ 2015-12-12  0:08 UTC (permalink / raw)
  To: Robert Shearman; +Cc: ebiederm, davem, netdev, sam.h.russell

On 12/11/15, 2:51 PM, roopa wrote:
> On 12/10/15, 11:30 AM, Robert Shearman wrote:
>> If an L2 via address for an mpls nexthop is specified, the length of
>> the L2 address must match that expected by the output device,
>> otherwise it could access memory beyond the end of the via address
>> buffer in the route.
>>
>> This check was present prior to commit f8efb73c97e2 ("mpls: multipath
>> route support"), but got lost in the refactoring, so add it back,
>> applying it to all nexthops in multipath routes.
>>
>> Fixes: f8efb73c97e2 ("mpls: multipath route support")
>> Signed-off-by: Robert Shearman <rshearma@brocade.com>
>> ---
>>  net/mpls/af_mpls.c | 4 ++++
>>  1 file changed, 4 insertions(+)
>>
>> diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
>> index c70d750148b6..3be29cb1f658 100644
>> --- a/net/mpls/af_mpls.c
>> +++ b/net/mpls/af_mpls.c
>> @@ -534,6 +534,10 @@ static int mpls_nh_assign_dev(struct net *net, struct mpls_route *rt,
>>  	if (!mpls_dev_get(dev))
>>  		goto errout;
>>  
>> +	if ((nh->nh_via_table == NEIGH_LINK_TABLE) &&
>> +	    (dev->addr_len != nh->nh_via_alen))
>> +		goto errout;
>> +
>>
> Robert, seems like the right place for this check is nla_get_via ?
never mind. This looks fine.

Acked-by: Roopa Prabhu <roopa@cumulusnetworks.com>

Thanks!.

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

* Re: [PATCH net 0/4] mpls: fixes for nexthops without via addresses
  2015-12-10 19:30 [PATCH net 0/4] mpls: fixes for nexthops without via addresses Robert Shearman
                   ` (3 preceding siblings ...)
  2015-12-10 19:30 ` [PATCH net 4/4] mpls: make via address optional for multipath routes Robert Shearman
@ 2015-12-12  5:44 ` David Miller
  4 siblings, 0 replies; 8+ messages in thread
From: David Miller @ 2015-12-12  5:44 UTC (permalink / raw)
  To: rshearma; +Cc: ebiederm, roopa, netdev, sam.h.russell

From: Robert Shearman <rshearma@brocade.com>
Date: Thu, 10 Dec 2015 19:30:47 +0000

> These four fixes all apply to the case of having an mpls route with an
> output device, but without a nexthop.

Series applied, thanks.

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

end of thread, other threads:[~2015-12-12  5:44 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-10 19:30 [PATCH net 0/4] mpls: fixes for nexthops without via addresses Robert Shearman
2015-12-10 19:30 ` [PATCH net 1/4] mpls: validate L2 via address length Robert Shearman
2015-12-11 22:51   ` roopa
2015-12-12  0:08     ` roopa
2015-12-10 19:30 ` [PATCH net 2/4] mpls: don't dump RTA_VIA attribute if not specified Robert Shearman
2015-12-10 19:30 ` [PATCH net 3/4] mpls: fix out-of-bounds access when via address " Robert Shearman
2015-12-10 19:30 ` [PATCH net 4/4] mpls: make via address optional for multipath routes Robert Shearman
2015-12-12  5:44 ` [PATCH net 0/4] mpls: fixes for nexthops without via addresses David Miller

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.