macvlan: fix a race on port dismantle and possible skb leaks
[linux-drm-fsl-dcu.git] / drivers / net / macvlan.c
index 29b3bb410781c2530a41ae689b8a91d51e1de3ef..bfb0b6ec8c56e26d67fa94814fe460af34c95fed 100644 (file)
@@ -272,7 +272,7 @@ static void macvlan_process_broadcast(struct work_struct *w)
        struct sk_buff *skb;
        struct sk_buff_head list;
 
-       skb_queue_head_init(&list);
+       __skb_queue_head_init(&list);
 
        spin_lock_bh(&port->bc_queue.lock);
        skb_queue_splice_tail_init(&port->bc_queue, &list);
@@ -1082,9 +1082,15 @@ static void macvlan_port_destroy(struct net_device *dev)
 {
        struct macvlan_port *port = macvlan_port_get_rtnl(dev);
 
-       cancel_work_sync(&port->bc_work);
        dev->priv_flags &= ~IFF_MACVLAN_PORT;
        netdev_rx_handler_unregister(dev);
+
+       /* After this point, no packet can schedule bc_work anymore,
+        * but we need to cancel it and purge left skbs if any.
+        */
+       cancel_work_sync(&port->bc_work);
+       __skb_queue_purge(&port->bc_queue);
+
        kfree_rcu(port, rcu);
 }