Skip to contentSkip to conversation

bareudp: Pull inner IP header on xmit/recv.

PATCH Applied Guillaume Nault 3 participants 6 messages Sep 11, 2024 – Sep 13, 2024

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

v2 cover bareudp: Pull inner IP header on xmit/recv.

Bareudp accesses the inner IP header in its xmit and recv paths. However it doesn't ensure that this header is part of skb->head.

Both vxlan and geneve have received fixes for similar problems in the past. This series fixes bareudp using the same approach.

Guillaume Nault (2):
bareudp: Pull inner IP header in bareudp_udp_encap_recv().
bareudp: Pull inner IP header on xmit.

 drivers/net/bareudp.c | 26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
Signature · 1 line
2.39.2
#1 lore raw

PATCH v2 1/2 bareudp: Pull inner IP header in bareudp_udp_encap_recv().

Bareudp reads the inner IP header to get the ECN value. Therefore, it needs to ensure that it's part of the skb's linear data.

This is similar to the vxlan and geneve fixes for that same problem:
* commit f7789419137b ("vxlan: Pull inner IP header in vxlan_rcv().")
* commit 1ca1ba465e55 ("geneve: make sure to pull inner header in

    geneve_rx()")
Fixes 571912c69f0e ("net: UDP tunnel encapsulation module for tunnelling different protocols like MPLS, IP, NSH etc.")

---
v2: Add Fixes: tag.

 drivers/net/bareudp.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)
drivers/net/bareudp.c +18 -2
index 7aca0544fb29..b4e820a123ca 100644
@@ -68,6 +68,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	__be16 proto;
 	void *oiph;
 	int err;
+	int nh;
 
 	bareudp = rcu_dereference_sk_user_data(sk);
 	if (!bareudp)
@@ -148,10 +149,25 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
 	}
 	skb_dst_set(skb, &tun_dst->dst);
 	skb->dev = bareudp->dev;
-	oiph = skb_network_header(skb);
-	skb_reset_network_header(skb);
 	skb_reset_mac_header(skb);
 
+	/* Save offset of outer header relative to skb->head,
+	 * because we are going to reset the network header to the inner header
+	 * and might change skb->head.
+	 */
+	nh = skb_network_header(skb) - skb->head;
+
+	skb_reset_network_header(skb);
+
+	if (!pskb_inet_may_pull(skb)) {
+		DEV_STATS_INC(bareudp->dev, rx_length_errors);
+		DEV_STATS_INC(bareudp->dev, rx_errors);
+		goto drop;
+	}
+
+	/* Get the outer header. */
+	oiph = skb->head + nh;
+
 	if (!ipv6_mod_enabled() || family == AF_INET)
 		err = IP_ECN_decapsulate(oiph, skb);
 	else
Signature · 1 line
2.39.2
Reviewed-by on v2 1/2
#2 lore raw

Re: [PATCH net v2 1/2] bareudp: Pull inner IP header in bareudp_udp_encap_recv().

Quoted 10 lines · Guillaume Nault

Bareudp reads the inner IP header to get the ECN value. Therefore, it needs to ensure that it's part of the skb's linear data.

This is similar to the vxlan and geneve fixes for that same problem:
* commit f7789419137b ("vxlan: Pull inner IP header in vxlan_rcv().")
* commit 1ca1ba465e55 ("geneve: make sure to pull inner header in

    geneve_rx()")
Fixes 571912c69f0e ("net: UDP tunnel encapsulation module for tunnelling different protocols like MPLS, IP, NSH etc.")
#3 lore raw

PATCH v2 2/2 bareudp: Pull inner IP header on xmit.

In reply to Guillaume Nault

Both bareudp_xmit_skb() and bareudp6_xmit_skb() read their skb's inner IP header to get its ECN value (with ip_tunnel_ecn_encap()). Therefore we need to ensure that the inner IP header is part of the skb's linear data.

Fixes 571912c69f0e ("net: UDP tunnel encapsulation module for tunnelling different protocols like MPLS, IP, NSH etc.")

---
v2: Add Fixes: tag.

 drivers/net/bareudp.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/net/bareudp.c +6 -0
index b4e820a123ca..e80992b4f9de 100644
@@ -317,6 +317,9 @@ static int bareudp_xmit_skb(struct sk_buff *skb, struct net_device *dev,
 	__be32 saddr;
 	int err;
 
+	if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
+		return -EINVAL;
+
 	if (!sock)
 		return -ESHUTDOWN;
 
@@ -384,6 +387,9 @@ static int bareudp6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
 	__be16 sport;
 	int err;
 
+	if (!skb_vlan_inet_prepare(skb, skb->protocol != htons(ETH_P_TEB)))
+		return -EINVAL;
+
 	if (!sock)
 		return -ESHUTDOWN;
 
Signature · 1 line
2.39.2
Reviewed-by on v2 2/2
#4 lore raw

Re: [PATCH net v2 2/2] bareudp: Pull inner IP header on xmit.

Quoted 7 lines · Guillaume Nault

Both bareudp_xmit_skb() and bareudp6_xmit_skb() read their skb's inner IP header to get its ECN value (with ip_tunnel_ecn_encap()). Therefore we need to ensure that the inner IP header is part of the skb's linear data.

Fixes 571912c69f0e ("net: UDP tunnel encapsulation module for tunnelling different protocols like MPLS, IP, NSH etc.")
#5 lore raw
In reply to Guillaume Nault
This series was applied to netdev/net.git (main) by Jakub Kicinski <[email protected]>:

Hello:

This series was applied to netdev/net.git (main)
by Jakub Kicinski <[email protected]>:

Quoted 11 lines · On Wed, 11 Sep 2024 11:20:51 +0200 you wrote:

Bareudp accesses the inner IP header in its xmit and recv paths. However it doesn't ensure that this header is part of skb->head.

Both vxlan and geneve have received fixes for similar problems in the past. This series fixes bareudp using the same approach.

Guillaume Nault (2):
bareudp: Pull inner IP header in bareudp_udp_encap_recv().
bareudp: Pull inner IP header on xmit.

[...]

Here is the summary with links:
- [net,v2,1/2] bareudp: Pull inner IP header in bareudp_udp_encap_recv().

    https://git.kernel.org/netdev/net/c/45fa29c85117
  - [net,v2,2/2] bareudp: Pull inner IP header on xmit.
    https://git.kernel.org/netdev/net/c/c471236b2359

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html