aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_main.c
diff options
context:
space:
mode:
authorVeaceslav Falico <vfalico@redhat.com>2014-02-20 06:07:57 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-20 13:20:55 -0500
commit010d3c3989706d800ae72253773fa6537cc9f74c (patch)
treebc10b84b5f84cd00b934dcb113bee0a76b87d3d9 /drivers/net/bonding/bond_main.c
parenta1eabb0178bcef8eee6286bc646b66e23f4f77ea (diff)
bonding: fix bond_arp_rcv() race of curr_active_slave
bond->curr_active_slave can be changed between its deferences, even to NULL, and thus we might panic. We're always holding the rcu (rx_handler->bond_handle_frame()->bond_arp_rcv()) so fix this by rcu_dereferencing() it and using the saved. Reported-by: Ding Tianhong <dingtianhong@huawei.com> Fixes: aeea64a ("bonding: don't trust arp requests unless active slave really works") CC: Jay Vosburgh <fubar@us.ibm.com> CC: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Veaceslav Falico <vfalico@redhat.com> Acked-by: Ding Tianhong <dingtianhong@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r--drivers/net/bonding/bond_main.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 71edf03544aa..bd70bbc7992c 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -2254,6 +2254,7 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
2254 struct slave *slave) 2254 struct slave *slave)
2255{ 2255{
2256 struct arphdr *arp = (struct arphdr *)skb->data; 2256 struct arphdr *arp = (struct arphdr *)skb->data;
2257 struct slave *curr_active_slave;
2257 unsigned char *arp_ptr; 2258 unsigned char *arp_ptr;
2258 __be32 sip, tip; 2259 __be32 sip, tip;
2259 int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP); 2260 int alen, is_arp = skb->protocol == __cpu_to_be16(ETH_P_ARP);
@@ -2299,6 +2300,8 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
2299 bond->params.arp_validate, slave_do_arp_validate(bond, slave), 2300 bond->params.arp_validate, slave_do_arp_validate(bond, slave),
2300 &sip, &tip); 2301 &sip, &tip);
2301 2302
2303 curr_active_slave = rcu_dereference(bond->curr_active_slave);
2304
2302 /* 2305 /*
2303 * Backup slaves won't see the ARP reply, but do come through 2306 * Backup slaves won't see the ARP reply, but do come through
2304 * here for each ARP probe (so we swap the sip/tip to validate 2307 * here for each ARP probe (so we swap the sip/tip to validate
@@ -2312,11 +2315,12 @@ int bond_arp_rcv(const struct sk_buff *skb, struct bonding *bond,
2312 * is done to avoid endless looping when we can't reach the 2315 * is done to avoid endless looping when we can't reach the
2313 * arp_ip_target and fool ourselves with our own arp requests. 2316 * arp_ip_target and fool ourselves with our own arp requests.
2314 */ 2317 */
2318
2315 if (bond_is_active_slave(slave)) 2319 if (bond_is_active_slave(slave))
2316 bond_validate_arp(bond, slave, sip, tip); 2320 bond_validate_arp(bond, slave, sip, tip);
2317 else if (bond->curr_active_slave && 2321 else if (curr_active_slave &&
2318 time_after(slave_last_rx(bond, bond->curr_active_slave), 2322 time_after(slave_last_rx(bond, curr_active_slave),
2319 bond->curr_active_slave->last_link_up)) 2323 curr_active_slave->last_link_up))
2320 bond_validate_arp(bond, slave, tip, sip); 2324 bond_validate_arp(bond, slave, tip, sip);
2321 2325
2322out_unlock: 2326out_unlock: