]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
batman-adv: tt: prevent TVLV entry number overflow
authorSven Eckelmann <sven@narfation.org>
Sat, 2 May 2026 19:25:19 +0000 (21:25 +0200)
committerSven Eckelmann <sven@narfation.org>
Tue, 12 May 2026 06:33:53 +0000 (08:33 +0200)
The helpers to prepare the buffers for the local and global TT based
replies are trying to sum up all TT entries which can be found for each
VLAN. In theory, this sum can be too big for an u16 and therefore overflow.
A too small buffer would then be allocated for the TVLV.

The too small buffer will be handled gracefully by
batadv_tt_tvlv_generate() and is not causing a buffer overflow - just a
truncated reply. But this overflow shouldn't have happened in the first and
the too small buffer should never have been allocated when an overflow was
detected.

Cc: stable@kernel.org
Fixes: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
net/batman-adv/translation-table.c

index 2259b241e0b56b1433f0dc77d6d1961fb7f17ed9..9f6e67771ffa800b1d85c7183eff5b017b968892 100644 (file)
@@ -804,11 +804,18 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
        u16 total_entries = 0;
        u8 *tt_change_ptr;
        int vlan_entries;
+       u16 sum_entries;
 
        spin_lock_bh(&orig_node->vlan_list_lock);
        hlist_for_each_entry(vlan, &orig_node->vlan_list, list) {
                vlan_entries = atomic_read(&vlan->tt.num_entries);
-               total_entries += vlan_entries;
+
+               if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
+                       *tt_len = 0;
+                       goto out;
+               }
+
+               total_entries = sum_entries;
                num_vlan++;
        }
 
@@ -893,15 +900,22 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
        struct batadv_meshif_vlan *vlan;
        size_t change_offset;
        u16 num_vlan = 0;
-       u16 vlan_entries = 0;
        u16 total_entries = 0;
        u16 tvlv_len;
        u8 *tt_change_ptr;
+       int vlan_entries;
+       u16 sum_entries;
 
        spin_lock_bh(&bat_priv->meshif_vlan_list_lock);
        hlist_for_each_entry(vlan, &bat_priv->meshif_vlan_list, list) {
                vlan_entries = atomic_read(&vlan->tt.num_entries);
-               total_entries += vlan_entries;
+
+               if (check_add_overflow(vlan_entries, total_entries, &sum_entries)) {
+                       tvlv_len = 0;
+                       goto out;
+               }
+
+               total_entries = sum_entries;
                num_vlan++;
        }