diff options
author | Jakub Kicinski | 2021-11-19 06:21:53 -0800 |
---|---|---|
committer | David S. Miller | 2021-11-20 12:25:57 +0000 |
commit | d07b26f5bbea9ade34dfd6abea7b3ca056c03cd1 (patch) | |
tree | 4a907941337e5445e0834277647ba4c04269523e /net | |
parent | 5f0b69238427f19a20063e90486754b1ea3ccd3b (diff) |
dev_addr: add a modification check
netdev->dev_addr should only be modified via helpers,
but someone may be casting off the const. Add a runtime
check to catch abuses.
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/core/dev.c | 1 | ||||
-rw-r--r-- | net/core/dev_addr_lists.c | 19 |
2 files changed, 20 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 92c9258cbf28..9219e319e901 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1377,6 +1377,7 @@ static int __dev_open(struct net_device *dev, struct netlink_ext_ack *extack) int ret; ASSERT_RTNL(); + dev_addr_check(dev); if (!netif_device_present(dev)) { /* may be detached because parent is runtime-suspended */ diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index a23a83ac18e5..969942734951 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -498,6 +498,21 @@ EXPORT_SYMBOL(__hw_addr_init); * Device addresses handling functions */ +/* Check that netdev->dev_addr is not written to directly as this would + * break the rbtree layout. All changes should go thru dev_addr_set() and co. + * Remove this check in mid-2024. + */ +void dev_addr_check(struct net_device *dev) +{ + if (!memcmp(dev->dev_addr, dev->dev_addr_shadow, MAX_ADDR_LEN)) + return; + + netdev_warn(dev, "Current addr: %*ph\n", MAX_ADDR_LEN, dev->dev_addr); + netdev_warn(dev, "Expected addr: %*ph\n", + MAX_ADDR_LEN, dev->dev_addr_shadow); + netdev_WARN(dev, "Incorrect netdev->dev_addr\n"); +} + /** * dev_addr_flush - Flush device address list * @dev: device @@ -509,6 +524,7 @@ EXPORT_SYMBOL(__hw_addr_init); void dev_addr_flush(struct net_device *dev) { /* rtnl_mutex must be held here */ + dev_addr_check(dev); __hw_addr_flush(&dev->dev_addrs); dev->dev_addr = NULL; @@ -552,8 +568,11 @@ void dev_addr_mod(struct net_device *dev, unsigned int offset, { struct netdev_hw_addr *ha; + dev_addr_check(dev); + ha = container_of(dev->dev_addr, struct netdev_hw_addr, addr[0]); memcpy(&ha->addr[offset], addr, len); + memcpy(&dev->dev_addr_shadow[offset], addr, len); } EXPORT_SYMBOL(dev_addr_mod); |