]>
Commit | Line | Data |
---|---|---|
571e214c GKH |
1 | From 5fc01fb846bce8fa6d5f95e2625b8ce0f8e86810 Mon Sep 17 00:00:00 2001 |
2 | From: Myungho Jung <mhjungk@gmail.com> | |
3 | Date: Wed, 9 Jan 2019 22:27:31 -0800 | |
4 | Subject: RDMA/cma: Rollback source IP address if failing to acquire device | |
5 | ||
6 | From: Myungho Jung <mhjungk@gmail.com> | |
7 | ||
8 | commit 5fc01fb846bce8fa6d5f95e2625b8ce0f8e86810 upstream. | |
9 | ||
10 | If cma_acquire_dev_by_src_ip() returns error in addr_handler(), the | |
11 | device state changes back to RDMA_CM_ADDR_BOUND but the resolved source | |
12 | IP address is still left. After that, if rdma_destroy_id() is called | |
13 | after rdma_listen(), the device is freed without removed from | |
14 | listen_any_list in cma_cancel_operation(). Revert to the previous IP | |
15 | address if acquiring device fails. | |
16 | ||
17 | Reported-by: syzbot+f3ce716af730c8f96637@syzkaller.appspotmail.com | |
18 | Signed-off-by: Myungho Jung <mhjungk@gmail.com> | |
19 | Reviewed-by: Parav Pandit <parav@mellanox.com> | |
20 | Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> | |
21 | Signed-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; |