On Wed, 2019-05-15 at 15:21 -0700, Thomas Pedersen wrote:
> ifmsh->csa was being dereferenced without the RCU read
> lock held.

> +++ b/net/mac80211/mesh.c
> @@ -1220,10 +1220,12 @@ int ieee80211_mesh_finish_csa(struct 
> ieee80211_sub_if_data *sdata)
>       ifmsh->chsw_ttl = 0;
>  
>       /* Remove the CSA and MCSP elements from the beacon */
> +     rcu_read_lock();
>       tmp_csa_settings = rcu_dereference(ifmsh->csa);
>       RCU_INIT_POINTER(ifmsh->csa, NULL);
>       if (tmp_csa_settings)
>               kfree_rcu(tmp_csa_settings, rcu_head);
> +     rcu_read_unlock();

This seems wrong to me.

Really this code is the *writer* side, so you should do something like
this:

diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 766e5e5bab8a..d578147ad7e8 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1220,7 +1220,8 @@ int ieee80211_mesh_finish_csa(struct
ieee80211_sub_if_data *sdata)
        ifmsh->chsw_ttl = 0;
 
        /* Remove the CSA and MCSP elements from the beacon */
-       tmp_csa_settings = rcu_dereference(ifmsh->csa);
+       tmp_csa_settings = rcu_dereference_protected(ifmsh->csa,
+                               lockdep_is_held(&sdata->wdev.mtx));
        RCU_INIT_POINTER(ifmsh->csa, NULL);
        if (tmp_csa_settings)
                kfree_rcu(tmp_csa_settings, rcu_head);
@@ -1242,6 +1243,8 @@ int ieee80211_mesh_csa_beacon(struct
ieee80211_sub_if_data *sdata,
        struct mesh_csa_settings *tmp_csa_settings;
        int ret = 0;
 
+       lockdep_assert_held(&sdata->wdev.mtx);
+
        tmp_csa_settings = kmalloc(sizeof(*tmp_csa_settings),
                                   GFP_ATOMIC);
        if (!tmp_csa_settings)


Can you test that and send a proper patch?

johannes

Reply via email to