Skip to content

Commit

Permalink
net: fix a potential recursive NETDEV_FEAT_CHANGE
Browse files Browse the repository at this point in the history
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 when the LRO feature fails to change,
so it goes back and forth recursively until the kernel stack is
exhausted.

Commit 17b85d2 intentionally lets __netdev_update_features()
return -1 for such a failure case, so we have to just rely on
the existing check inside netdev_sync_lower_features() and skip
NETDEV_FEAT_CHANGE event only for this specific failure case.

Fixes: fd867d5 ("net/core: generic support for disabling netdev features down stack")
Reported-by: [email protected]
Reported-by: [email protected]
Cc: Jarod Wilson <[email protected]>
Cc: Nikolay Aleksandrov <[email protected]>
Cc: Josh Poimboeuf <[email protected]>
Cc: Jann Horn <[email protected]>
Reviewed-by: Jay Vosburgh <[email protected]>
Signed-off-by: Cong Wang <[email protected]>
Acked-by: Nikolay Aleksandrov <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
congwang authored and davem330 committed May 8, 2020
1 parent 7d14b0d commit dd91230
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -8907,11 +8907,13 @@ 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",
&feature, lower->name);
else
netdev_features_change(lower);
}
}
}
Expand Down

0 comments on commit dd91230

Please sign in to comment.