Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7dac7b76 authored by Linus Lüssing's avatar Linus Lüssing Committed by Antonio Quartulli
Browse files

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: default avatarLinus Lüssing <linus.luessing@web.de>
Acked-by: default avatarSimon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: default avatarMarek Lindner <lindner_marek@yahoo.de>
parent 7f112af4
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -1167,6 +1167,8 @@ int batadv_bla_init(struct batadv_priv *bat_priv)
	uint16_t crc;
	unsigned long entrytime;

	spin_lock_init(&bat_priv->bla.bcast_duplist_lock);

	batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n");

	/* setting claim destination address */
@@ -1226,7 +1228,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 +1240,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 +1263,12 @@ 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 +1277,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;
}


+2 −0
Original line number Diff line number Diff line
@@ -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;
};