Skip to contentSkip to conversation

sctp: fix src address selection if using secondary address

PATCH In review Marcelo Ricardo Leitner 4 participants 6 messages Jul 17, 2015 – Jul 21, 2015

Subsystems (3)
lore
Share & tools
lore

Marcelo Ricardo Leitner

author maintainer
#0 lore raw

v2 cover sctp: fix src address selection if using secondary address

This series improves the way SCTP chooses its src address so that the choosen one will always belong to the interface being used for output.

v1->v2:
- split out the refactoring from the fix itself
- Doing a full reverse routing as in v1 is not necessary. Only looking for the interface that has the address and comparing its number is enough.

Marcelo Ricardo Leitner (2):
sctp: reduce indent level on sctp_v4_get_dst
sctp: fix src address selection if using secondary addresses

 net/sctp/protocol.c | 42 +++++++++++++++++++++++++++---------------
 1 file changed, 27 insertions(+), 15 deletions(-)
Signature · 1 line
2.4.1
author maintainer
#1 lore raw

PATCH v2 1/2 sctp: reduce indent level on sctp_v4_get_dst

Paves the day for the next patch. Functionality stays untouched.

---
 net/sctp/protocol.c | 32 +++++++++++++++++---------------
 1 file changed, 17 insertions(+), 15 deletions(-)
net/sctp/protocol.c +17 -15
index 59e80356672bdf89777265ae1f8c384792dfb98c..fa80fe4f23629fc3c3f5c44f99dbf3cc524cc6a0 100644
@@ -489,21 +489,23 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
 		if (!laddr->valid)
 			continue;
-		if ((laddr->state = SCTP_ADDR_SRC) &&
-		    (AF_INET = laddr->a.sa.sa_family)) {
-			fl4->fl4_sport = laddr->a.v4.sin_port;
-			flowi4_update_output(fl4,
-					     asoc->base.sk->sk_bound_dev_if,
-					     RT_CONN_FLAGS(asoc->base.sk),
-					     daddr->v4.sin_addr.s_addr,
-					     laddr->a.v4.sin_addr.s_addr);
-
-			rt = ip_route_output_key(sock_net(sk), fl4);
-			if (!IS_ERR(rt)) {
-				dst = &rt->dst;
-				goto out_unlock;
-			}
-		}
+		if (laddr->state != SCTP_ADDR_SRC ||
+		    AF_INET != laddr->a.sa.sa_family)
+			continue;
+
+		fl4->fl4_sport = laddr->a.v4.sin_port;
+		flowi4_update_output(fl4,
+				     asoc->base.sk->sk_bound_dev_if,
+				     RT_CONN_FLAGS(asoc->base.sk),
+				     daddr->v4.sin_addr.s_addr,
+				     laddr->a.v4.sin_addr.s_addr);
+
+		rt = ip_route_output_key(sock_net(sk), fl4);
+		if (IS_ERR(rt))
+			continue;
+
+		dst = &rt->dst;
+		break;
 	}
 
 out_unlock:
Signature · 1 line
2.4.1
author maintainer
#2 lore raw

PATCH v2 2/2 sctp: fix src address selection if using secondary addresses

In reply to Marcelo Ricardo Leitner

In short, sctp is likely to incorrectly choose src address if socket is bound to secondary addresses. This patch fixes it by adding a new check that checks if such src address belongs to the interface that routing identified as output.

This is enough to avoid rp_filter drops on remote peer.

Details:

Currently, sctp will do a routing attempt without specifying the src address and compare the returned value (preferred source) with the addresses that the socket is bound to. When using secondary addresses, this will not match.

Then it will try specifying each of the addresses that the socket is bound to and re-routing, checking if that address is valid as src for that dst. Thing is, this check alone is weak:

# ip r l
192.168.100.0/24 dev eth1  proto kernel  scope link  src 192.168.100.149
192.168.122.0/24 dev eth0  proto kernel  scope link  src 192.168.122.147
# ip a l
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:15:18:6a brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.147/24 brd 192.168.122.255 scope global dynamic eth0
       valid_lft 2160sec preferred_lft 2160sec
    inet 192.168.122.148/24 scope global secondary eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe15:186a/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:b3:91:46 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.149/24 brd 192.168.100.255 scope global dynamic eth1
       valid_lft 2162sec preferred_lft 2162sec
    inet 192.168.100.148/24 scope global secondary eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:feb3:9146/64 scope link
       valid_lft forever preferred_lft forever
4: ens9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:05:47:ee brd ff:ff:ff:ff:ff:ff
    inet6 fe80::5054:ff:fe05:47ee/64 scope link
       valid_lft forever preferred_lft forever
# ip r g 192.168.100.193 from 192.168.122.148
192.168.100.193 from 192.168.122.148 dev eth1
    cache

Even if you specify an interface:

# ip r g 192.168.100.193 from 192.168.122.148 oif eth1
192.168.100.193 from 192.168.122.148 dev eth1
    cache

Although this would be valid, peers using rp_filter will drop such packets as their src doesn't match the routes for that interface.

---
 net/sctp/protocol.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
net/sctp/protocol.c +10 -0
index fa80fe4f23629fc3c3f5c44f99dbf3cc524cc6a0..4345790ad3266c353eeac5398593c2a9ce4effda 100644
@@ -487,6 +487,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 	 */
 	rcu_read_lock();
 	list_for_each_entry_rcu(laddr, &bp->address_list, list) {
+		struct net_device *odev;
+
 		if (!laddr->valid)
 			continue;
 		if (laddr->state != SCTP_ADDR_SRC ||
@@ -504,6 +506,14 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 		if (IS_ERR(rt))
 			continue;
 
+		/* Ensure the src address belongs to the output
+		 * interface.
+		 */
+		odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr,
+				     false);
+		if (!odev || odev->ifindex != fl4->flowi4_oif)
+			continue;
+
 		dst = &rt->dst;
 		break;
 	}
Signature · 1 line
2.4.1
Acked-by on the v2 series
#3 lore raw
In reply to Marcelo Ricardo Leitner
Quoted 9 lines · Marcelo Ricardo Leitner

This series improves the way SCTP chooses its src address so that the choosen one will always belong to the interface being used for output.

v1->v2:
- split out the refactoring from the fix itself
- Doing a full reverse routing as in v1 is not necessary. Only looking for the interface that has the address and comparing its number is enough.

Quoted 4 lines

Marcelo Ricardo Leitner (2):
sctp: reduce indent level on sctp_v4_get_dst
sctp: fix src address selection if using secondary addresses

For the series:

Thanks
-vlad

Quoted 3 lines
 net/sctp/protocol.c | 42 +++++++++++++++++++++++++++---------------
 1 file changed, 27 insertions(+), 15 deletions(-)
Acked-by on the v2 series
#4 lore raw
In reply to Marcelo Ricardo Leitner
Quoted 9 lines · Marcelo Ricardo Leitner

This series improves the way SCTP chooses its src address so that the choosen one will always belong to the interface being used for output.

v1->v2:
- split out the refactoring from the fix itself
- Doing a full reverse routing as in v1 is not necessary. Only looking for the interface that has the address and comparing its number is enough.

Quoted 15 lines

Marcelo Ricardo Leitner (2):
sctp: reduce indent level on sctp_v4_get_dst
sctp: fix src address selection if using secondary addresses

 net/sctp/protocol.c | 42 +++++++++++++++++++++++++++---------------
 1 file changed, 27 insertions(+), 15 deletions(-)
Signature · 6 lines
2.4.1

--
To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
maintainer
#5 lore raw
In reply to Marcelo Ricardo Leitner

From: Marcelo Ricardo Leitner <[email protected]>
Date: Fri, 17 Jul 2015 12:34:16 -0300

Quoted 8 lines

This series improves the way SCTP chooses its src address so that the choosen one will always belong to the interface being used for output.

v1->v2:
- split out the refactoring from the fix itself
- Doing a full reverse routing as in v1 is not necessary. Only looking for the interface that has the address and comparing its number is enough.

Series applied, thanks.