Commit 40b9d1ab authored by Mahesh Bandewar's avatar Mahesh Bandewar Committed by David S. Miller

ipvlan: hold lower dev to avoid possible use-after-free

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: 2ad7bf36 ("ipvlan: Initial check-in of the IPVLAN driver.")
Signed-off-by: default avatarMahesh Bandewar <maheshb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8207f253
...@@ -98,6 +98,7 @@ struct ipvl_port { ...@@ -98,6 +98,7 @@ struct ipvl_port {
struct sk_buff_head backlog; struct sk_buff_head backlog;
int count; int count;
struct ida ida; struct ida ida;
netdevice_tracker dev_tracker;
}; };
struct ipvl_skb_cb { struct ipvl_skb_cb {
......
...@@ -83,6 +83,7 @@ static int ipvlan_port_create(struct net_device *dev) ...@@ -83,6 +83,7 @@ static int ipvlan_port_create(struct net_device *dev)
if (err) if (err)
goto err; goto err;
netdev_hold(dev, &port->dev_tracker, GFP_KERNEL);
return 0; return 0;
err: err:
...@@ -95,6 +96,7 @@ static void ipvlan_port_destroy(struct net_device *dev) ...@@ -95,6 +96,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
struct ipvl_port *port = ipvlan_port_get_rtnl(dev); struct ipvl_port *port = ipvlan_port_get_rtnl(dev);
struct sk_buff *skb; struct sk_buff *skb;
netdev_put(dev, &port->dev_tracker);
if (port->mode == IPVLAN_MODE_L3S) if (port->mode == IPVLAN_MODE_L3S)
ipvlan_l3s_unregister(port); ipvlan_l3s_unregister(port);
netdev_rx_handler_unregister(dev); netdev_rx_handler_unregister(dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment