Skip to content

Commit e3ffec4

Browse files
committed
Merge tag 'batadv-net-for-davem-20180524' of git://git.open-mesh.org/linux-merge
Simon Wunderlich says: ==================== Here are some batman-adv bugfixes: - prevent hardif_put call with NULL parameter, by Colin Ian King - Avoid race in Translation Table allocator, by Sven Eckelmann - Fix Translation Table sync flags for intermediate Responses, by Linus Luessing - prevent sending inconsistent Translation Table TVLVs, by Marek Lindner ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 1383cb8 + 16116da commit e3ffec4

File tree

2 files changed

+68
-18
lines changed

2 files changed

+68
-18
lines changed

net/batman-adv/multicast.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1536,7 +1536,7 @@ batadv_mcast_netlink_get_primary(struct netlink_callback *cb,
15361536

15371537
if (!ret && primary_if)
15381538
*primary_if = hard_iface;
1539-
else
1539+
else if (hard_iface)
15401540
batadv_hardif_put(hard_iface);
15411541

15421542
return ret;

net/batman-adv/translation-table.c

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
862862
struct batadv_orig_node_vlan *vlan;
863863
u8 *tt_change_ptr;
864864

865-
rcu_read_lock();
865+
spin_lock_bh(&orig_node->vlan_list_lock);
866866
hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
867867
num_vlan++;
868868
num_entries += atomic_read(&vlan->tt.num_entries);
@@ -900,7 +900,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
900900
*tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
901901

902902
out:
903-
rcu_read_unlock();
903+
spin_unlock_bh(&orig_node->vlan_list_lock);
904904
return tvlv_len;
905905
}
906906

@@ -931,23 +931,28 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
931931
struct batadv_tvlv_tt_vlan_data *tt_vlan;
932932
struct batadv_softif_vlan *vlan;
933933
u16 num_vlan = 0;
934-
u16 num_entries = 0;
934+
u16 vlan_entries = 0;
935+
u16 total_entries = 0;
935936
u16 tvlv_len;
936937
u8 *tt_change_ptr;
937938
int change_offset;
938939

939-
rcu_read_lock();
940+
spin_lock_bh(&bat_priv->softif_vlan_list_lock);
940941
hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
942+
vlan_entries = atomic_read(&vlan->tt.num_entries);
943+
if (vlan_entries < 1)
944+
continue;
945+
941946
num_vlan++;
942-
num_entries += atomic_read(&vlan->tt.num_entries);
947+
total_entries += vlan_entries;
943948
}
944949

945950
change_offset = sizeof(**tt_data);
946951
change_offset += num_vlan * sizeof(*tt_vlan);
947952

948953
/* if tt_len is negative, allocate the space needed by the full table */
949954
if (*tt_len < 0)
950-
*tt_len = batadv_tt_len(num_entries);
955+
*tt_len = batadv_tt_len(total_entries);
951956

952957
tvlv_len = *tt_len;
953958
tvlv_len += change_offset;
@@ -964,6 +969,10 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
964969

965970
tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
966971
hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
972+
vlan_entries = atomic_read(&vlan->tt.num_entries);
973+
if (vlan_entries < 1)
974+
continue;
975+
967976
tt_vlan->vid = htons(vlan->vid);
968977
tt_vlan->crc = htonl(vlan->tt.crc);
969978

@@ -974,7 +983,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
974983
*tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
975984

976985
out:
977-
rcu_read_unlock();
986+
spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
978987
return tvlv_len;
979988
}
980989

@@ -1538,21 +1547,28 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
15381547
* handled by a given originator
15391548
* @entry: the TT global entry to check
15401549
* @orig_node: the originator to search in the list
1550+
* @flags: a pointer to store TT flags for the given @entry received
1551+
* from @orig_node
15411552
*
15421553
* find out if an orig_node is already in the list of a tt_global_entry.
15431554
*
15441555
* Return: true if found, false otherwise
15451556
*/
15461557
static bool
15471558
batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
1548-
const struct batadv_orig_node *orig_node)
1559+
const struct batadv_orig_node *orig_node,
1560+
u8 *flags)
15491561
{
15501562
struct batadv_tt_orig_list_entry *orig_entry;
15511563
bool found = false;
15521564

15531565
orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
15541566
if (orig_entry) {
15551567
found = true;
1568+
1569+
if (flags)
1570+
*flags = orig_entry->flags;
1571+
15561572
batadv_tt_orig_list_entry_put(orig_entry);
15571573
}
15581574

@@ -1731,7 +1747,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
17311747
if (!(common->flags & BATADV_TT_CLIENT_TEMP))
17321748
goto out;
17331749
if (batadv_tt_global_entry_has_orig(tt_global_entry,
1734-
orig_node))
1750+
orig_node, NULL))
17351751
goto out_remove;
17361752
batadv_tt_global_del_orig_list(tt_global_entry);
17371753
goto add_orig_entry;
@@ -2880,23 +2896,46 @@ batadv_tt_req_node_new(struct batadv_priv *bat_priv,
28802896
}
28812897

28822898
/**
2883-
* batadv_tt_local_valid() - verify that given tt entry is a valid one
2899+
* batadv_tt_local_valid() - verify local tt entry and get flags
28842900
* @entry_ptr: to be checked local tt entry
28852901
* @data_ptr: not used but definition required to satisfy the callback prototype
2902+
* @flags: a pointer to store TT flags for this client to
2903+
*
2904+
* Checks the validity of the given local TT entry. If it is, then the provided
2905+
* flags pointer is updated.
28862906
*
28872907
* Return: true if the entry is a valid, false otherwise.
28882908
*/
2889-
static bool batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
2909+
static bool batadv_tt_local_valid(const void *entry_ptr,
2910+
const void *data_ptr,
2911+
u8 *flags)
28902912
{
28912913
const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
28922914

28932915
if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
28942916
return false;
2917+
2918+
if (flags)
2919+
*flags = tt_common_entry->flags;
2920+
28952921
return true;
28962922
}
28972923

2924+
/**
2925+
* batadv_tt_global_valid() - verify global tt entry and get flags
2926+
* @entry_ptr: to be checked global tt entry
2927+
* @data_ptr: an orig_node object (may be NULL)
2928+
* @flags: a pointer to store TT flags for this client to
2929+
*
2930+
* Checks the validity of the given global TT entry. If it is, then the provided
2931+
* flags pointer is updated either with the common (summed) TT flags if data_ptr
2932+
* is NULL or the specific, per originator TT flags otherwise.
2933+
*
2934+
* Return: true if the entry is a valid, false otherwise.
2935+
*/
28982936
static bool batadv_tt_global_valid(const void *entry_ptr,
2899-
const void *data_ptr)
2937+
const void *data_ptr,
2938+
u8 *flags)
29002939
{
29012940
const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
29022941
const struct batadv_tt_global_entry *tt_global_entry;
@@ -2910,7 +2949,8 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
29102949
struct batadv_tt_global_entry,
29112950
common);
29122951

2913-
return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
2952+
return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node,
2953+
flags);
29142954
}
29152955

29162956
/**
@@ -2920,25 +2960,34 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
29202960
* @hash: hash table containing the tt entries
29212961
* @tt_len: expected tvlv tt data buffer length in number of bytes
29222962
* @tvlv_buff: pointer to the buffer to fill with the TT data
2923-
* @valid_cb: function to filter tt change entries
2963+
* @valid_cb: function to filter tt change entries and to return TT flags
29242964
* @cb_data: data passed to the filter function as argument
2965+
*
2966+
* Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
2967+
* is not provided then this becomes a no-op.
29252968
*/
29262969
static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
29272970
struct batadv_hashtable *hash,
29282971
void *tvlv_buff, u16 tt_len,
29292972
bool (*valid_cb)(const void *,
2930-
const void *),
2973+
const void *,
2974+
u8 *flags),
29312975
void *cb_data)
29322976
{
29332977
struct batadv_tt_common_entry *tt_common_entry;
29342978
struct batadv_tvlv_tt_change *tt_change;
29352979
struct hlist_head *head;
29362980
u16 tt_tot, tt_num_entries = 0;
2981+
u8 flags;
2982+
bool ret;
29372983
u32 i;
29382984

29392985
tt_tot = batadv_tt_entries(tt_len);
29402986
tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
29412987

2988+
if (!valid_cb)
2989+
return;
2990+
29422991
rcu_read_lock();
29432992
for (i = 0; i < hash->size; i++) {
29442993
head = &hash->table[i];
@@ -2948,11 +2997,12 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
29482997
if (tt_tot == tt_num_entries)
29492998
break;
29502999

2951-
if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
3000+
ret = valid_cb(tt_common_entry, cb_data, &flags);
3001+
if (!ret)
29523002
continue;
29533003

29543004
ether_addr_copy(tt_change->addr, tt_common_entry->addr);
2955-
tt_change->flags = tt_common_entry->flags;
3005+
tt_change->flags = flags;
29563006
tt_change->vid = htons(tt_common_entry->vid);
29573007
memset(tt_change->reserved, 0,
29583008
sizeof(tt_change->reserved));

0 commit comments

Comments
 (0)