batman-adv: Merge bugfixes from 2018.3
[feed/routing.git] / batman-adv / patches / 0021-batman-adv-Prevent-duplicated-tvlv-handler.patch
1 From: Sven Eckelmann <sven@narfation.org>
2 Date: Thu, 6 Sep 2018 14:35:28 +0200
3 Subject: [PATCH] batman-adv: Prevent duplicated tvlv handler
4
5 The function batadv_tvlv_handler_register is responsible for adding new
6 tvlv_handler to the handler_list. It first checks whether the entry
7 already is in the list or not. If it is, then the creation of a new entry
8 is aborted.
9
10 But the lock for the list is only held when the list is really modified.
11 This could lead to duplicated entries because another context could create
12 an entry with the same key between the check and the list manipulation.
13
14 The check and the manipulation of the list must therefore be in the same
15 locked code section.
16
17 Fixes: 0b6aa0d43767 ("batman-adv: tvlv - basic infrastructure")
18 Signed-off-by: Sven Eckelmann <sven@narfation.org>
19 Acked-by: Marek Lindner <mareklindner@neomailbox.ch>
20
21 Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/acabad79e01740525cf4ff8ce6e9a210b683d420
22 ---
23 net/batman-adv/tvlv.c | 8 ++++++--
24 1 file changed, 6 insertions(+), 2 deletions(-)
25
26 diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c
27 index a637458205d16bf838f796383d8cc15ac861801b..40e69c9346d22c09481544b8b4dec56cad88b64a 100644
28 --- a/net/batman-adv/tvlv.c
29 +++ b/net/batman-adv/tvlv.c
30 @@ -529,15 +529,20 @@ void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
31 {
32 struct batadv_tvlv_handler *tvlv_handler;
33
34 + spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
35 +
36 tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
37 if (tvlv_handler) {
38 + spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
39 batadv_tvlv_handler_put(tvlv_handler);
40 return;
41 }
42
43 tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC);
44 - if (!tvlv_handler)
45 + if (!tvlv_handler) {
46 + spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
47 return;
48 + }
49
50 tvlv_handler->ogm_handler = optr;
51 tvlv_handler->unicast_handler = uptr;
52 @@ -547,7 +552,6 @@ void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
53 kref_init(&tvlv_handler->refcount);
54 INIT_HLIST_NODE(&tvlv_handler->list);
55
56 - spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
57 kref_get(&tvlv_handler->refcount);
58 hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list);
59 spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);