Skip to content
  • Xin Long's avatar
    sctp: call gso_reset_checksum when computing checksum in sctp_gso_segment · fc228abc
    Xin Long authored
    
    
    Jianlin reported a panic when running sctp gso over gre over vlan device:
    
      [   84.772930] RIP: 0010:do_csum+0x6d/0x170
      [   84.790605] Call Trace:
      [   84.791054]  csum_partial+0xd/0x20
      [   84.791657]  gre_gso_segment+0x2c3/0x390
      [   84.792364]  inet_gso_segment+0x161/0x3e0
      [   84.793071]  skb_mac_gso_segment+0xb8/0x120
      [   84.793846]  __skb_gso_segment+0x7e/0x180
      [   84.794581]  validate_xmit_skb+0x141/0x2e0
      [   84.795297]  __dev_queue_xmit+0x258/0x8f0
      [   84.795949]  ? eth_header+0x26/0xc0
      [   84.796581]  ip_finish_output2+0x196/0x430
      [   84.797295]  ? skb_gso_validate_network_len+0x11/0x80
      [   84.798183]  ? ip_finish_output+0x169/0x270
      [   84.798875]  ip_output+0x6c/0xe0
      [   84.799413]  ? ip_append_data.part.50+0xc0/0xc0
      [   84.800145]  iptunnel_xmit+0x144/0x1c0
      [   84.800814]  ip_tunnel_xmit+0x62d/0x930 [ip_tunnel]
      [   84.801699]  gre_tap_xmit+0xac/0xf0 [ip_gre]
      [   84.802395]  dev_hard_start_xmit+0xa5/0x210
      [   84.803086]  sch_direct_xmit+0x14f/0x340
      [   84.803733]  __dev_queue_xmit+0x799/0x8f0
      [   84.804472]  ip_finish_output2+0x2e0/0x430
      [   84.805255]  ? skb_gso_validate_network_len+0x11/0x80
      [   84.806154]  ip_output+0x6c/0xe0
      [   84.806721]  ? ip_append_data.part.50+0xc0/0xc0
      [   84.807516]  sctp_packet_transmit+0x716/0xa10 [sctp]
      [   84.808337]  sctp_outq_flush+0xd7/0x880 [sctp]
    
    It was caused by SKB_GSO_CB(skb)->csum_start not set in sctp_gso_segment.
    sctp_gso_segment() calls skb_segment() with 'feature | NETIF_F_HW_CSUM',
    which causes SKB_GSO_CB(skb)->csum_start not to be set in skb_segment().
    
    For TCP/UDP, when feature supports HW_CSUM, CHECKSUM_PARTIAL will be set
    and gso_reset_checksum will be called to set SKB_GSO_CB(skb)->csum_start.
    
    So SCTP should do the same as TCP/UDP, to call gso_reset_checksum() when
    computing checksum in sctp_gso_segment.
    
    Reported-by: default avatarJianlin Shi <jishi@redhat.com>
    Signed-off-by: default avatarXin Long <lucien.xin@gmail.com>
    Acked-by: default avatarNeil Horman <nhorman@tuxdriver.com>
    Acked-by: default avatarMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>
    Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
    fc228abc