]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.14.57/ib-cm-fix-rb-tree-duplicate-free-and-use-after-free.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 3.14.57 / ib-cm-fix-rb-tree-duplicate-free-and-use-after-free.patch
1 From 0ca81a2840f77855bbad1b9f172c545c4dc9e6a4 Mon Sep 17 00:00:00 2001
2 From: Doron Tsur <doront@mellanox.com>
3 Date: Sun, 11 Oct 2015 15:58:17 +0300
4 Subject: IB/cm: Fix rb-tree duplicate free and use-after-free
5
6 From: Doron Tsur <doront@mellanox.com>
7
8 commit 0ca81a2840f77855bbad1b9f172c545c4dc9e6a4 upstream.
9
10 ib_send_cm_sidr_rep could sometimes erase the node from the sidr
11 (depending on errors in the process). Since ib_send_cm_sidr_rep is
12 called both from cm_sidr_req_handler and cm_destroy_id, cm_id_priv
13 could be either erased from the rb_tree twice or not erased at all.
14 Fixing that by making sure it's erased only once before freeing
15 cm_id_priv.
16
17 Fixes: a977049dacde ('[PATCH] IB: Add the kernel CM implementation')
18 Signed-off-by: Doron Tsur <doront@mellanox.com>
19 Signed-off-by: Matan Barak <matanb@mellanox.com>
20 Signed-off-by: Doug Ledford <dledford@redhat.com>
21 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22
23 ---
24 drivers/infiniband/core/cm.c | 10 +++++++++-
25 1 file changed, 9 insertions(+), 1 deletion(-)
26
27 --- a/drivers/infiniband/core/cm.c
28 +++ b/drivers/infiniband/core/cm.c
29 @@ -860,6 +860,11 @@ retest:
30 case IB_CM_SIDR_REQ_RCVD:
31 spin_unlock_irq(&cm_id_priv->lock);
32 cm_reject_sidr_req(cm_id_priv, IB_SIDR_REJECT);
33 + spin_lock_irq(&cm.lock);
34 + if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node))
35 + rb_erase(&cm_id_priv->sidr_id_node,
36 + &cm.remote_sidr_table);
37 + spin_unlock_irq(&cm.lock);
38 break;
39 case IB_CM_REQ_SENT:
40 ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
41 @@ -3099,7 +3104,10 @@ int ib_send_cm_sidr_rep(struct ib_cm_id
42 spin_unlock_irqrestore(&cm_id_priv->lock, flags);
43
44 spin_lock_irqsave(&cm.lock, flags);
45 - rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
46 + if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) {
47 + rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table);
48 + RB_CLEAR_NODE(&cm_id_priv->sidr_id_node);
49 + }
50 spin_unlock_irqrestore(&cm.lock, flags);
51 return 0;
52