aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornikolay@redhat.com <nikolay@redhat.com>2012-11-28 20:31:31 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-29 13:13:15 -0500
commitfbb0c41b814d497c656fc7be9e35456f139cb2fb (patch)
tree96bd353986b83fb0fb062d697bc65718509c781e
parente9296e89b85604862bd9ec2d54dc43edad775c0d (diff)
bonding: fix miimon and arp_interval delayed work race conditions
First I would give three observations which will be used later. Observation 1: if (delayed_work_pending(wq)) cancel_delayed_work(wq) This usage is wrong because the pending bit is cleared just before the work's fn is executed and if the function re-arms itself we might end up with the work still running. It's safe to call cancel_delayed_work_sync() even if the work is not queued at all. Observation 2: Use of INIT_DELAYED_WORK() Work needs to be initialized only once prior to (de/en)queueing. Observation 3: IFF_UP is set only after ndo_open is called Related race conditions: 1. Race between bonding_store_miimon() and bonding_store_arp_interval() Because of Obs.1 we can end up having both works enqueued. 2. Multiple races with INIT_DELAYED_WORK() Since the works are not protected by anything between INIT_DELAYED_WORK() and calls to (en/de)queue it is possible for races between the following functions: (races are also possible between the calls to INIT_DELAYED_WORK() and workqueue code) bonding_store_miimon() - bonding_store_arp_interval(), bond_close(), bond_open(), enqueued functions bonding_store_arp_interval() - bonding_store_miimon(), bond_close(), bond_open(), enqueued functions 3. By Obs.1 we need to change bond_cancel_all() Bugs 1 and 2 are fixed by moving all work initializations in bond_open which by Obs. 2 and Obs. 3 and the fact that we make sure that all works are cancelled in bond_close(), is guaranteed not to have any work enqueued. Also RTNL lock is now acquired in bonding_store_miimon/arp_interval so they can't race with bond_close and bond_open. The opposing work is cancelled only if the IFF_UP flag is set and it is cancelled unconditionally. The opposing work is already cancelled if the interface is down so no need to cancel it again. This way we don't need new synchronizations for the bonding workqueue. These bugs (and fixes) are tied together and belong in the same patch. Note: I have left 1 line intentionally over 80 characters (84) because I didn't like how it looks broken down. If you'd prefer it otherwise, then simply break it. v2: Make description text < 75 columns Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/bonding/bond_main.c88
-rw-r--r--drivers/net/bonding/bond_sysfs.c34
2 files changed, 36 insertions, 86 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 5f5b69f37d2e..1445c7ddb26c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3459,6 +3459,28 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb, int count)
3459 3459
3460/*-------------------------- Device entry points ----------------------------*/ 3460/*-------------------------- Device entry points ----------------------------*/
3461 3461
3462static void bond_work_init_all(struct bonding *bond)
3463{
3464 INIT_DELAYED_WORK(&bond->mcast_work,
3465 bond_resend_igmp_join_requests_delayed);
3466 INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
3467 INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
3468 if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
3469 INIT_DELAYED_WORK(&bond->arp_work, bond_activebackup_arp_mon);
3470 else
3471 INIT_DELAYED_WORK(&bond->arp_work, bond_loadbalance_arp_mon);
3472 INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
3473}
3474
3475static void bond_work_cancel_all(struct bonding *bond)
3476{
3477 cancel_delayed_work_sync(&bond->mii_work);
3478 cancel_delayed_work_sync(&bond->arp_work);
3479 cancel_delayed_work_sync(&bond->alb_work);
3480 cancel_delayed_work_sync(&bond->ad_work);
3481 cancel_delayed_work_sync(&bond->mcast_work);
3482}
3483
3462static int bond_open(struct net_device *bond_dev) 3484static int bond_open(struct net_device *bond_dev)
3463{ 3485{
3464 struct bonding *bond = netdev_priv(bond_dev); 3486 struct bonding *bond = netdev_priv(bond_dev);
@@ -3481,41 +3503,27 @@ static int bond_open(struct net_device *bond_dev)
3481 } 3503 }
3482 read_unlock(&bond->lock); 3504 read_unlock(&bond->lock);
3483 3505
3484 INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed); 3506 bond_work_init_all(bond);
3485 3507
3486 if (bond_is_lb(bond)) { 3508 if (bond_is_lb(bond)) {
3487 /* bond_alb_initialize must be called before the timer 3509 /* bond_alb_initialize must be called before the timer
3488 * is started. 3510 * is started.
3489 */ 3511 */
3490 if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) { 3512 if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB)))
3491 /* something went wrong - fail the open operation */
3492 return -ENOMEM; 3513 return -ENOMEM;
3493 }
3494
3495 INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor);
3496 queue_delayed_work(bond->wq, &bond->alb_work, 0); 3514 queue_delayed_work(bond->wq, &bond->alb_work, 0);
3497 } 3515 }
3498 3516
3499 if (bond->params.miimon) { /* link check interval, in milliseconds. */ 3517 if (bond->params.miimon) /* link check interval, in milliseconds. */
3500 INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor);
3501 queue_delayed_work(bond->wq, &bond->mii_work, 0); 3518 queue_delayed_work(bond->wq, &bond->mii_work, 0);
3502 }
3503 3519
3504 if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ 3520 if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
3505 if (bond->params.mode == BOND_MODE_ACTIVEBACKUP)
3506 INIT_DELAYED_WORK(&bond->arp_work,
3507 bond_activebackup_arp_mon);
3508 else
3509 INIT_DELAYED_WORK(&bond->arp_work,
3510 bond_loadbalance_arp_mon);
3511
3512 queue_delayed_work(bond->wq, &bond->arp_work, 0); 3521 queue_delayed_work(bond->wq, &bond->arp_work, 0);
3513 if (bond->params.arp_validate) 3522 if (bond->params.arp_validate)
3514 bond->recv_probe = bond_arp_rcv; 3523 bond->recv_probe = bond_arp_rcv;
3515 } 3524 }
3516 3525
3517 if (bond->params.mode == BOND_MODE_8023AD) { 3526 if (bond->params.mode == BOND_MODE_8023AD) {
3518 INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler);
3519 queue_delayed_work(bond->wq, &bond->ad_work, 0); 3527 queue_delayed_work(bond->wq, &bond->ad_work, 0);
3520 /* register to receive LACPDUs */ 3528 /* register to receive LACPDUs */
3521 bond->recv_probe = bond_3ad_lacpdu_recv; 3529 bond->recv_probe = bond_3ad_lacpdu_recv;
@@ -3530,34 +3538,10 @@ static int bond_close(struct net_device *bond_dev)
3530 struct bonding *bond = netdev_priv(bond_dev); 3538 struct bonding *bond = netdev_priv(bond_dev);
3531 3539
3532 write_lock_bh(&bond->lock); 3540 write_lock_bh(&bond->lock);
3533
3534 bond->send_peer_notif = 0; 3541 bond->send_peer_notif = 0;
3535
3536 write_unlock_bh(&bond->lock); 3542 write_unlock_bh(&bond->lock);
3537 3543
3538 if (bond->params.miimon) { /* link check interval, in milliseconds. */ 3544 bond_work_cancel_all(bond);
3539 cancel_delayed_work_sync(&bond->mii_work);
3540 }
3541
3542 if (bond->params.arp_interval) { /* arp interval, in milliseconds. */
3543 cancel_delayed_work_sync(&bond->arp_work);
3544 }
3545
3546 switch (bond->params.mode) {
3547 case BOND_MODE_8023AD:
3548 cancel_delayed_work_sync(&bond->ad_work);
3549 break;
3550 case BOND_MODE_TLB:
3551 case BOND_MODE_ALB:
3552 cancel_delayed_work_sync(&bond->alb_work);
3553 break;
3554 default:
3555 break;
3556 }
3557
3558 if (delayed_work_pending(&bond->mcast_work))
3559 cancel_delayed_work_sync(&bond->mcast_work);
3560
3561 if (bond_is_lb(bond)) { 3545 if (bond_is_lb(bond)) {
3562 /* Must be called only after all 3546 /* Must be called only after all
3563 * slaves have been released 3547 * slaves have been released
@@ -4436,26 +4420,6 @@ static void bond_setup(struct net_device *bond_dev)
4436 bond_dev->features |= bond_dev->hw_features; 4420 bond_dev->features |= bond_dev->hw_features;
4437} 4421}
4438 4422
4439static void bond_work_cancel_all(struct bonding *bond)
4440{
4441 if (bond->params.miimon && delayed_work_pending(&bond->mii_work))
4442 cancel_delayed_work_sync(&bond->mii_work);
4443
4444 if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work))
4445 cancel_delayed_work_sync(&bond->arp_work);
4446
4447 if (bond->params.mode == BOND_MODE_ALB &&
4448 delayed_work_pending(&bond->alb_work))
4449 cancel_delayed_work_sync(&bond->alb_work);
4450
4451 if (bond->params.mode == BOND_MODE_8023AD &&
4452 delayed_work_pending(&bond->ad_work))
4453 cancel_delayed_work_sync(&bond->ad_work);
4454
4455 if (delayed_work_pending(&bond->mcast_work))
4456 cancel_delayed_work_sync(&bond->mcast_work);
4457}
4458
4459/* 4423/*
4460* Destroy a bonding device. 4424* Destroy a bonding device.
4461* Must be under rtnl_lock when this function is called. 4425* Must be under rtnl_lock when this function is called.
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index ef8d2a080d17..3327a072e224 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -513,6 +513,8 @@ static ssize_t bonding_store_arp_interval(struct device *d,
513 int new_value, ret = count; 513 int new_value, ret = count;
514 struct bonding *bond = to_bond(d); 514 struct bonding *bond = to_bond(d);
515 515
516 if (!rtnl_trylock())
517 return restart_syscall();
516 if (sscanf(buf, "%d", &new_value) != 1) { 518 if (sscanf(buf, "%d", &new_value) != 1) {
517 pr_err("%s: no arp_interval value specified.\n", 519 pr_err("%s: no arp_interval value specified.\n",
518 bond->dev->name); 520 bond->dev->name);
@@ -539,10 +541,6 @@ static ssize_t bonding_store_arp_interval(struct device *d,
539 pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n", 541 pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
540 bond->dev->name, bond->dev->name); 542 bond->dev->name, bond->dev->name);
541 bond->params.miimon = 0; 543 bond->params.miimon = 0;
542 if (delayed_work_pending(&bond->mii_work)) {
543 cancel_delayed_work(&bond->mii_work);
544 flush_workqueue(bond->wq);
545 }
546 } 544 }
547 if (!bond->params.arp_targets[0]) { 545 if (!bond->params.arp_targets[0]) {
548 pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n", 546 pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
@@ -554,19 +552,12 @@ static ssize_t bonding_store_arp_interval(struct device *d,
554 * timer will get fired off when the open function 552 * timer will get fired off when the open function
555 * is called. 553 * is called.
556 */ 554 */
557 if (!delayed_work_pending(&bond->arp_work)) { 555 cancel_delayed_work_sync(&bond->mii_work);
558 if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) 556 queue_delayed_work(bond->wq, &bond->arp_work, 0);
559 INIT_DELAYED_WORK(&bond->arp_work,
560 bond_activebackup_arp_mon);
561 else
562 INIT_DELAYED_WORK(&bond->arp_work,
563 bond_loadbalance_arp_mon);
564
565 queue_delayed_work(bond->wq, &bond->arp_work, 0);
566 }
567 } 557 }
568 558
569out: 559out:
560 rtnl_unlock();
570 return ret; 561 return ret;
571} 562}
572static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR, 563static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR,
@@ -962,6 +953,8 @@ static ssize_t bonding_store_miimon(struct device *d,
962 int new_value, ret = count; 953 int new_value, ret = count;
963 struct bonding *bond = to_bond(d); 954 struct bonding *bond = to_bond(d);
964 955
956 if (!rtnl_trylock())
957 return restart_syscall();
965 if (sscanf(buf, "%d", &new_value) != 1) { 958 if (sscanf(buf, "%d", &new_value) != 1) {
966 pr_err("%s: no miimon value specified.\n", 959 pr_err("%s: no miimon value specified.\n",
967 bond->dev->name); 960 bond->dev->name);
@@ -993,10 +986,6 @@ static ssize_t bonding_store_miimon(struct device *d,
993 bond->params.arp_validate = 986 bond->params.arp_validate =
994 BOND_ARP_VALIDATE_NONE; 987 BOND_ARP_VALIDATE_NONE;
995 } 988 }
996 if (delayed_work_pending(&bond->arp_work)) {
997 cancel_delayed_work(&bond->arp_work);
998 flush_workqueue(bond->wq);
999 }
1000 } 989 }
1001 990
1002 if (bond->dev->flags & IFF_UP) { 991 if (bond->dev->flags & IFF_UP) {
@@ -1005,15 +994,12 @@ static ssize_t bonding_store_miimon(struct device *d,
1005 * timer will get fired off when the open function 994 * timer will get fired off when the open function
1006 * is called. 995 * is called.
1007 */ 996 */
1008 if (!delayed_work_pending(&bond->mii_work)) { 997 cancel_delayed_work_sync(&bond->arp_work);
1009 INIT_DELAYED_WORK(&bond->mii_work, 998 queue_delayed_work(bond->wq, &bond->mii_work, 0);
1010 bond_mii_monitor);
1011 queue_delayed_work(bond->wq,
1012 &bond->mii_work, 0);
1013 }
1014 } 999 }
1015 } 1000 }
1016out: 1001out:
1002 rtnl_unlock();
1017 return ret; 1003 return ret;
1018} 1004}
1019static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, 1005static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR,