Commit 5fc9220a authored by Gao Feng's avatar Gao Feng Committed by David S. Miller

ipvlan: Fix insufficient skb linear check for arp

In the function ipvlan_get_L3_hdr, current codes use pskb_may_pull to
make sure the skb header has enough linear room for arp header. But it
would access the arp payload in func ipvlan_addr_lookup. So it still may
access the unepxected memory.

Now use arp_hdr_len(port->dev) instead of the arp header as the param.
Signed-off-by: default avatarGao Feng <gfree.wind@vip.163.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f9094b76
...@@ -116,7 +116,7 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6) ...@@ -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) ...@@ -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);
...@@ -510,7 +510,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev) ...@@ -510,7 +510,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 +539,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) ...@@ -539,7 +539,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 +606,7 @@ static bool ipvlan_external_frame(struct sk_buff *skb, struct ipvl_port *port) ...@@ -606,7 +606,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 +627,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb, ...@@ -627,7 +627,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 +666,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, ...@@ -666,7 +666,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 +717,7 @@ static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb, ...@@ -717,7 +717,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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment