Skip to content

Commit

Permalink
RDMA/cma: Rollback source IP address if failing to acquire device
Browse files Browse the repository at this point in the history
commit 5fc01fb upstream.

If cma_acquire_dev_by_src_ip() returns error in addr_handler(), the
device state changes back to RDMA_CM_ADDR_BOUND but the resolved source
IP address is still left. After that, if rdma_destroy_id() is called
after rdma_listen(), the device is freed without removed from
listen_any_list in cma_cancel_operation(). Revert to the previous IP
address if acquiring device fails.

Reported-by: syzbot+f3ce716af730c8f96637@syzkaller.appspotmail.com
Signed-off-by: Myungho Jung <mhjungk@gmail.com>
Reviewed-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
myunghoj authored and gregkh committed Mar 27, 2019
1 parent 015b828 commit 9dd5053
Showing 1 changed file with 12 additions and 1 deletion.
13 changes: 12 additions & 1 deletion drivers/infiniband/core/cma.c
Original file line number Diff line number Diff line change
Expand Up @@ -2854,13 +2854,22 @@ static void addr_handler(int status, struct sockaddr *src_addr,
{
struct rdma_id_private *id_priv = context;
struct rdma_cm_event event = {};
struct sockaddr *addr;
struct sockaddr_storage old_addr;

mutex_lock(&id_priv->handler_mutex);
if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_QUERY,
RDMA_CM_ADDR_RESOLVED))
goto out;

memcpy(cma_src_addr(id_priv), src_addr, rdma_addr_size(src_addr));
/*
* Store the previous src address, so that if we fail to acquire
* matching rdma device, old address can be restored back, which helps
* to cancel the cma listen operation correctly.
*/
addr = cma_src_addr(id_priv);
memcpy(&old_addr, addr, rdma_addr_size(addr));
memcpy(addr, src_addr, rdma_addr_size(src_addr));
if (!status && !id_priv->cma_dev) {
status = cma_acquire_dev(id_priv, NULL);
if (status)
Expand All @@ -2871,6 +2880,8 @@ static void addr_handler(int status, struct sockaddr *src_addr,
}

if (status) {
memcpy(addr, &old_addr,
rdma_addr_size((struct sockaddr *)&old_addr));
if (!cma_comp_exch(id_priv, RDMA_CM_ADDR_RESOLVED,
RDMA_CM_ADDR_BOUND))
goto out;
Expand Down

0 comments on commit 9dd5053

Please sign in to comment.