From 747a713502e1dfdf0e93bc81ee0f5ec7510975e5 Mon Sep 17 00:00:00 2001 From: Gao Feng Date: Thu, 23 Nov 2017 11:47:12 +0800 Subject: [PATCH] ipvlan: Fix insufficient skb linear check for ipv6 icmp In the function ipvlan_get_L3_hdr, current codes use pskb_may_pull to make sure the skb header has enough linear room for ipv6 header. But it would use the latter memory directly without linear check when it is icmp. So it still may access the unepxected memory in ipvlan_addr_lookup. Now invoke the pskb_may_pull again if it is ipv6 icmp. Signed-off-by: Gao Feng Signed-off-by: David S. Miller --- drivers/net/ipvlan/ipvlan_core.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 4476425b1033..11c1e7950fe5 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -165,8 +165,26 @@ static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int /* Only Neighbour Solicitation pkts need different treatment */ if (ipv6_addr_any(&ip6h->saddr) && ip6h->nexthdr == NEXTHDR_ICMP) { + struct icmp6hdr *icmph; + + if (unlikely(!pskb_may_pull(skb, sizeof(*ip6h) + sizeof(*icmph)))) + return NULL; + + ip6h = ipv6_hdr(skb); + icmph = (struct icmp6hdr *)(ip6h + 1); + + if (icmph->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) { + /* Need to access the ipv6 address in body */ + if (unlikely(!pskb_may_pull(skb, sizeof(*ip6h) + sizeof(*icmph) + + sizeof(struct in6_addr)))) + return NULL; + + ip6h = ipv6_hdr(skb); + icmph = (struct icmp6hdr *)(ip6h + 1); + } + *type = IPVL_ICMPV6; - lyr3h = ip6h + 1; + lyr3h = icmph; } break; } -- 2.30.2