mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
xfrm: Fix inner mode lookup in tunnel mode GSO segmentation
Commit61fafbee6c("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:61fafbee6c("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>
This commit is contained in:
committed by
Steffen Klassert
parent
8f7aa3d3c7
commit
3d5221af9c
@@ -122,8 +122,8 @@ static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x,
|
||||
struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
{
|
||||
const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x,
|
||||
XFRM_MODE_SKB_CB(skb)->protocol);
|
||||
struct xfrm_offload *xo = xfrm_offload(skb);
|
||||
const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x, xo->proto);
|
||||
__be16 type = inner_mode->family == AF_INET6 ? htons(ETH_P_IPV6)
|
||||
: htons(ETH_P_IP);
|
||||
|
||||
|
||||
@@ -158,8 +158,8 @@ static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x,
|
||||
struct sk_buff *skb,
|
||||
netdev_features_t features)
|
||||
{
|
||||
const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x,
|
||||
XFRM_MODE_SKB_CB(skb)->protocol);
|
||||
struct xfrm_offload *xo = xfrm_offload(skb);
|
||||
const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x, xo->proto);
|
||||
__be16 type = inner_mode->family == AF_INET ? htons(ETH_P_IP)
|
||||
: htons(ETH_P_IPV6);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user