diff options
author | Parav Pandit <parav@mellanox.com> | 2018-08-30 01:35:19 -0400 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2018-09-06 15:01:59 -0400 |
commit | 954a8e3aea87e896e320cf648c1a5bbe47de443e (patch) | |
tree | fe1fb0ea23827207ef93717c4f572a7386781cc5 | |
parent | 08e74be103051861eb2c1ee52a2dcf119cde264f (diff) |
RDMA/cma: Protect cma dev list with lock
When AF_IB addresses are used during rdma_resolve_addr() a lock is not
held. A cma device can get removed while list traversal is in progress
which may lead to crash. ie
CPU0 CPU1
==== ====
rdma_resolve_addr()
cma_resolve_ib_dev()
list_for_each() cma_remove_one()
cur_dev->device mutex_lock(&lock)
list_del();
mutex_unlock(&lock);
cma_process_remove();
Therefore, hold a lock while traversing the list which avoids such
situation.
Cc: <stable@vger.kernel.org> # 3.10
Fixes: f17df3b0dede ("RDMA/cma: Add support for AF_IB to rdma_resolve_addr()")
Signed-off-by: Parav Pandit <parav@mellanox.com>
Reviewed-by: Daniel Jurgens <danielj@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r-- | drivers/infiniband/core/cma.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index f72677291b69..a36c94930c31 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c | |||
@@ -724,6 +724,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) | |||
724 | dgid = (union ib_gid *) &addr->sib_addr; | 724 | dgid = (union ib_gid *) &addr->sib_addr; |
725 | pkey = ntohs(addr->sib_pkey); | 725 | pkey = ntohs(addr->sib_pkey); |
726 | 726 | ||
727 | mutex_lock(&lock); | ||
727 | list_for_each_entry(cur_dev, &dev_list, list) { | 728 | list_for_each_entry(cur_dev, &dev_list, list) { |
728 | for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) { | 729 | for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) { |
729 | if (!rdma_cap_af_ib(cur_dev->device, p)) | 730 | if (!rdma_cap_af_ib(cur_dev->device, p)) |
@@ -750,18 +751,19 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv) | |||
750 | cma_dev = cur_dev; | 751 | cma_dev = cur_dev; |
751 | sgid = gid; | 752 | sgid = gid; |
752 | id_priv->id.port_num = p; | 753 | id_priv->id.port_num = p; |
754 | goto found; | ||
753 | } | 755 | } |
754 | } | 756 | } |
755 | } | 757 | } |
756 | } | 758 | } |
757 | 759 | mutex_unlock(&lock); | |
758 | if (!cma_dev) | 760 | return -ENODEV; |
759 | return -ENODEV; | ||
760 | 761 | ||
761 | found: | 762 | found: |
762 | cma_attach_to_dev(id_priv, cma_dev); | 763 | cma_attach_to_dev(id_priv, cma_dev); |
763 | addr = (struct sockaddr_ib *) cma_src_addr(id_priv); | 764 | mutex_unlock(&lock); |
764 | memcpy(&addr->sib_addr, &sgid, sizeof sgid); | 765 | addr = (struct sockaddr_ib *)cma_src_addr(id_priv); |
766 | memcpy(&addr->sib_addr, &sgid, sizeof(sgid)); | ||
765 | cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr); | 767 | cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr); |
766 | return 0; | 768 | return 0; |
767 | } | 769 | } |