[commits] [batman-adv] next: batman-adv: Fix potential broadcast BLA-duplicate-check race condition (4c1721b)

postmaster at open-mesh.org postmaster at open-mesh.org
Wed Oct 17 19:55:05 CEST 2012


Repository : ssh://git@open-mesh.org/batman-adv

On branch  : next

>---------------------------------------------------------------

commit 4c1721b39c8a77c99e8f4de97b5d5d112006406c
Author: Linus Lüssing <linus.luessing at web.de>
Date:   Wed Oct 17 14:53:05 2012 +0200

    batman-adv: Fix potential broadcast BLA-duplicate-check race condition
    
    Threads in the bottom half of batadv_bla_check_bcast_duplist() might
    otherwise for instance overwrite variables which other threads might
    be using/reading at the same time in the top half, potentially
    leading to messing up the bcast_duplist, possibly resulting in false
    bridge loop avoidance duplicate check decisions.
    
    Signed-off-by: Linus Lüssing <linus.luessing at web.de>
    Acked-by: Simon Wunderlich <siwu at hrz.tu-chemnitz.de>
    Signed-off-by: Marek Lindner <lindner_marek at yahoo.de>


>---------------------------------------------------------------

4c1721b39c8a77c99e8f4de97b5d5d112006406c
 bridge_loop_avoidance.c |   16 +++++++++++-----
 main.c                  |    1 +
 types.h                 |    2 ++
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/bridge_loop_avoidance.c b/bridge_loop_avoidance.c
index eebab20..9a4b24f 100644
--- a/bridge_loop_avoidance.c
+++ b/bridge_loop_avoidance.c
@@ -1226,7 +1226,7 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 				   struct batadv_bcast_packet *bcast_packet,
 				   int bcast_packet_len)
 {
-	int i, length, curr;
+	int i, length, curr, ret = 0;
 	uint8_t *content;
 	uint16_t crc;
 	struct batadv_bcast_duplist_entry *entry;
@@ -1238,6 +1238,8 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 	/* calculate the crc ... */
 	crc = crc16(0, content, length);
 
+	spin_lock_bh(&bat_priv->bla.bcast_duplist_lock);
+
 	for (i = 0; i < BATADV_DUPLIST_SIZE; i++) {
 		curr = (bat_priv->bla.bcast_duplist_curr + i);
 		curr %= BATADV_DUPLIST_SIZE;
@@ -1259,9 +1261,11 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 		/* this entry seems to match: same crc, not too old,
 		 * and from another gw. therefore return 1 to forbid it.
 		 */
-		return 1;
+		ret = 1;
+		goto out;
 	}
-	/* not found, add a new entry (overwrite the oldest entry) */
+	/* not found, add a new entry (overwrite the oldest entry)
+	 * and allow it, its the first occurence. */
 	curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1);
 	curr %= BATADV_DUPLIST_SIZE;
 	entry = &bat_priv->bla.bcast_duplist[curr];
@@ -1270,8 +1274,10 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv,
 	memcpy(entry->orig, bcast_packet->orig, ETH_ALEN);
 	bat_priv->bla.bcast_duplist_curr = curr;
 
-	/* allow it, its the first occurence. */
-	return 0;
+out:
+	spin_unlock_bh(&bat_priv->bla.bcast_duplist_lock);
+
+	return ret;
 }
 
 
diff --git a/main.c b/main.c
index b4aa470..f167b65 100644
--- a/main.c
+++ b/main.c
@@ -101,6 +101,7 @@ int batadv_mesh_init(struct net_device *soft_iface)
 	spin_lock_init(&bat_priv->gw.list_lock);
 	spin_lock_init(&bat_priv->vis.hash_lock);
 	spin_lock_init(&bat_priv->vis.list_lock);
+	spin_lock_init(&bat_priv->bla.bcast_duplist_lock);
 
 	INIT_HLIST_HEAD(&bat_priv->forw_bat_list);
 	INIT_HLIST_HEAD(&bat_priv->forw_bcast_list);
diff --git a/types.h b/types.h
index 2ed82ca..ac1e07a 100644
--- a/types.h
+++ b/types.h
@@ -205,6 +205,8 @@ struct batadv_priv_bla {
 	struct batadv_hashtable *backbone_hash;
 	struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE];
 	int bcast_duplist_curr;
+	/* protects bcast_duplist and bcast_duplist_curr */
+	spinlock_t bcast_duplist_lock;
 	struct batadv_bla_claim_dst claim_dest;
 	struct delayed_work work;
 };



More information about the commits mailing list