• Xin Long's avatar
    xfrm: call xfrm_output_gso when inner_protocol is set in xfrm_output · a204aef9
    Xin Long authored
    An use-after-free crash can be triggered when sending big packets over
    vxlan over esp with esp offload enabled:
    
      [] BUG: KASAN: use-after-free in ipv6_gso_pull_exthdrs.part.8+0x32c/0x4e0
      [] Call Trace:
      []  dump_stack+0x75/0xa0
      []  kasan_report+0x37/0x50
      []  ipv6_gso_pull_exthdrs.part.8+0x32c/0x4e0
      []  ipv6_gso_segment+0x2c8/0x13c0
      []  skb_mac_gso_segment+0x1cb/0x420
      []  skb_udp_tunnel_segment+0x6b5/0x1c90
      []  inet_gso_segment+0x440/0x1380
      []  skb_mac_gso_segment+0x1cb/0x420
      []  esp4_gso_segment+0xae8/0x1709 [esp4_offload]
      []  inet_gso_segment+0x440/0x1380
      []  skb_mac_gso_segment+0x1cb/0x420
      []  __skb_gso_segment+0x2d7/0x5f0
      []  validate_xmit_skb+0x527/0xb10
      []  __dev_queue_xmit+0x10f8/0x2320 <---
      []  ip_finish_output2+0xa2e/0x1b50
      []  ip_output+0x1a8/0x2f0
      []  xfrm_output_resume+0x110e/0x15f0
      []  __xfrm4_output+0xe1/0x1b0
      []  xfrm4_output+0xa0/0x200
      []  iptunnel_xmit+0x5a7/0x920
      []  vxlan_xmit_one+0x1658/0x37a0 [vxlan]
      []  vxlan_xmit+0x5e4/0x3ec8 [vxlan]
      []  dev_hard_start_xmit+0x125/0x540
      []  __dev_queue_xmit+0x17bd/0x2320  <---
      []  ip6_finish_output2+0xb20/0x1b80
      []  ip6_output+0x1b3/0x390
      []  ip6_xmit+0xb82/0x17e0
      []  inet6_csk_xmit+0x225/0x3d0
      []  __tcp_transmit_skb+0x1763/0x3520
      []  tcp_write_xmit+0xd64/0x5fe0
      []  __tcp_push_pending_frames+0x8c/0x320
      []  tcp_sendmsg_locked+0x2245/0x3500
      []  tcp_sendmsg+0x27/0x40
    
    As on the tx path of vxlan over esp, skb->inner_network_header would be
    set on vxlan_xmit() and xfrm4_tunnel_encap_add(), and the later one can
    overwrite the former one. It causes skb_udp_tunnel_segment() to use a
    wrong skb->inner_network_header, then the issue occurs.
    
    This patch is to fix it by calling xfrm_output_gso() instead when the
    inner_protocol is set, in which gso_segment of inner_protocol will be
    done first.
    
    While at it, also improve some code around.
    
    Fixes: 7862b405 ("esp: Add gso handlers for esp4 and esp6")
    Reported-by: default avatarXiumei Mu <xmu@redhat.com>
    Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
    Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
    a204aef9
xfrm_output.c 15.5 KB