Commit a257f093 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge branch 'net-gro-add-flush-flush_id-checks-and-fix-wrong-offset-in-udp'

Richard Gobert says:

====================
net: gro: add flush/flush_id checks and fix wrong offset in udp

This series fixes a bug in the complete phase of UDP in GRO, in which
socket lookup fails due to using network_header when parsing encapsulated
packets. The fix is to add network_offset and inner_network_offset to
napi_gro_cb and use these offsets for socket lookup.

In addition p->flush/flush_id should be checked in all UDP flows. The
same logic from tcp_gro_receive is applied for all flows in
udp_gro_receive_segment. This prevents packets with mismatching network
headers (flush/flush_id turned on) from merging in UDP GRO.

The original series includes a change to vxlan test which adds the local
parameter to prevent similar future bugs. I plan to submit it separately to
net-next.

This series is part of a previously submitted series to net-next:
https://lore.kernel.org/all/20240408141720.98832-1-richardbgobert@gmail.com/

v3 -> v4:
 - Store network offsets, and use them only in udp_gro_complete flows
 - Correct commit hash used in Fixes tag
 - v3:
 https://lore.kernel.org/netdev/20240424163045.123528-1-richardbgobert@gmail.com/

v2 -> v3:
 - Add network_offsets and fix udp bug in a single commit to make backporting easier
 - Write to inner_network_offset in {inet,ipv6}_gro_receive
 - Use network_offsets union in tcp[46]_gro_complete as well
 - v2:
 https://lore.kernel.org/netdev/20240419153542.121087-1-richardbgobert@gmail.com/

v1 -> v2:
 - Use network_offsets instead of p_poff param as suggested by Willem
 - Check flush before postpull, and for all UDP GRO flows
 - v1:
 https://lore.kernel.org/netdev/20240412152120.115067-1-richardbgobert@gmail.com/
====================

Link: https://lore.kernel.org/r/20240430143555.126083-1-richardbgobert@gmail.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents fc1092f5 5babae77
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -87,6 +87,15 @@ struct napi_gro_cb {

	/* used to support CHECKSUM_COMPLETE for tunneling protocols */
	__wsum	csum;

	/* L3 offsets */
	union {
		struct {
			u16 network_offset;
			u16 inner_network_offset;
		};
		u16 network_offsets[2];
	};
};

#define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
+2 −0
Original line number Diff line number Diff line
@@ -478,6 +478,8 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
	if (unlikely(!vhdr))
		goto out;

	NAPI_GRO_CB(skb)->network_offsets[NAPI_GRO_CB(skb)->encap_mark] = hlen;

	type = vhdr->h_vlan_encapsulated_proto;

	ptype = gro_find_receive_by_type(type);
+1 −0
Original line number Diff line number Diff line
@@ -371,6 +371,7 @@ static inline void skb_gro_reset_offset(struct sk_buff *skb, u32 nhoff)
	const skb_frag_t *frag0;
	unsigned int headlen;

	NAPI_GRO_CB(skb)->network_offset = 0;
	NAPI_GRO_CB(skb)->data_offset = 0;
	headlen = skb_headlen(skb);
	NAPI_GRO_CB(skb)->frag0 = skb->data;
+1 −0
Original line number Diff line number Diff line
@@ -1572,6 +1572,7 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
	/* The above will be needed by the transport layer if there is one
	 * immediately following this IP hdr.
	 */
	NAPI_GRO_CB(skb)->inner_network_offset = off;

	/* Note : No need to call skb_gro_postpull_rcsum() here,
	 * as we already checked checksum over ipv4 header was 0
+2 −1
Original line number Diff line number Diff line
@@ -532,7 +532,8 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb,
struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
				 __be16 sport, __be16 dport)
{
	const struct iphdr *iph = ip_hdr(skb);
	const u16 offset = NAPI_GRO_CB(skb)->network_offsets[skb->encapsulation];
	const struct iphdr *iph = (struct iphdr *)(skb->data + offset);
	struct net *net = dev_net(skb->dev);
	int iif, sdif;

Loading