Skip to content

Commit dff9bc4

Browse files
ecsvsimonwunderlich
authored andcommitted
batman-adv: Prevent duplicated gateway_node entry
The function batadv_gw_node_add is responsible for adding new gw_node to the gateway_list. It is expecting that the caller already checked that there is not already an entry with the same key or not. But the lock for the list is only held when the list is really modified. This could lead to duplicated entries because another context could create an entry with the same key between the check and the list manipulation. The check and the manipulation of the list must therefore be in the same locked code section. Fixes: c6c8fea ("net: Add batman-adv meshing protocol") Signed-off-by: Sven Eckelmann <[email protected]> Acked-by: Marek Lindner <[email protected]> Signed-off-by: Simon Wunderlich <[email protected]>
1 parent a25bab9 commit dff9bc4

File tree

1 file changed

+9
-2
lines changed

1 file changed

+9
-2
lines changed

net/batman-adv/gateway_client.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <linux/kernel.h>
3333
#include <linux/kref.h>
3434
#include <linux/list.h>
35+
#include <linux/lockdep.h>
3536
#include <linux/netdevice.h>
3637
#include <linux/netlink.h>
3738
#include <linux/rculist.h>
@@ -348,13 +349,18 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
348349
* @bat_priv: the bat priv with all the soft interface information
349350
* @orig_node: originator announcing gateway capabilities
350351
* @gateway: announced bandwidth information
352+
*
353+
* Has to be called with the appropriate locks being acquired
354+
* (gw.list_lock).
351355
*/
352356
static void batadv_gw_node_add(struct batadv_priv *bat_priv,
353357
struct batadv_orig_node *orig_node,
354358
struct batadv_tvlv_gateway_data *gateway)
355359
{
356360
struct batadv_gw_node *gw_node;
357361

362+
lockdep_assert_held(&bat_priv->gw.list_lock);
363+
358364
if (gateway->bandwidth_down == 0)
359365
return;
360366

@@ -369,10 +375,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
369375
gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
370376
gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
371377

372-
spin_lock_bh(&bat_priv->gw.list_lock);
373378
kref_get(&gw_node->refcount);
374379
hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list);
375-
spin_unlock_bh(&bat_priv->gw.list_lock);
376380

377381
batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
378382
"Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n",
@@ -428,11 +432,14 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
428432
{
429433
struct batadv_gw_node *gw_node, *curr_gw = NULL;
430434

435+
spin_lock_bh(&bat_priv->gw.list_lock);
431436
gw_node = batadv_gw_node_get(bat_priv, orig_node);
432437
if (!gw_node) {
433438
batadv_gw_node_add(bat_priv, orig_node, gateway);
439+
spin_unlock_bh(&bat_priv->gw.list_lock);
434440
goto out;
435441
}
442+
spin_unlock_bh(&bat_priv->gw.list_lock);
436443

437444
if (gw_node->bandwidth_down == ntohl(gateway->bandwidth_down) &&
438445
gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))

0 commit comments

Comments
 (0)