Commit 1f2e900a authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'bareudp-pull-inner-ip-header-on-xmit-recv'

Guillaume Nault says:

====================
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.
====================

Link: https://patch.msgid.link/cover.1726046181.git.gnault@redhat.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 5abfdfd4 c471236b
Loading
Loading
Loading
Loading
+24 −2
Original line number Diff line number Diff line
@@ -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
@@ -301,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;

@@ -368,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;