Merge branch 'ipvlan-Fix-insufficient-skb-linear-check'
Gao Feng says: ==================== ipvlan: Fix insufficient skb linear check The current ipvlan codes use pskb_may_pull to get the skb linear header in func ipvlan_get_L3_hdr, but the size isn't enough for arp and ipv6 icmp. So it may access the unexpected momory in ipvlan_addr_lookup. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
9ed33805cd
|
@ -116,7 +116,7 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
|
static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type)
|
||||||
{
|
{
|
||||||
void *lyr3h = NULL;
|
void *lyr3h = NULL;
|
||||||
|
|
||||||
|
@ -124,7 +124,7 @@ static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
|
||||||
case htons(ETH_P_ARP): {
|
case htons(ETH_P_ARP): {
|
||||||
struct arphdr *arph;
|
struct arphdr *arph;
|
||||||
|
|
||||||
if (unlikely(!pskb_may_pull(skb, sizeof(*arph))))
|
if (unlikely(!pskb_may_pull(skb, arp_hdr_len(port->dev))))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
arph = arp_hdr(skb);
|
arph = arp_hdr(skb);
|
||||||
|
@ -165,8 +165,26 @@ static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type)
|
||||||
/* Only Neighbour Solicitation pkts need different treatment */
|
/* Only Neighbour Solicitation pkts need different treatment */
|
||||||
if (ipv6_addr_any(&ip6h->saddr) &&
|
if (ipv6_addr_any(&ip6h->saddr) &&
|
||||||
ip6h->nexthdr == NEXTHDR_ICMP) {
|
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;
|
*type = IPVL_ICMPV6;
|
||||||
lyr3h = ip6h + 1;
|
lyr3h = icmph;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -510,7 +528,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
|
||||||
struct ipvl_addr *addr;
|
struct ipvl_addr *addr;
|
||||||
int addr_type;
|
int addr_type;
|
||||||
|
|
||||||
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
|
lyr3h = ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type);
|
||||||
if (!lyr3h)
|
if (!lyr3h)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -539,7 +557,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
|
||||||
|
|
||||||
if (!ipvlan_is_vepa(ipvlan->port) &&
|
if (!ipvlan_is_vepa(ipvlan->port) &&
|
||||||
ether_addr_equal(eth->h_dest, eth->h_source)) {
|
ether_addr_equal(eth->h_dest, eth->h_source)) {
|
||||||
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
|
lyr3h = ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type);
|
||||||
if (lyr3h) {
|
if (lyr3h) {
|
||||||
addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
|
addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
|
||||||
if (addr) {
|
if (addr) {
|
||||||
|
@ -606,7 +624,7 @@ static bool ipvlan_external_frame(struct sk_buff *skb, struct ipvl_port *port)
|
||||||
int addr_type;
|
int addr_type;
|
||||||
|
|
||||||
if (ether_addr_equal(eth->h_source, skb->dev->dev_addr)) {
|
if (ether_addr_equal(eth->h_source, skb->dev->dev_addr)) {
|
||||||
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
|
lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
|
||||||
if (!lyr3h)
|
if (!lyr3h)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -627,7 +645,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
|
||||||
struct sk_buff *skb = *pskb;
|
struct sk_buff *skb = *pskb;
|
||||||
rx_handler_result_t ret = RX_HANDLER_PASS;
|
rx_handler_result_t ret = RX_HANDLER_PASS;
|
||||||
|
|
||||||
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
|
lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
|
||||||
if (!lyr3h)
|
if (!lyr3h)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
@ -666,7 +684,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
|
||||||
} else {
|
} else {
|
||||||
struct ipvl_addr *addr;
|
struct ipvl_addr *addr;
|
||||||
|
|
||||||
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
|
lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
|
||||||
if (!lyr3h)
|
if (!lyr3h)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -717,7 +735,7 @@ static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb,
|
||||||
if (!port || port->mode != IPVLAN_MODE_L3S)
|
if (!port || port->mode != IPVLAN_MODE_L3S)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
lyr3h = ipvlan_get_L3_hdr(skb, &addr_type);
|
lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type);
|
||||||
if (!lyr3h)
|
if (!lyr3h)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue