@@ -796,8 +796,8 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
796
796
struct sk_buff * skb ),
797
797
bool log_ecn_err )
798
798
{
799
- const struct ipv6hdr * ipv6h = ipv6_hdr ( skb ) ;
800
- int err ;
799
+ const struct ipv6hdr * ipv6h ;
800
+ int nh , err ;
801
801
802
802
if ((!(tpi -> flags & TUNNEL_CSUM ) &&
803
803
(tunnel -> parms .i_flags & TUNNEL_CSUM )) ||
@@ -829,15 +829,30 @@ static int __ip6_tnl_rcv(struct ip6_tnl *tunnel, struct sk_buff *skb,
829
829
goto drop ;
830
830
}
831
831
832
- ipv6h = ipv6_hdr (skb );
833
832
skb -> protocol = eth_type_trans (skb , tunnel -> dev );
834
833
skb_postpull_rcsum (skb , eth_hdr (skb ), ETH_HLEN );
835
834
} else {
836
835
skb -> dev = tunnel -> dev ;
837
836
skb_reset_mac_header (skb );
838
837
}
839
838
839
+ /* Save offset of outer header relative to skb->head,
840
+ * because we are going to reset the network header to the inner header
841
+ * and might change skb->head.
842
+ */
843
+ nh = skb_network_header (skb ) - skb -> head ;
844
+
840
845
skb_reset_network_header (skb );
846
+
847
+ if (!pskb_inet_may_pull (skb )) {
848
+ DEV_STATS_INC (tunnel -> dev , rx_length_errors );
849
+ DEV_STATS_INC (tunnel -> dev , rx_errors );
850
+ goto drop ;
851
+ }
852
+
853
+ /* Get the outer header. */
854
+ ipv6h = (struct ipv6hdr * )(skb -> head + nh );
855
+
841
856
memset (skb -> cb , 0 , sizeof (struct inet6_skb_parm ));
842
857
843
858
__skb_tunnel_rx (skb , tunnel -> dev , tunnel -> net );
0 commit comments