From f99bd4669843216d5e6723551c44297dd17fdc34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Fri, 28 Jul 2017 10:02:50 +0200 Subject: [PATCH] batman-adv: fix TT sync flag inconsistencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a proper patch for the DDoS characteristics some communities were seeing since upgrading to Gluon v2017.0 / batman-adv v2016.3. Signed-off-by: Linus Lüssing --- ...-Add-a-bugfix-for-batman-adv-v2017.1.patch | 225 ++++++++++++++++++ 1 file changed, 225 insertions(+) create mode 100644 patches/packages/routing/0002-batman-adv-Add-a-bugfix-for-batman-adv-v2017.1.patch diff --git a/patches/packages/routing/0002-batman-adv-Add-a-bugfix-for-batman-adv-v2017.1.patch b/patches/packages/routing/0002-batman-adv-Add-a-bugfix-for-batman-adv-v2017.1.patch new file mode 100644 index 00000000..d5ce76c4 --- /dev/null +++ b/patches/packages/routing/0002-batman-adv-Add-a-bugfix-for-batman-adv-v2017.1.patch @@ -0,0 +1,225 @@ +From: Linus Lüssing +Date: Fri, 28 Jul 2017 09:58:58 +0200 +Subject: batman-adv: Add a bugfix for batman-adv v2017.1 + +* batman-adv: fix TT sync flag inconsistencies + +Signed-off-by: Linus Lüssing + +diff --git a/batman-adv/patches/0001-batman-adv-fix-TT-sync-flag-inconsistencies.patch b/batman-adv/patches/0001-batman-adv-fix-TT-sync-flag-inconsistencies.patch +new file mode 100644 +index 0000000000000000000000000000000000000000..e885f0846a6b76f937c35815f56148fba8e428ac +--- /dev/null ++++ b/batman-adv/patches/0001-batman-adv-fix-TT-sync-flag-inconsistencies.patch +@@ -0,0 +1,211 @@ ++From fd54bf156fcfc3ed924f79a7e5e572b38d05a17c Mon Sep 17 00:00:00 2001 ++From: =?UTF-8?q?Linus=20L=C3=BCssing?= ++Date: Fri, 23 Jun 2017 17:00:59 +0200 ++Subject: [PATCH] batman-adv: fix TT sync flag inconsistencies ++MIME-Version: 1.0 ++Content-Type: text/plain; charset=UTF-8 ++Content-Transfer-Encoding: 8bit ++ ++This patch fixes an issue in the translation table code potentially ++leading to a TT Request + Response storm. The issue may occur for nodes ++involving BLA and an inconsistent configuration of the batman-adv AP ++isolation feature. However, since the new multicast optimizations, a ++single, malformed packet may lead to a mesh-wide, persistent ++Denial-of-Service, too. ++ ++The issue occurs because nodes are currently OR-ing the TT sync flags of ++all originators announcing a specific MAC address via the ++translation table. When an intermediate node now receives a TT Request ++and wants to answer this on behave of the destination node then this ++intermediate node now responds with an altered flag field and broken ++CRC. The next OGM of the real destination will lead to a CRC mismatch ++and triggering a TT Request and Response again. ++ ++Furthermore, the OR-ing is currently never undone as long as at least ++one originator announcing the according MAC address remains, leading to ++the potential persistency of this issue. ++ ++This patch fixes this issue by storing the flags used in the CRC ++calculation on a a per TT orig entry basis to be able to respond with ++the correct, original flags in an intermediate TT Response for one ++thing. And to be able to correctly unset sync flags once all nodes ++announcing a sync flag vanish for another. ++ ++Fixes: fa614fd04692 ("batman-adv: fix tt_global_entries flags update") ++Signed-off-by: Linus Lüssing ++--- ++ net/batman-adv/translation-table.c | 60 ++++++++++++++++++++++++++++++++------ ++ net/batman-adv/types.h | 2 ++ ++ 2 files changed, 53 insertions(+), 9 deletions(-) ++ ++diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c ++index e75b493..95b3c58 100644 ++--- a/net/batman-adv/translation-table.c +++++ b/net/batman-adv/translation-table.c ++@@ -1549,9 +1549,41 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, ++ return found; ++ } ++ +++/** +++ * batadv_tt_global_sync_flags - update TT sync flags +++ * @tt_global: the TT global entry to update sync flags in +++ * +++ * Updates the sync flag bits in the tt_global flag attribute with a logical +++ * OR of all sync flags from any of its TT orig entries. +++ */ +++static void +++batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global) +++{ +++ struct batadv_tt_orig_list_entry *orig_entry; +++ const struct hlist_head *head; +++ u16 flags = BATADV_NO_FLAGS; +++ +++ rcu_read_lock(); +++ head = &tt_global->orig_list; +++ hlist_for_each_entry_rcu(orig_entry, head, list) +++ flags |= orig_entry->flags; +++ rcu_read_unlock(); +++ +++ flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK); +++ tt_global->common.flags = flags; +++} +++ +++/** +++ * batadv_tt_global_orig_entry_add - add or update a TT orig entry +++ * @tt_global: the TT global entry to add an orig entry in +++ * @orig_node: the originator to add an orig entry for +++ * @ttvn: translation table version number of this changeset +++ * @flags: TT sync flags +++ */ ++ static void ++ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, ++- struct batadv_orig_node *orig_node, int ttvn) +++ struct batadv_orig_node *orig_node, int ttvn, +++ u8 flags) ++ { ++ struct batadv_tt_orig_list_entry *orig_entry; ++ ++@@ -1561,7 +1593,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, ++ * was added during a "temporary client detection" ++ */ ++ orig_entry->ttvn = ttvn; ++- goto out; +++ orig_entry->flags = flags; +++ goto sync_flags; ++ } ++ ++ orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC); ++@@ -1573,6 +1606,7 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, ++ batadv_tt_global_size_inc(orig_node, tt_global->common.vid); ++ orig_entry->orig_node = orig_node; ++ orig_entry->ttvn = ttvn; +++ orig_entry->flags = flags; ++ kref_init(&orig_entry->refcount); ++ ++ spin_lock_bh(&tt_global->list_lock); ++@@ -1582,6 +1616,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, ++ spin_unlock_bh(&tt_global->list_lock); ++ atomic_inc(&tt_global->orig_list_count); ++ +++sync_flags: +++ batadv_tt_global_sync_flags(tt_global); ++ out: ++ if (orig_entry) ++ batadv_tt_orig_list_entry_put(orig_entry); ++@@ -1703,10 +1739,10 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, ++ } ++ ++ /* the change can carry possible "attribute" flags like the ++- * TT_CLIENT_WIFI, therefore they have to be copied in the +++ * TT_CLIENT_TEMP, therefore they have to be copied in the ++ * client entry ++ */ ++- common->flags |= flags; +++ common->flags |= flags & (~BATADV_TT_SYNC_MASK); ++ ++ /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only ++ * one originator left in the list and we previously received a ++@@ -1723,7 +1759,8 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, ++ } ++ add_orig_entry: ++ /* add the new orig_entry (if needed) or update it */ ++- batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); +++ batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn, +++ flags & BATADV_TT_SYNC_MASK); ++ ++ batadv_dbg(BATADV_DBG_TT, bat_priv, ++ "Creating new global tt entry: %pM (vid: %d, via %pM)\n", ++@@ -1946,6 +1983,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, ++ struct batadv_tt_orig_list_entry *orig, ++ bool best) ++ { +++ u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags; ++ void *hdr; ++ struct batadv_orig_node_vlan *vlan; ++ u8 last_ttvn; ++@@ -1975,7 +2013,7 @@ batadv_tt_global_dump_subentry(struct sk_buff *msg, u32 portid, u32 seq, ++ nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) || ++ nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) || ++ nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) || ++- nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags)) +++ nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags)) ++ goto nla_put_failure; ++ ++ if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST)) ++@@ -2591,6 +2629,7 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, ++ unsigned short vid) ++ { ++ struct batadv_hashtable *hash = bat_priv->tt.global_hash; +++ struct batadv_tt_orig_list_entry *tt_orig; ++ struct batadv_tt_common_entry *tt_common; ++ struct batadv_tt_global_entry *tt_global; ++ struct hlist_head *head; ++@@ -2629,8 +2668,9 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, ++ /* find out if this global entry is announced by this ++ * originator ++ */ ++- if (!batadv_tt_global_entry_has_orig(tt_global, ++- orig_node)) +++ tt_orig = batadv_tt_global_orig_entry_find(tt_global, +++ orig_node); +++ if (!tt_orig) ++ continue; ++ ++ /* use network order to read the VID: this ensures that ++@@ -2642,10 +2682,12 @@ static u32 batadv_tt_global_crc(struct batadv_priv *bat_priv, ++ /* compute the CRC on flags that have to be kept in sync ++ * among nodes ++ */ ++- flags = tt_common->flags & BATADV_TT_SYNC_MASK; +++ flags = tt_orig->flags; ++ crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags)); ++ ++ crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN); +++ +++ batadv_tt_orig_list_entry_put(tt_orig); ++ } ++ rcu_read_unlock(); ++ } ++diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h ++index ea43a64..a627958 100644 ++--- a/net/batman-adv/types.h +++++ b/net/batman-adv/types.h ++@@ -1260,6 +1260,7 @@ struct batadv_tt_global_entry { ++ * struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client ++ * @orig_node: pointer to orig node announcing this non-mesh client ++ * @ttvn: translation table version number which added the non-mesh client +++ * @flags: per orig entry TT sync flags ++ * @list: list node for batadv_tt_global_entry::orig_list ++ * @refcount: number of contexts the object is used ++ * @rcu: struct used for freeing in an RCU-safe manner ++@@ -1267,6 +1268,7 @@ struct batadv_tt_global_entry { ++ struct batadv_tt_orig_list_entry { ++ struct batadv_orig_node *orig_node; ++ u8 ttvn; +++ u8 flags; ++ struct hlist_node list; ++ struct kref refcount; ++ struct rcu_head rcu; ++-- ++2.1.4 ++