|
@@ -105,6 +105,15 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
|
|
neigh_node = NULL;
|
|
neigh_node = NULL;
|
|
|
|
|
|
spin_lock_bh(&orig_node->neigh_list_lock);
|
|
spin_lock_bh(&orig_node->neigh_list_lock);
|
|
|
|
+ /* curr_router used earlier may not be the current orig_ifinfo->router
|
|
|
|
+ * anymore because it was dereferenced outside of the neigh_list_lock
|
|
|
|
+ * protected region. After the new best neighbor has replace the current
|
|
|
|
+ * best neighbor the reference counter needs to decrease. Consequently,
|
|
|
|
+ * the code needs to ensure the curr_router variable contains a pointer
|
|
|
|
+ * to the replaced best neighbor.
|
|
|
|
+ */
|
|
|
|
+ curr_router = rcu_dereference_protected(orig_ifinfo->router, true);
|
|
|
|
+
|
|
rcu_assign_pointer(orig_ifinfo->router, neigh_node);
|
|
rcu_assign_pointer(orig_ifinfo->router, neigh_node);
|
|
spin_unlock_bh(&orig_node->neigh_list_lock);
|
|
spin_unlock_bh(&orig_node->neigh_list_lock);
|
|
batadv_orig_ifinfo_put(orig_ifinfo);
|
|
batadv_orig_ifinfo_put(orig_ifinfo);
|