]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.19.32/rdma-cma-rollback-source-ip-address-if-failing-to-acquire-device.patch
Linux 4.19.32
[thirdparty/kernel/stable-queue.git] / releases / 4.19.32 / rdma-cma-rollback-source-ip-address-if-failing-to-acquire-device.patch
CommitLineData
571e214c
GKH
1From 5fc01fb846bce8fa6d5f95e2625b8ce0f8e86810 Mon Sep 17 00:00:00 2001
2From: Myungho Jung <mhjungk@gmail.com>
3Date: Wed, 9 Jan 2019 22:27:31 -0800
4Subject: RDMA/cma: Rollback source IP address if failing to acquire device
5
6From: Myungho Jung <mhjungk@gmail.com>
7
8commit 5fc01fb846bce8fa6d5f95e2625b8ce0f8e86810 upstream.
9
10If cma_acquire_dev_by_src_ip() returns error in addr_handler(), the
11device state changes back to RDMA_CM_ADDR_BOUND but the resolved source
12IP address is still left. After that, if rdma_destroy_id() is called
13after rdma_listen(), the device is freed without removed from
14listen_any_list in cma_cancel_operation(). Revert to the previous IP
15address if acquiring device fails.
16
17Reported-by: syzbot+f3ce716af730c8f96637@syzkaller.appspotmail.com
18Signed-off-by: Myungho Jung <mhjungk@gmail.com>
19Reviewed-by: Parav Pandit <parav@mellanox.com>
20Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
21Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22
23---
24 drivers/infiniband/core/cma.c | 13 ++++++++++++-
25 1 file changed, 12 insertions(+), 1 deletion(-)
26
27--- a/drivers/infiniband/core/cma.c
28+++ b/drivers/infiniband/core/cma.c
29@@ -2854,13 +2854,22 @@ static void addr_handler(int status, str
30 {
31 struct rdma_id_private *id_priv = context;
32 struct rdma_cm_event event = {};
33+ struct sockaddr *addr;
34+ struct sockaddr_storage old_addr;
35
36 mutex_lock(&id_priv->handler_mutex);
37 if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY,
38 RDMA_CM_ADDR_RESOLVED))
39 goto out;
40
41- memcpy(cma_src_addr(id_priv), src_addr, rdma_addr_size(src_addr));
42+ /*
43+ * Store the previous src address, so that if we fail to acquire
44+ * matching rdma device, old address can be restored back, which helps
45+ * to cancel the cma listen operation correctly.
46+ */
47+ addr = cma_src_addr(id_priv);
48+ memcpy(&old_addr, addr, rdma_addr_size(addr));
49+ memcpy(addr, src_addr, rdma_addr_size(src_addr));
50 if (!status && !id_priv->cma_dev) {
51 status = cma_acquire_dev(id_priv, NULL);
52 if (status)
53@@ -2871,6 +2880,8 @@ static void addr_handler(int status, str
54 }
55
56 if (status) {
57+ memcpy(addr, &old_addr,
58+ rdma_addr_size((struct sockaddr *)&old_addr));
59 if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_RESOLVED,
60 RDMA_CM_ADDR_BOUND))
61 goto out;