| From e4103312d7b7afb8a3a7a842a33ef2b1856b2c0f Mon Sep 17 00:00:00 2001 |
| From: Parav Pandit <parav@mellanox.com> |
| Date: Wed, 12 Feb 2020 09:26:29 +0200 |
| Subject: Revert "RDMA/cma: Simplify rdma_resolve_addr() error flow" |
| |
| From: Parav Pandit <parav@mellanox.com> |
| |
| commit e4103312d7b7afb8a3a7a842a33ef2b1856b2c0f upstream. |
| |
| This reverts commit 219d2e9dfda9431b808c28d5efc74b404b95b638. |
| |
| The call chain below requires the cm_id_priv's destination address to be |
| setup before performing rdma_bind_addr(). Otherwise source port allocation |
| fails as cma_port_is_unique() no longer sees the correct tuple to allow |
| duplicate users of the source port. |
| |
| rdma_resolve_addr() |
| cma_bind_addr() |
| rdma_bind_addr() |
| cma_get_port() |
| cma_alloc_any_port() |
| cma_port_is_unique() <- compared with zero daddr |
| |
| This can result in false failures to connect, particularly if the source |
| port range is restricted. |
| |
| Fixes: 219d2e9dfda9 ("RDMA/cma: Simplify rdma_resolve_addr() error flow") |
| Link: https://lore.kernel.org/r/20200212072635.682689-4-leon@kernel.org |
| Signed-off-by: Parav Pandit <parav@mellanox.com> |
| Signed-off-by: Leon Romanovsky <leonro@mellanox.com> |
| Signed-off-by: Jason Gunthorpe <jgg@mellanox.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/infiniband/core/cma.c | 15 +++++++++++---- |
| 1 file changed, 11 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/infiniband/core/cma.c |
| +++ b/drivers/infiniband/core/cma.c |
| @@ -3182,19 +3182,26 @@ int rdma_resolve_addr(struct rdma_cm_id |
| int ret; |
| |
| id_priv = container_of(id, struct rdma_id_private, id); |
| + memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); |
| if (id_priv->state == RDMA_CM_IDLE) { |
| ret = cma_bind_addr(id, src_addr, dst_addr); |
| - if (ret) |
| + if (ret) { |
| + memset(cma_dst_addr(id_priv), 0, |
| + rdma_addr_size(dst_addr)); |
| return ret; |
| + } |
| } |
| |
| - if (cma_family(id_priv) != dst_addr->sa_family) |
| + if (cma_family(id_priv) != dst_addr->sa_family) { |
| + memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr)); |
| return -EINVAL; |
| + } |
| |
| - if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) |
| + if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_BOUND, RDMA_CM_ADDR_QUERY)) { |
| + memset(cma_dst_addr(id_priv), 0, rdma_addr_size(dst_addr)); |
| return -EINVAL; |
| + } |
| |
| - memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr)); |
| if (cma_any_addr(dst_addr)) { |
| ret = cma_resolve_loopback(id_priv); |
| } else { |