[OpenWrt-Devel] [PATCH] kernel/generic: (try) fixing MAP-E patch misbehaving in 4.0

Daniel Golle daniel at makrotopia.org
Wed May 23 14:18:46 EDT 2018


Hi Axel,
Hi Steven,

revisiting your patch, I try to understand what we need to fix here
or if the issue has already been resolved in the meantime.
See below:

On Fri, Feb 09, 2018 at 01:20:53PM +0100, Axel Neumann wrote:
> Hello,
> 
> the 666 kernel patches [1,2,3] break the possibility for using an ip4ip6
> tunnel interface as a fall back interface accepting ip4-in-ip6 tunneled
> packets from any remote address. This works out of the box with any
> normal (non-666-patched) 4.4 (and earlier) kernel and can be configured
> by setting up an 'ip -6 tunnel' with type 'any' or 'ip4ip6' and a remote
> address of '::'.
> 
> The misbehavior comes with line 290 of [3] which discards all packets
> that do not show the expected saddr, even if no single fmr rule was
> defined and despite the validity of the saddr was already approved earlier.
> 
> Attached diff would re-enable this fall back capability without
> affecting the behavior in case of any configured FMR rules.
> 
> It would be nice if the proposed or a similar fix could be applied asap
> because currently I see no way of recovering the standard kernel
> behavior which breaks certain desired bmx6 and bmx7 tunneling features.
> 
> Best regards
> /axel
> 
> 
> [1]
> https://github.com/openwrt-mirror/openwrt/blob/master/target/linux/generic/patches-3.18/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch
> [2]
> https://github.com/openwrt-mirror/openwrt/blob/master/target/linux/generic/patches-4.1/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch
> [3]
> https://github.com/openwrt-mirror/openwrt/blob/master/target/linux/generic/patches-4.4/666-Add-support-for-MAP-E-FMRs-mesh-mode.patch#L290
> 

The patch below is supposedly applied to net/ipv6/ip6_tunnel.c after
666-Add-support-for-MAP-E-FMRs-mesh-mode.patch has been applied, right?

> 1032c1032
> < 				if (fmr) {
> ---
> > 				if (fmr)
> 1036,1039c1036,1038
> < 					if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) {
> < 						rcu_read_unlock();
> < 						goto discard;
> < 					}
> ---
> > 				if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) {
> > 					rcu_read_unlock();
> > 					goto discard;

The original hunk in 666-Add-support-for-MAP-E-FMRs-mesh-mode.patch
looks like this

---
@@ -832,6 +950,27 @@ static int __ip6_tnl_rcv(struct ip6_tnl
 	skb_reset_network_header(skb);
 	memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
 
+	if (tpi->proto == htons(ETH_P_IP) &&
+		!ipv6_addr_equal(&ipv6h->saddr, &tunnel->parms.raddr)) {
+			/* Packet didn't come from BR, so lookup FMR */
+			struct __ip6_tnl_fmr *fmr;
+			struct in6_addr expected = tunnel->parms.raddr;
+			for (fmr = tunnel->parms.fmrs; fmr; fmr = fmr->next)
+				if (ipv6_prefix_equal(&ipv6h->saddr,
+					&fmr->ip6_prefix, fmr->ip6_prefix_len))
+						break;
+
+			/* Check that IPv6 matches IPv4 source to prevent spoofing */
+			if (fmr)
+				ip4ip6_fmr_calc(&expected, ip_hdr(skb),
+						skb_tail_pointer(skb), fmr, false);
+
+			if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) {
+				rcu_read_unlock();
+				goto drop;
+			}
+	}
+
 	__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
 
 	err = dscp_ecn_decapsulate(tunnel, ipv6h, skb);
---

Reading this it is obvious that yout patch can be reverse-applied to
ip6_tunnel.c after 666-Add-support-for-MAP-E-FMRs-mesh-mode.patch has
been applied. As the MAP-E patch apparently hasn't been touched for
quite a while I assume that it must have looked the same at the time
when you sent the patch and you just used diff in a slightly
counter-intuitive way...

Just to make things crystal clear:
You are suggesting to change the patch above to rather be like:
---
@@ -832,6 +951,28 @@ static int __ip6_tnl_rcv(struct ip6_tnl
 	skb_reset_network_header(skb);
 	memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
 
+	if (tpi->proto == htons(ETH_P_IP) &&
+		!ipv6_addr_equal(&ipv6h->saddr, &tunnel->parms.raddr)) {
+			/* Packet didn't come from BR, so lookup FMR */
+			struct __ip6_tnl_fmr *fmr;
+			struct in6_addr expected = tunnel->parms.raddr;
+			for (fmr = tunnel->parms.fmrs; fmr; fmr = fmr->next)
+				if (ipv6_prefix_equal(&ipv6h->saddr,
+					&fmr->ip6_prefix, fmr->ip6_prefix_len))
+						break;
+
+			/* Check that IPv6 matches IPv4 source to prevent spoofing */
+			if (fmr) {
+				ip4ip6_fmr_calc(&expected, ip_hdr(skb),
+						skb_tail_pointer(skb), fmr, false);
+
+				if (!ipv6_addr_equal(&ipv6h->saddr, &expected)) {
+					rcu_read_unlock();
+					goto drop;
+				}
+			}
+	}
+
 	__skb_tunnel_rx(skb, tunnel->dev, tunnel->net);
 
 	err = dscp_ecn_decapsulate(tunnel, ipv6h, skb);
---

Please confirm that this was your original intention, so we can move
forward with the discussion and this is an IPv6 show-stopper for
LibreMesh as well...


Cheers


Daniel

_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
http://lists.infradead.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list