summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/ip6_tunnel.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 419960b0ba16..a0b6932c3afd 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1234,7 +1234,7 @@ static inline int
1234ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) 1234ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1235{ 1235{
1236 struct ip6_tnl *t = netdev_priv(dev); 1236 struct ip6_tnl *t = netdev_priv(dev);
1237 const struct iphdr *iph = ip_hdr(skb); 1237 const struct iphdr *iph;
1238 int encap_limit = -1; 1238 int encap_limit = -1;
1239 struct flowi6 fl6; 1239 struct flowi6 fl6;
1240 __u8 dsfield; 1240 __u8 dsfield;
@@ -1242,6 +1242,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1242 u8 tproto; 1242 u8 tproto;
1243 int err; 1243 int err;
1244 1244
1245 /* ensure we can access the full inner ip header */
1246 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
1247 return -1;
1248
1249 iph = ip_hdr(skb);
1245 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); 1250 memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt));
1246 1251
1247 tproto = READ_ONCE(t->parms.proto); 1252 tproto = READ_ONCE(t->parms.proto);
@@ -1306,7 +1311,7 @@ static inline int
1306ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) 1311ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1307{ 1312{
1308 struct ip6_tnl *t = netdev_priv(dev); 1313 struct ip6_tnl *t = netdev_priv(dev);
1309 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 1314 struct ipv6hdr *ipv6h;
1310 int encap_limit = -1; 1315 int encap_limit = -1;
1311 __u16 offset; 1316 __u16 offset;
1312 struct flowi6 fl6; 1317 struct flowi6 fl6;
@@ -1315,6 +1320,10 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
1315 u8 tproto; 1320 u8 tproto;
1316 int err; 1321 int err;
1317 1322
1323 if (unlikely(!pskb_may_pull(skb, sizeof(*ipv6h))))
1324 return -1;
1325
1326 ipv6h = ipv6_hdr(skb);
1318 tproto = READ_ONCE(t->parms.proto); 1327 tproto = READ_ONCE(t->parms.proto);
1319 if ((tproto != IPPROTO_IPV6 && tproto != 0) || 1328 if ((tproto != IPPROTO_IPV6 && tproto != 0) ||
1320 ip6_tnl_addr_conflict(t, ipv6h)) 1329 ip6_tnl_addr_conflict(t, ipv6h))