summaryrefslogtreecommitdiffstats
path: root/drivers/net/macvlan.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2017-04-20 08:55:12 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-25 10:42:10 -0400
commitf6478218e6edc2a587b8f132f66373baa7b2497c (patch)
tree85d69a0d169b13b811aa8a7244b1335b9d8d00c8 /drivers/net/macvlan.c
parent6f2aee0c0de65013333bbc26fe50c9c7b09a37f7 (diff)
macvlan: Fix device ref leak when purging bc_queue
When a parent macvlan device is destroyed we end up purging its broadcast queue without dropping the device reference count on the packet source device. This causes the source device to linger. This patch drops that reference count. Fixes: 260916dfb48c ("macvlan: Fix potential use-after free for...") Reported-by: Joe Ghalam <Joe.Ghalam@dell.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r--drivers/net/macvlan.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 9261722960a7..b34eaaae03fd 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1139,6 +1139,7 @@ static int macvlan_port_create(struct net_device *dev)
1139static void macvlan_port_destroy(struct net_device *dev) 1139static void macvlan_port_destroy(struct net_device *dev)
1140{ 1140{
1141 struct macvlan_port *port = macvlan_port_get_rtnl(dev); 1141 struct macvlan_port *port = macvlan_port_get_rtnl(dev);
1142 struct sk_buff *skb;
1142 1143
1143 dev->priv_flags &= ~IFF_MACVLAN_PORT; 1144 dev->priv_flags &= ~IFF_MACVLAN_PORT;
1144 netdev_rx_handler_unregister(dev); 1145 netdev_rx_handler_unregister(dev);
@@ -1147,7 +1148,15 @@ static void macvlan_port_destroy(struct net_device *dev)
1147 * but we need to cancel it and purge left skbs if any. 1148 * but we need to cancel it and purge left skbs if any.
1148 */ 1149 */
1149 cancel_work_sync(&port->bc_work); 1150 cancel_work_sync(&port->bc_work);
1150 __skb_queue_purge(&port->bc_queue); 1151
1152 while ((skb = __skb_dequeue(&port->bc_queue))) {
1153 const struct macvlan_dev *src = MACVLAN_SKB_CB(skb)->src;
1154
1155 if (src)
1156 dev_put(src->dev);
1157
1158 kfree_skb(skb);
1159 }
1151 1160
1152 kfree(port); 1161 kfree(port);
1153} 1162}