aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVeaceslav Falico <vfalico@redhat.com>2014-01-10 05:59:43 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-14 01:22:27 -0500
commitc1bc9644ecd1f663f918d42b33b41a508683b0ee (patch)
treed020bd6c841fbd0f368618a3e88db5417d46e3bf
parent853dc21bfe15f545347b5c82aad02735d552110d (diff)
bonding: fix bond_3ad_set_carrier() RCU usage
Currently, its usage is just plainly wrong. It first gets a slave under RCU, and, after releasing the RCU lock, continues to use it - whilst it can be freed. Fix this by ensuring that bond_3ad_set_carrier() holds RCU till it uses its slave (or its agg). Fixes: be79bd048ab ("bonding: add RCU for bond_3ad_state_machine_handler()") CC: dingtianhong@huawei.com CC: Jay Vosburgh <fubar@us.ibm.com> CC: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Veaceslav Falico <vfalico@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bonding/bond_3ad.c22
1 files changed, 11 insertions, 11 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 29db1caee764..da0d7c54d352 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -2327,32 +2327,32 @@ int bond_3ad_set_carrier(struct bonding *bond)
2327{ 2327{
2328 struct aggregator *active; 2328 struct aggregator *active;
2329 struct slave *first_slave; 2329 struct slave *first_slave;
2330 int ret = 1;
2330 2331
2331 rcu_read_lock(); 2332 rcu_read_lock();
2332 first_slave = bond_first_slave_rcu(bond); 2333 first_slave = bond_first_slave_rcu(bond);
2333 rcu_read_unlock(); 2334 if (!first_slave) {
2334 if (!first_slave) 2335 ret = 0;
2335 return 0; 2336 goto out;
2337 }
2336 active = __get_active_agg(&(SLAVE_AD_INFO(first_slave).aggregator)); 2338 active = __get_active_agg(&(SLAVE_AD_INFO(first_slave).aggregator));
2337 if (active) { 2339 if (active) {
2338 /* are enough slaves available to consider link up? */ 2340 /* are enough slaves available to consider link up? */
2339 if (active->num_of_ports < bond->params.min_links) { 2341 if (active->num_of_ports < bond->params.min_links) {
2340 if (netif_carrier_ok(bond->dev)) { 2342 if (netif_carrier_ok(bond->dev)) {
2341 netif_carrier_off(bond->dev); 2343 netif_carrier_off(bond->dev);
2342 return 1; 2344 goto out;
2343 } 2345 }
2344 } else if (!netif_carrier_ok(bond->dev)) { 2346 } else if (!netif_carrier_ok(bond->dev)) {
2345 netif_carrier_on(bond->dev); 2347 netif_carrier_on(bond->dev);
2346 return 1; 2348 goto out;
2347 } 2349 }
2348 return 0; 2350 } else if (netif_carrier_ok(bond->dev)) {
2349 }
2350
2351 if (netif_carrier_ok(bond->dev)) {
2352 netif_carrier_off(bond->dev); 2351 netif_carrier_off(bond->dev);
2353 return 1;
2354 } 2352 }
2355 return 0; 2353out:
2354 rcu_read_unlock();
2355 return ret;
2356} 2356}
2357 2357
2358/** 2358/**