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

Configure Feed

Select the types of activity you want to include in your feed.

xfrm: Fix inner mode lookup in tunnel mode GSO segmentation

Commit 61fafbee6cfe ("xfrm: Determine inner GSO type from packet inner
protocol") attempted to fix GSO segmentation by reading the inner
protocol from XFRM_MODE_SKB_CB(skb)->protocol. This was incorrect
because the field holds the inner L4 protocol (TCP/UDP) instead of the
required tunnel protocol. Also, the memory location (shared by
XFRM_SKB_CB(skb) which could be overwritten by xfrm_replay_overflow())
is prone to corruption. This combination caused the kernel to select
the wrong inner mode and get the wrong address family.

The correct value is in xfrm_offload(skb)->proto, which is set from
the outer tunnel header's protocol field by esp[4|6]_gso_encap(). It
is initialized by xfrm[4|6]_tunnel_encap_add() to either IPPROTO_IPIP
or IPPROTO_IPV6, using xfrm_af2proto() and correctly reflects the
inner packet's address family.

Fixes: 61fafbee6cfe ("xfrm: Determine inner GSO type from packet inner protocol")
Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>

authored by

Jianbo Liu and committed by
Steffen Klassert
3d5221af 8f7aa3d3

+4 -4
+2 -2
net/ipv4/esp4_offload.c
··· 122 122 struct sk_buff *skb, 123 123 netdev_features_t features) 124 124 { 125 - const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x, 126 - XFRM_MODE_SKB_CB(skb)->protocol); 125 + struct xfrm_offload *xo = xfrm_offload(skb); 126 + const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x, xo->proto); 127 127 __be16 type = inner_mode->family == AF_INET6 ? htons(ETH_P_IPV6) 128 128 : htons(ETH_P_IP); 129 129
+2 -2
net/ipv6/esp6_offload.c
··· 158 158 struct sk_buff *skb, 159 159 netdev_features_t features) 160 160 { 161 - const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x, 162 - XFRM_MODE_SKB_CB(skb)->protocol); 161 + struct xfrm_offload *xo = xfrm_offload(skb); 162 + const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x, xo->proto); 163 163 __be16 type = inner_mode->family == AF_INET ? htons(ETH_P_IP) 164 164 : htons(ETH_P_IPV6); 165 165