Skip to content

Commit fa122fe

Browse files
ecsvsimonwunderlich
authored andcommitted
batman-adv: Prevent duplicated nc_node entry
The function batadv_nc_get_nc_node is responsible for adding new nc_nodes to the in_coding_list and out_coding_list. It first checks whether the entry already is in the list or not. If it is, then the creation of a new entry is aborted. But the lock for the list is only held when the list is really modified. This could lead to duplicated entries because another context could create an entry with the same key between the check and the list manipulation. The check and the manipulation of the list must therefore be in the same locked code section. Fixes: d56b170 ("batman-adv: network coding - detect coding nodes and remove these after timeout") Signed-off-by: Sven Eckelmann <[email protected]> Acked-by: Marek Lindner <[email protected]> Signed-off-by: Simon Wunderlich <[email protected]>
1 parent dff9bc4 commit fa122fe

File tree

1 file changed

+15
-12
lines changed

1 file changed

+15
-12
lines changed

net/batman-adv/network-coding.c

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -854,16 +854,27 @@ batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
854854
spinlock_t *lock; /* Used to lock list selected by "int in_coding" */
855855
struct list_head *list;
856856

857+
/* Select ingoing or outgoing coding node */
858+
if (in_coding) {
859+
lock = &orig_neigh_node->in_coding_list_lock;
860+
list = &orig_neigh_node->in_coding_list;
861+
} else {
862+
lock = &orig_neigh_node->out_coding_list_lock;
863+
list = &orig_neigh_node->out_coding_list;
864+
}
865+
866+
spin_lock_bh(lock);
867+
857868
/* Check if nc_node is already added */
858869
nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding);
859870

860871
/* Node found */
861872
if (nc_node)
862-
return nc_node;
873+
goto unlock;
863874

864875
nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC);
865876
if (!nc_node)
866-
return NULL;
877+
goto unlock;
867878

868879
/* Initialize nc_node */
869880
INIT_LIST_HEAD(&nc_node->list);
@@ -872,22 +883,14 @@ batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
872883
kref_get(&orig_neigh_node->refcount);
873884
nc_node->orig_node = orig_neigh_node;
874885

875-
/* Select ingoing or outgoing coding node */
876-
if (in_coding) {
877-
lock = &orig_neigh_node->in_coding_list_lock;
878-
list = &orig_neigh_node->in_coding_list;
879-
} else {
880-
lock = &orig_neigh_node->out_coding_list_lock;
881-
list = &orig_neigh_node->out_coding_list;
882-
}
883-
884886
batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n",
885887
nc_node->addr, nc_node->orig_node->orig);
886888

887889
/* Add nc_node to orig_node */
888-
spin_lock_bh(lock);
889890
kref_get(&nc_node->refcount);
890891
list_add_tail_rcu(&nc_node->list, list);
892+
893+
unlock:
891894
spin_unlock_bh(lock);
892895

893896
return nc_node;

0 commit comments

Comments
 (0)