Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gre: Fix GREv4 TCPv6 segmentation.

For ipv6 traffic, GRE can generate packet with strange GSO
bits, e.g. ipv4 packet with SKB_GSO_TCPV6 flag set. Therefore
following patch relaxes check in inet gso handler to allow
such packet for segmentation.
This patch also fixes wrong skb->protocol set that was done in
gre_gso_segment() handler.

Reported-by: Steinar H. Gunderson <sesse@google.com>
CC: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Acked-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Pravin B Shelar and committed by
David S. Miller
9b3eb5ed 83401eb4

+4 -1
+1
net/ipv4/af_inet.c
··· 1293 1293 SKB_GSO_DODGY | 1294 1294 SKB_GSO_TCP_ECN | 1295 1295 SKB_GSO_GRE | 1296 + SKB_GSO_TCPV6 | 1296 1297 SKB_GSO_UDP_TUNNEL | 1297 1298 0))) 1298 1299 goto out;
+3 -1
net/ipv4/gre.c
··· 121 121 int ghl = GRE_HEADER_SECTION; 122 122 struct gre_base_hdr *greh; 123 123 int mac_len = skb->mac_len; 124 + __be16 protocol = skb->protocol; 124 125 int tnl_hlen; 125 126 bool csum; 126 127 ··· 151 150 152 151 /* setup inner skb. */ 153 152 if (greh->protocol == htons(ETH_P_TEB)) { 154 - struct ethhdr *eth = eth_hdr(skb); 153 + struct ethhdr *eth = (struct ethhdr *)skb_inner_mac_header(skb); 155 154 skb->protocol = eth->h_proto; 156 155 } else { 157 156 skb->protocol = greh->protocol; ··· 200 199 skb_reset_mac_header(skb); 201 200 skb_set_network_header(skb, mac_len); 202 201 skb->mac_len = mac_len; 202 + skb->protocol = protocol; 203 203 } while ((skb = skb->next)); 204 204 out: 205 205 return segs;