Skip to content

Commit

Permalink
net: macvlan: fix potential UAF problem for lowerdev
Browse files Browse the repository at this point in the history
Add the reference operation to lowerdev of macvlan to avoid
the potential UAF problem under the following known scenario:

Someone module puts the NETDEV_UNREGISTER event handler to a
work, and lowerdev is accessed in the work handler. But when
the work is excuted, lowerdev has been destroyed because upper
macvlan did not get reference to lowerdev correctly.

That likes as the scenario occurred by
commit 563bcba ("net: vlan: fix a UAF in vlan_dev_real_dev()").

Signed-off-by: Ziyang Xuan <william.xuanziyang@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Ziyang Xuan authored and David S. Miller committed Mar 14, 2022
1 parent de29aff commit 291ac68
Showing 1 changed file with 13 additions and 1 deletion.
14 changes: 13 additions & 1 deletion drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,7 @@ static void macvlan_set_lockdep_class(struct net_device *dev)
static int macvlan_init(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);
const struct net_device *lowerdev = vlan->lowerdev;
struct net_device *lowerdev = vlan->lowerdev;
struct macvlan_port *port = vlan->port;

dev->state = (dev->state & ~MACVLAN_STATE_MASK) |
Expand All @@ -911,6 +911,9 @@ static int macvlan_init(struct net_device *dev)

port->count += 1;

/* Get macvlan's reference to lowerdev */
dev_hold(lowerdev);

return 0;
}

Expand Down Expand Up @@ -1173,6 +1176,14 @@ static const struct net_device_ops macvlan_netdev_ops = {
.ndo_features_check = passthru_features_check,
};

static void macvlan_dev_free(struct net_device *dev)
{
struct macvlan_dev *vlan = netdev_priv(dev);

/* Get rid of the macvlan's reference to lowerdev */
dev_put(vlan->lowerdev);
}

void macvlan_common_setup(struct net_device *dev)
{
ether_setup(dev);
Expand All @@ -1184,6 +1195,7 @@ void macvlan_common_setup(struct net_device *dev)
dev->priv_flags |= IFF_UNICAST_FLT | IFF_CHANGE_PROTO_DOWN;
dev->netdev_ops = &macvlan_netdev_ops;
dev->needs_free_netdev = true;
dev->priv_destructor = macvlan_dev_free;
dev->header_ops = &macvlan_hard_header_ops;
dev->ethtool_ops = &macvlan_ethtool_ops;
}
Expand Down

0 comments on commit 291ac68

Please sign in to comment.