lkml.org 
[lkml]   [2016]   [Jan]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.16.y-ckt 105/126] mac80211: mesh: fix call_rcu() usage
    Date
    3.16.7-ckt22 -stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Johannes Berg <johannes.berg@intel.com>

    commit c2e703a55245bfff3db53b1f7cbe59f1ee8a4339 upstream.

    When using call_rcu(), the called function may be delayed quite
    significantly, and without a matching rcu_barrier() there's no
    way to be sure it has finished.
    Therefore, global state that could be gone/freed/reused should
    never be touched in the callback.

    Fix this in mesh by moving the atomic_dec() into the caller;
    that's not really a problem since we already unlinked the path
    and it will be destroyed anyway.

    This fixes a crash Jouni observed when running certain tests in
    a certain order, in which the mesh interface was torn down, the
    memory reused for a function pointer (work struct) and running
    that then crashed since the pointer had been decremented by 1,
    resulting in an invalid instruction byte stream.

    Fixes: eb2b9311fd00 ("mac80211: mesh path table implementation")
    Reported-by: Jouni Malinen <j@w1.fi>
    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
    Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
    ---
    net/mac80211/mesh_pathtbl.c | 8 ++++----
    1 file changed, 4 insertions(+), 4 deletions(-)

    diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
    index cf032a8db9d7..8830af725bc6 100644
    --- a/net/mac80211/mesh_pathtbl.c
    +++ b/net/mac80211/mesh_pathtbl.c
    @@ -748,10 +748,8 @@ void mesh_plink_broken(struct sta_info *sta)
    static void mesh_path_node_reclaim(struct rcu_head *rp)
    {
    struct mpath_node *node = container_of(rp, struct mpath_node, rcu);
    - struct ieee80211_sub_if_data *sdata = node->mpath->sdata;

    del_timer_sync(&node->mpath->timer);
    - atomic_dec(&sdata->u.mesh.mpaths);
    kfree(node->mpath);
    kfree(node);
    }
    @@ -759,8 +757,9 @@ static void mesh_path_node_reclaim(struct rcu_head *rp)
    /* needs to be called with the corresponding hashwlock taken */
    static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node)
    {
    - struct mesh_path *mpath;
    - mpath = node->mpath;
    + struct mesh_path *mpath = node->mpath;
    + struct ieee80211_sub_if_data *sdata = node->mpath->sdata;
    +
    spin_lock(&mpath->state_lock);
    mpath->flags |= MESH_PATH_RESOLVING;
    if (mpath->is_gate)
    @@ -768,6 +767,7 @@ static void __mesh_path_del(struct mesh_table *tbl, struct mpath_node *node)
    hlist_del_rcu(&node->list);
    call_rcu(&node->rcu, mesh_path_node_reclaim);
    spin_unlock(&mpath->state_lock);
    + atomic_dec(&sdata->u.mesh.mpaths);
    atomic_dec(&tbl->entries);
    }


    \
     
     \ /
      Last update: 2016-01-06 12:21    [W:4.104 / U:0.220 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site