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 de94921..025e0c1 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 54c94a6..796a38f 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);