lkml.org 
[lkml]   [2015]   [Nov]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.12 24/72] IB/cm: Fix rb-tree duplicate free and use-after-free
    Date
    From: Doron Tsur <doront@mellanox.com>

    3.12-stable review patch. If anyone has any objections, please let me know.

    ===============

    commit 0ca81a2840f77855bbad1b9f172c545c4dc9e6a4 upstream.

    ib_send_cm_sidr_rep could sometimes erase the node from the sidr
    (depending on errors in the process). Since ib_send_cm_sidr_rep is
    called both from cm_sidr_req_handler and cm_destroy_id, cm_id_priv
    could be either erased from the rb_tree twice or not erased at all.
    Fixing that by making sure it's erased only once before freeing
    cm_id_priv.

    Fixes: a977049dacde ('[PATCH] IB: Add the kernel CM implementation')
    Signed-off-by: Doron Tsur <doront@mellanox.com>
    Signed-off-by: Matan Barak <matanb@mellanox.com>
    Signed-off-by: Doug Ledford <dledford@redhat.com>
    Signed-off-by: Jiri Slaby <jslaby@suse.cz>
    ---
    drivers/infiniband/core/cm.c | 10 +++++++++-
    1 file changed, 9 insertions(+), 1 deletion(-)

    diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
    index 784b97cb05b0..c410217fbe89 100644
    --- a/drivers/infiniband/core/cm.c
    +++ b/drivers/infiniband/core/cm.c
    @@ -857,6 +857,11 @@ retest:
    case IB_CM_SIDR_REQ_RCVD:
    spin_unlock_irq(&cm_id_priv->lock);
    cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
    + spin_lock_irq(&cm.lock);
    + if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
    + rb_erase(&cm_id_priv->sidr_id_node,
    + &cm.remote_sidr_table);
    + spin_unlock_irq(&cm.lock);
    break;
    case IB_CM_REQ_SENT:
    ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
    @@ -3093,7 +3098,10 @@ int ib_send_cm_sidr_rep(struct ib_cm_id *cm_id,
    spin_unlock_irqrestore(&cm_id_priv->lock, flags);

    spin_lock_irqsave(&cm.lock, flags);
    - rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
    + if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
    + rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
    + RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
    + }
    spin_unlock_irqrestore(&cm.lock, flags);
    return 0;

    --
    2.6.3


    \
     
     \ /
      Last update: 2015-11-23 14:41    [W:7.491 / U:0.916 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site