| From 0ca81a2840f77855bbad1b9f172c545c4dc9e6a4 Mon Sep 17 00:00:00 2001 |
| From: Doron Tsur <doront@mellanox.com> |
| Date: Sun, 11 Oct 2015 15:58:17 +0300 |
| Subject: IB/cm: Fix rb-tree duplicate free and use-after-free |
| |
| 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: Zefan Li <lizefan@huawei.com> |
| --- |
| drivers/infiniband/core/cm.c | 10 +++++++++- |
| 1 file changed, 9 insertions(+), 1 deletion(-) |
| |
| --- 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 |
| 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; |
| |