[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1460976397-5688-43-git-send-email-lizf@kernel.org>
Date: Mon, 18 Apr 2016 18:45:48 +0800
From: lizf@...nel.org
To: stable@...r.kernel.org
Cc: linux-kernel@...r.kernel.org, Doron Tsur <doront@...lanox.com>,
Matan Barak <matanb@...lanox.com>,
Doug Ledford <dledford@...hat.com>,
Zefan Li <lizefan@...wei.com>
Subject: [PATCH 3.4 43/92] IB/cm: Fix rb-tree duplicate free and use-after-free
From: Doron Tsur <doront@...lanox.com>
3.4.112-rc1 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@...lanox.com>
Signed-off-by: Matan Barak <matanb@...lanox.com>
Signed-off-by: Doug Ledford <dledford@...hat.com>
Signed-off-by: Zefan Li <lizefan@...wei.com>
---
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 c889aae..90104c6 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -856,6 +856,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);
@@ -3092,7 +3097,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;
--
1.9.1
Powered by blists - more mailing lists