syzbot managed to trigger a recursive NETDEV_FEAT_CHANGE event between bonding master and slave. I managed to find a reproducer for this:
ip li set bond0 up ifenslave bond0 eth0 brctl addbr br0 ethtool -K eth0 lro off brctl addif br0 bond0 ip li set br0 up When a NETDEV_FEAT_CHANGE event is triggered on a bonding slave, it captures this and calls bond_compute_features() to fixup its master's and other slaves' features. However, when syncing with its lower devices by netdev_sync_lower_features() this event is triggered again on slaves, so it goes back and forth recursively until the kernel stack is exhausted. It is unnecessary to trigger it for a second time, because when we update the features from top down, we rely on each dev->netdev_ops->ndo_fix_features() to do the job, each stacked device should implement it. NETDEV_FEAT_CHANGE event is necessary when we update from bottom up, like in existing stacked device implementations. Just calling __netdev_update_features() is sufficient to fix this issue. Fixes: fd867d51f889 ("net/core: generic support for disabling netdev features down stack") Reported-by: syzbot+e73ceacfd8560cc8a...@syzkaller.appspotmail.com Reported-by: syzbot+c2fb6f9ddcea95ba4...@syzkaller.appspotmail.com Cc: Jarod Wilson <ja...@redhat.com> Cc: Josh Poimboeuf <jpoim...@redhat.com> Cc: Jay Vosburgh <j.vosbu...@gmail.com> Cc: Jann Horn <ja...@google.com> Signed-off-by: Cong Wang <xiyou.wangc...@gmail.com> --- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 522288177bbd..ece50ae346c3 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -8907,7 +8907,7 @@ static void netdev_sync_lower_features(struct net_device *upper, netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n", &feature, lower->name); lower->wanted_features &= ~feature; - netdev_update_features(lower); + __netdev_update_features(lower); if (unlikely(lower->features & feature)) netdev_WARN(upper, "failed to disable %pNF on %s!\n", -- 2.26.2