aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ipvlan
diff options
context:
space:
mode:
authorSabrina Dubroca <sd@queasysnail.net>2015-11-16 16:34:26 -0500
committerDavid S. Miller <davem@davemloft.net>2015-11-17 14:39:28 -0500
commitcf554ada0be7077906aa9a17faf151ff66e3cb8e (patch)
tree73f8237dcd14a6d0f57e3fd99f4c98e4743c8777 /drivers/net/ipvlan
parenteb3f8b42aaba19325eff7e99842ca36429a0a3b8 (diff)
ipvlan: fix leak in ipvlan_rcv_frame
Pass a **skb to ipvlan_rcv_frame so that if skb_share_check returns a new skb, we actually use it during further processing. It's safe to ignore the new skb in the ipvlan_xmit_* functions, because they call ipvlan_rcv_frame with local == true, so that dev_forward_skb is called and always takes ownership of the skb. Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.") Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ipvlan')
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index d50887e3df6d..a9148e46dad0 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -254,7 +254,7 @@ acct:
254 } 254 }
255} 255}
256 256
257static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb, 257static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff **pskb,
258 bool local) 258 bool local)
259{ 259{
260 struct ipvl_dev *ipvlan = addr->master; 260 struct ipvl_dev *ipvlan = addr->master;
@@ -262,6 +262,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb,
262 unsigned int len; 262 unsigned int len;
263 rx_handler_result_t ret = RX_HANDLER_CONSUMED; 263 rx_handler_result_t ret = RX_HANDLER_CONSUMED;
264 bool success = false; 264 bool success = false;
265 struct sk_buff *skb = *pskb;
265 266
266 len = skb->len + ETH_HLEN; 267 len = skb->len + ETH_HLEN;
267 if (unlikely(!(dev->flags & IFF_UP))) { 268 if (unlikely(!(dev->flags & IFF_UP))) {
@@ -273,6 +274,7 @@ static int ipvlan_rcv_frame(struct ipvl_addr *addr, struct sk_buff *skb,
273 if (!skb) 274 if (!skb)
274 goto out; 275 goto out;
275 276
277 *pskb = skb;
276 skb->dev = dev; 278 skb->dev = dev;
277 skb->pkt_type = PACKET_HOST; 279 skb->pkt_type = PACKET_HOST;
278 280
@@ -486,7 +488,7 @@ static int ipvlan_xmit_mode_l3(struct sk_buff *skb, struct net_device *dev)
486 488
487 addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true); 489 addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
488 if (addr) 490 if (addr)
489 return ipvlan_rcv_frame(addr, skb, true); 491 return ipvlan_rcv_frame(addr, &skb, true);
490 492
491out: 493out:
492 skb->dev = ipvlan->phy_dev; 494 skb->dev = ipvlan->phy_dev;
@@ -506,7 +508,7 @@ static int ipvlan_xmit_mode_l2(struct sk_buff *skb, struct net_device *dev)
506 if (lyr3h) { 508 if (lyr3h) {
507 addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true); 509 addr = ipvlan_addr_lookup(ipvlan->port, lyr3h, addr_type, true);
508 if (addr) 510 if (addr)
509 return ipvlan_rcv_frame(addr, skb, true); 511 return ipvlan_rcv_frame(addr, &skb, true);
510 } 512 }
511 skb = skb_share_check(skb, GFP_ATOMIC); 513 skb = skb_share_check(skb, GFP_ATOMIC);
512 if (!skb) 514 if (!skb)
@@ -589,7 +591,7 @@ static rx_handler_result_t ipvlan_handle_mode_l3(struct sk_buff **pskb,
589 591
590 addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); 592 addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
591 if (addr) 593 if (addr)
592 ret = ipvlan_rcv_frame(addr, skb, false); 594 ret = ipvlan_rcv_frame(addr, pskb, false);
593 595
594out: 596out:
595 return ret; 597 return ret;
@@ -626,7 +628,7 @@ static rx_handler_result_t ipvlan_handle_mode_l2(struct sk_buff **pskb,
626 628
627 addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true); 629 addr = ipvlan_addr_lookup(port, lyr3h, addr_type, true);
628 if (addr) 630 if (addr)
629 ret = ipvlan_rcv_frame(addr, skb, false); 631 ret = ipvlan_rcv_frame(addr, pskb, false);
630 } 632 }
631 633
632 return ret; 634 return ret;