]> git.baikalelectronics.ru Git - kernel.git/commitdiff
ipvlan: hold lower dev to avoid possible use-after-free
authorMahesh Bandewar <maheshb@google.com>
Wed, 16 Nov 2022 01:19:14 +0000 (17:19 -0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 18 Nov 2022 10:39:22 +0000 (10:39 +0000)
Recently syzkaller discovered the issue of disappearing lower
device (NETDEV_UNREGISTER) while the virtual device (like
macvlan) is still having it as a lower device. So it's just
a matter of time similar discovery will be made for IPvlan
device setup. So fixing it preemptively. Also while at it,
add a refcount tracker.

Fixes: 2ad7bf363841 ("ipvlan: Initial check-in of the IPVLAN driver.")
Signed-off-by: Mahesh Bandewar <maheshb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ipvlan/ipvlan.h
drivers/net/ipvlan/ipvlan_main.c

index de94921cbef9f2beb2b7e4f5ecde06eb4e5cff9c..025e0c19ec255295fb904d1bbba9b15e0ad8924e 100644 (file)
@@ -98,6 +98,7 @@ struct ipvl_port {
        struct sk_buff_head     backlog;
        int                     count;
        struct ida              ida;
+       netdevice_tracker       dev_tracker;
 };
 
 struct ipvl_skb_cb {
index 54c94a69c2bb8df851f03bb0effe950fd72a93bb..796a38f9d7b24b87d4bc9b40f823c5c06880ad8c 100644 (file)
@@ -83,6 +83,7 @@ static int ipvlan_port_create(struct net_device *dev)
        if (err)
                goto err;
 
+       netdev_hold(dev, &port->dev_tracker, GFP_KERNEL);
        return 0;
 
 err:
@@ -95,6 +96,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
        struct ipvl_port *port = ipvlan_port_get_rtnl(dev);
        struct sk_buff *skb;
 
+       netdev_put(dev, &port->dev_tracker);
        if (port->mode == IPVLAN_MODE_L3S)
                ipvlan_l3s_unregister(port);
        netdev_rx_handler_unregister(dev);