diff options
author | Gao Feng <gfree.wind@vip.163.com> | 2017-11-22 22:47:11 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-11-23 13:37:02 -0500 |
commit | 5fc9220a6719574b37813d4330cc5c1ffe6d5c16 (patch) | |
tree | 069ad0802e58b2e5e56f7e76c394bc13b40e81eb | |
parent | f9094b7603c011d27db7ba109e69881c72fa611d (diff) |
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: Gao Feng <gfree.wind@vip.163.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ipvlan/ipvlan_core.c | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index f2a7e929316e..4476425b1033 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c | |||
@@ -116,7 +116,7 @@ bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6) | |||
116 | return false; | 116 | return false; |
117 | } | 117 | } |
118 | 118 | ||
119 | static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type) | 119 | static void *ipvlan_get_L3_hdr(struct ipvl_port *port, struct sk_buff *skb, int *type) |
120 | { | 120 | { |
121 | void *lyr3h = NULL; | 121 | void *lyr3h = NULL; |
122 | 122 | ||
@@ -124,7 +124,7 @@ static void *ipvlan_get_L3_hdr(struct sk_buff *skb, int *type) | |||
124 | case htons(ETH_P_ARP): { | 124 | case htons(ETH_P_ARP): { |
125 | struct arphdr *arph; | 125 | struct arphdr *arph; |
126 | 126 | ||
127 | if (unlikely(!pskb_may_pull(skb, sizeof(*arph)))) | 127 | if (unlikely(!pskb_may_pull(skb, arp_hdr_len(port->dev)))) |
128 | return NULL; | 128 | return NULL; |
129 | 129 | ||
130 | arph = arp_hdr(skb); | 130 | arph = arp_hdr(skb); |
@@ -510,7 +510,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev) | |||
510 | struct ipvl_addr *addr; | 510 | struct ipvl_addr *addr; |
511 | int addr_type; | 511 | int addr_type; |
512 | 512 | ||
513 | lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); | 513 | lyr3h = ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type); |
514 | if (!lyr3h) | 514 | if (!lyr3h) |
515 | goto out; | 515 | goto out; |
516 | 516 | ||
@@ -539,7 +539,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev) | |||
539 | 539 | ||
540 | if (!ipvlan_is_vepa(ipvlan->port) && | 540 | if (!ipvlan_is_vepa(ipvlan->port) && |
541 | ether_addr_equal(eth->h_dest, eth->h_source)) { | 541 | ether_addr_equal(eth->h_dest, eth->h_source)) { |
542 | lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); | 542 | lyr3h = ipvlan_get_L3_hdr(ipvlan->port, skb, &addr_type); |
543 | if (lyr3h) { | 543 | if (lyr3h) { |
544 | addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true); | 544 | addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true); |
545 | if (addr) { | 545 | if (addr) { |
@@ -606,7 +606,7 @@ static bool ipvlan_external_frame(struct sk_buff *skb, struct ipvl_port *port) | |||
606 | int addr_type; | 606 | int addr_type; |
607 | 607 | ||
608 | if (ether_addr_equal(eth->h_source, skb->dev->dev_addr)) { | 608 | if (ether_addr_equal(eth->h_source, skb->dev->dev_addr)) { |
609 | lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); | 609 | lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); |
610 | if (!lyr3h) | 610 | if (!lyr3h) |
611 | return true; | 611 | return true; |
612 | 612 | ||
@@ -627,7 +627,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb, | |||
627 | struct sk_buff *skb = *pskb; | 627 | struct sk_buff *skb = *pskb; |
628 | rx_handler_result_t ret = RX_HANDLER_PASS; | 628 | rx_handler_result_t ret = RX_HANDLER_PASS; |
629 | 629 | ||
630 | lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); | 630 | lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); |
631 | if (!lyr3h) | 631 | if (!lyr3h) |
632 | goto out; | 632 | goto out; |
633 | 633 | ||
@@ -666,7 +666,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb, | |||
666 | } else { | 666 | } else { |
667 | struct ipvl_addr *addr; | 667 | struct ipvl_addr *addr; |
668 | 668 | ||
669 | lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); | 669 | lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); |
670 | if (!lyr3h) | 670 | if (!lyr3h) |
671 | return ret; | 671 | return ret; |
672 | 672 | ||
@@ -717,7 +717,7 @@ static struct ipvl_addr *ipvlan_skb_to_addr(struct sk_buff *skb, | |||
717 | if (!port || port->mode != IPVLAN_MODE_L3S) | 717 | if (!port || port->mode != IPVLAN_MODE_L3S) |
718 | goto out; | 718 | goto out; |
719 | 719 | ||
720 | lyr3h = ipvlan_get_L3_hdr(skb, &addr_type); | 720 | lyr3h = ipvlan_get_L3_hdr(port, skb, &addr_type); |
721 | if (!lyr3h) | 721 | if (!lyr3h) |
722 | goto out; | 722 | goto out; |
723 | 723 | ||