In the Linux kernel, the following vulnerability has been resolved:
macsec: sync features on RTM_NEWLINK
Syzkaller managed to lock the lower device via ETHTOOL_SFEATURES:
netdevlock include/linux/netdevice.h:2761 [inline] netdevlockops include/net/netdevlock.h:42 [inline] netdevsynclowerfeatures net/core/dev.c:10649 [inline] _netdevupdatefeatures+0xcb1/0x1be0 net/core/dev.c:10819 netdevupdatefeatures+0x6d/0xe0 net/core/dev.c:10876 macsecnotify+0x2f5/0x660 drivers/net/macsec.c:4533 notifiercallchain+0x1b3/0x3e0 kernel/notifier.c:85 callnetdevicenotifiersextack net/core/dev.c:2267 [inline] callnetdevicenotifiers net/core/dev.c:2281 [inline] netdevfeatureschange+0x85/0xc0 net/core/dev.c:1570 _devethtool net/ethtool/ioctl.c:3469 [inline] devethtool+0x1536/0x19b0 net/ethtool/ioctl.c:3502 devioctl+0x392/0x1150 net/core/dev_ioctl.c:759
It happens because lower features are out of sync with the upper:
_devethtool (realdev) netdevlockops(realdev) ETHTOOLSFEATURES _netdevfeatureschange netdevsyncupperfeatures disable LRO on the lower if (oldfeatures != dev->features) netdevfeatureschange fires NETDEVFEATCHANGE macsecnotify NETDEVFEATCHANGE netdevupdatefeatures (for each macsec dev) netdevsynclowerfeatures if (upperfeatures != lowerfeatures) netdevlockops(lower) # lower == real_dev stuck ...
netdev_unlock_ops(real_dev)
Per commit af5f54b0ef9e ("net: Lock lower level devices when updating features"), we elide the lock/unlock when the upper and lower features are synced. Makes sure the lower (real_dev) has proper features after the macsec link has been created. This makes sure we never hit the situation where we need to sync upper flags to the lower.