bridge: Prevent possible race condition in br_fdb_change_mac_address
br_fdb_change_mac_address() calls fdb_insert()/fdb_delete() without br->hash_lock. These hash list updates are racy with br_fdb_update()/br_fdb_cleanup(). Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp> Acked-by: Vlad Yasevich <vyasevic@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
424bb9c97c
Коммит
ac4c886883
|
@ -191,6 +191,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
|
|||
struct net_port_vlans *pv;
|
||||
u16 vid = 0;
|
||||
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
|
||||
/* If old entry was unassociated with any port, then delete it. */
|
||||
f = __br_fdb_get(br, br->dev->dev_addr, 0);
|
||||
if (f && f->is_local && !f->dst)
|
||||
|
@ -204,7 +206,7 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
|
|||
*/
|
||||
pv = br_get_vlan_info(br);
|
||||
if (!pv)
|
||||
return;
|
||||
goto out;
|
||||
|
||||
for_each_set_bit_from(vid, pv->vlan_bitmap, VLAN_N_VID) {
|
||||
f = __br_fdb_get(br, br->dev->dev_addr, vid);
|
||||
|
@ -212,6 +214,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
|
|||
fdb_delete_local(br, NULL, f);
|
||||
fdb_insert(br, NULL, newaddr, vid);
|
||||
}
|
||||
out:
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
}
|
||||
|
||||
void br_fdb_cleanup(unsigned long _data)
|
||||
|
|
Загрузка…
Ссылка в новой задаче