Skip to content

Commit a33d970

Browse files
ecsvordex
authored andcommitted
batman-adv: Fix reference counting of vlan object for tt_local_entry
The batadv_tt_local_entry was specific to a batadv_softif_vlan and held an implicit reference to it. But this reference was never stored in form of a pointer in the tt_local_entry itself. Instead batadv_tt_local_remove, batadv_tt_local_table_free and batadv_tt_local_purge_pending_clients depend on a consistent state of bat_priv->softif_vlan_list and that batadv_softif_vlan_get always returns the batadv_softif_vlan object which it has a reference for. But batadv_softif_vlan_get cannot guarantee that because it is working only with rcu_read_lock on this list. It can therefore happen that an vid is in this list twice or that batadv_softif_vlan_get cannot find the batadv_softif_vlan for an vid due to some other list operations taking place at the same time. Instead add a batadv_softif_vlan pointer directly in batadv_tt_local_entry which will be used for the reference counter decremented on release of batadv_tt_local_entry. Fixes: 35df3b2 ("batman-adv: fix TT VLAN inconsistency on VLAN re-add") Signed-off-by: Sven Eckelmann <sven@narfation.org> Acked-by: Antonio Quartulli <a@unstable.cc> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Antonio Quartulli <a@unstable.cc>
1 parent b6cf5d4 commit a33d970

File tree

2 files changed

+6
-38
lines changed

2 files changed

+6
-38
lines changed

net/batman-adv/translation-table.c

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ static void batadv_tt_local_entry_release(struct kref *ref)
215215
tt_local_entry = container_of(ref, struct batadv_tt_local_entry,
216216
common.refcount);
217217

218+
batadv_softif_vlan_put(tt_local_entry->vlan);
219+
218220
kfree_rcu(tt_local_entry, common.rcu);
219221
}
220222

@@ -673,6 +675,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
673675
kref_get(&tt_local->common.refcount);
674676
tt_local->last_seen = jiffies;
675677
tt_local->common.added_at = tt_local->last_seen;
678+
tt_local->vlan = vlan;
676679

677680
/* the batman interface mac and multicast addresses should never be
678681
* purged
@@ -991,7 +994,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
991994
struct batadv_tt_common_entry *tt_common_entry;
992995
struct batadv_tt_local_entry *tt_local;
993996
struct batadv_hard_iface *primary_if;
994-
struct batadv_softif_vlan *vlan;
995997
struct hlist_head *head;
996998
unsigned short vid;
997999
u32 i;
@@ -1027,14 +1029,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
10271029
last_seen_msecs = last_seen_msecs % 1000;
10281030

10291031
no_purge = tt_common_entry->flags & np_flag;
1030-
1031-
vlan = batadv_softif_vlan_get(bat_priv, vid);
1032-
if (!vlan) {
1033-
seq_printf(seq, "Cannot retrieve VLAN %d\n",
1034-
BATADV_PRINT_VID(vid));
1035-
continue;
1036-
}
1037-
10381032
seq_printf(seq,
10391033
" * %pM %4i [%c%c%c%c%c%c] %3u.%03u (%#.8x)\n",
10401034
tt_common_entry->addr,
@@ -1052,9 +1046,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
10521046
BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
10531047
no_purge ? 0 : last_seen_secs,
10541048
no_purge ? 0 : last_seen_msecs,
1055-
vlan->tt.crc);
1056-
1057-
batadv_softif_vlan_put(vlan);
1049+
tt_local->vlan->tt.crc);
10581050
}
10591051
rcu_read_unlock();
10601052
}
@@ -1099,7 +1091,6 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
10991091
{
11001092
struct batadv_tt_local_entry *tt_local_entry;
11011093
u16 flags, curr_flags = BATADV_NO_FLAGS;
1102-
struct batadv_softif_vlan *vlan;
11031094
void *tt_entry_exists;
11041095

11051096
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
@@ -1139,14 +1130,6 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
11391130
/* extra call to free the local tt entry */
11401131
batadv_tt_local_entry_put(tt_local_entry);
11411132

1142-
/* decrease the reference held for this vlan */
1143-
vlan = batadv_softif_vlan_get(bat_priv, vid);
1144-
if (!vlan)
1145-
goto out;
1146-
1147-
batadv_softif_vlan_put(vlan);
1148-
batadv_softif_vlan_put(vlan);
1149-
11501133
out:
11511134
if (tt_local_entry)
11521135
batadv_tt_local_entry_put(tt_local_entry);
@@ -1219,7 +1202,6 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
12191202
spinlock_t *list_lock; /* protects write access to the hash lists */
12201203
struct batadv_tt_common_entry *tt_common_entry;
12211204
struct batadv_tt_local_entry *tt_local;
1222-
struct batadv_softif_vlan *vlan;
12231205
struct hlist_node *node_tmp;
12241206
struct hlist_head *head;
12251207
u32 i;
@@ -1241,14 +1223,6 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
12411223
struct batadv_tt_local_entry,
12421224
common);
12431225

1244-
/* decrease the reference held for this vlan */
1245-
vlan = batadv_softif_vlan_get(bat_priv,
1246-
tt_common_entry->vid);
1247-
if (vlan) {
1248-
batadv_softif_vlan_put(vlan);
1249-
batadv_softif_vlan_put(vlan);
1250-
}
1251-
12521226
batadv_tt_local_entry_put(tt_local);
12531227
}
12541228
spin_unlock_bh(list_lock);
@@ -3309,7 +3283,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
33093283
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
33103284
struct batadv_tt_common_entry *tt_common;
33113285
struct batadv_tt_local_entry *tt_local;
3312-
struct batadv_softif_vlan *vlan;
33133286
struct hlist_node *node_tmp;
33143287
struct hlist_head *head;
33153288
spinlock_t *list_lock; /* protects write access to the hash lists */
@@ -3339,13 +3312,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
33393312
struct batadv_tt_local_entry,
33403313
common);
33413314

3342-
/* decrease the reference held for this vlan */
3343-
vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
3344-
if (vlan) {
3345-
batadv_softif_vlan_put(vlan);
3346-
batadv_softif_vlan_put(vlan);
3347-
}
3348-
33493315
batadv_tt_local_entry_put(tt_local);
33503316
}
33513317
spin_unlock_bh(list_lock);

net/batman-adv/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,10 +1073,12 @@ struct batadv_tt_common_entry {
10731073
* struct batadv_tt_local_entry - translation table local entry data
10741074
* @common: general translation table data
10751075
* @last_seen: timestamp used for purging stale tt local entries
1076+
* @vlan: soft-interface vlan of the entry
10761077
*/
10771078
struct batadv_tt_local_entry {
10781079
struct batadv_tt_common_entry common;
10791080
unsigned long last_seen;
1081+
struct batadv_softif_vlan *vlan;
10801082
};
10811083

10821084
/**

0 commit comments

Comments
 (0)