diff options
author | Majd Dibbiny <majd@mellanox.com> | 2017-12-24 06:54:56 -0500 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2017-12-27 17:24:40 -0500 |
commit | ad9a3668a434faca1339789ed2f043d679199309 (patch) | |
tree | 6ae4f8fc84efe4a0db5750a696c24bc06dddbb09 | |
parent | 4c009af473b2026caaa26107e34d7cc68dad7756 (diff) |
IB/mlx5: Serialize access to the VMA list
User-space applications can do mmap and munmap directly at
any time.
Since the VMA list is not protected with a mutex, concurrent
accesses to the VMA list from the mmap and munmap can cause
data corruption. Add a mutex around the list.
Cc: <stable@vger.kernel.org> # v4.7
Fixes: 7c2344c3bbf9 ("IB/mlx5: Implements disassociate_ucontext API")
Reviewed-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Majd Dibbiny <majd@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r-- | drivers/infiniband/hw/mlx5/main.c | 8 | ||||
-rw-r--r-- | drivers/infiniband/hw/mlx5/mlx5_ib.h | 4 |
2 files changed, 12 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index b4ef4d9b6ce5..8ac50de2b242 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c | |||
@@ -1463,6 +1463,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, | |||
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | INIT_LIST_HEAD(&context->vma_private_list); | 1465 | INIT_LIST_HEAD(&context->vma_private_list); |
1466 | mutex_init(&context->vma_private_list_mutex); | ||
1466 | INIT_LIST_HEAD(&context->db_page_list); | 1467 | INIT_LIST_HEAD(&context->db_page_list); |
1467 | mutex_init(&context->db_page_mutex); | 1468 | mutex_init(&context->db_page_mutex); |
1468 | 1469 | ||
@@ -1624,7 +1625,9 @@ static void mlx5_ib_vma_close(struct vm_area_struct *area) | |||
1624 | * mlx5_ib_disassociate_ucontext(). | 1625 | * mlx5_ib_disassociate_ucontext(). |
1625 | */ | 1626 | */ |
1626 | mlx5_ib_vma_priv_data->vma = NULL; | 1627 | mlx5_ib_vma_priv_data->vma = NULL; |
1628 | mutex_lock(mlx5_ib_vma_priv_data->vma_private_list_mutex); | ||
1627 | list_del(&mlx5_ib_vma_priv_data->list); | 1629 | list_del(&mlx5_ib_vma_priv_data->list); |
1630 | mutex_unlock(mlx5_ib_vma_priv_data->vma_private_list_mutex); | ||
1628 | kfree(mlx5_ib_vma_priv_data); | 1631 | kfree(mlx5_ib_vma_priv_data); |
1629 | } | 1632 | } |
1630 | 1633 | ||
@@ -1644,10 +1647,13 @@ static int mlx5_ib_set_vma_data(struct vm_area_struct *vma, | |||
1644 | return -ENOMEM; | 1647 | return -ENOMEM; |
1645 | 1648 | ||
1646 | vma_prv->vma = vma; | 1649 | vma_prv->vma = vma; |
1650 | vma_prv->vma_private_list_mutex = &ctx->vma_private_list_mutex; | ||
1647 | vma->vm_private_data = vma_prv; | 1651 | vma->vm_private_data = vma_prv; |
1648 | vma->vm_ops = &mlx5_ib_vm_ops; | 1652 | vma->vm_ops = &mlx5_ib_vm_ops; |
1649 | 1653 | ||
1654 | mutex_lock(&ctx->vma_private_list_mutex); | ||
1650 | list_add(&vma_prv->list, vma_head); | 1655 | list_add(&vma_prv->list, vma_head); |
1656 | mutex_unlock(&ctx->vma_private_list_mutex); | ||
1651 | 1657 | ||
1652 | return 0; | 1658 | return 0; |
1653 | } | 1659 | } |
@@ -1690,6 +1696,7 @@ static void mlx5_ib_disassociate_ucontext(struct ib_ucontext *ibcontext) | |||
1690 | * mlx5_ib_vma_close. | 1696 | * mlx5_ib_vma_close. |
1691 | */ | 1697 | */ |
1692 | down_write(&owning_mm->mmap_sem); | 1698 | down_write(&owning_mm->mmap_sem); |
1699 | mutex_lock(&context->vma_private_list_mutex); | ||
1693 | list_for_each_entry_safe(vma_private, n, &context->vma_private_list, | 1700 | list_for_each_entry_safe(vma_private, n, &context->vma_private_list, |
1694 | list) { | 1701 | list) { |
1695 | vma = vma_private->vma; | 1702 | vma = vma_private->vma; |
@@ -1704,6 +1711,7 @@ static void mlx5_ib_disassociate_ucontext(struct ib_ucontext *ibcontext) | |||
1704 | list_del(&vma_private->list); | 1711 | list_del(&vma_private->list); |
1705 | kfree(vma_private); | 1712 | kfree(vma_private); |
1706 | } | 1713 | } |
1714 | mutex_unlock(&context->vma_private_list_mutex); | ||
1707 | up_write(&owning_mm->mmap_sem); | 1715 | up_write(&owning_mm->mmap_sem); |
1708 | mmput(owning_mm); | 1716 | mmput(owning_mm); |
1709 | put_task_struct(owning_process); | 1717 | put_task_struct(owning_process); |
diff --git a/drivers/infiniband/hw/mlx5/mlx5_ib.h b/drivers/infiniband/hw/mlx5/mlx5_ib.h index 6dd8cac78de2..2c5f3533bbc9 100644 --- a/drivers/infiniband/hw/mlx5/mlx5_ib.h +++ b/drivers/infiniband/hw/mlx5/mlx5_ib.h | |||
@@ -115,6 +115,8 @@ enum { | |||
115 | struct mlx5_ib_vma_private_data { | 115 | struct mlx5_ib_vma_private_data { |
116 | struct list_head list; | 116 | struct list_head list; |
117 | struct vm_area_struct *vma; | 117 | struct vm_area_struct *vma; |
118 | /* protect vma_private_list add/del */ | ||
119 | struct mutex *vma_private_list_mutex; | ||
118 | }; | 120 | }; |
119 | 121 | ||
120 | struct mlx5_ib_ucontext { | 122 | struct mlx5_ib_ucontext { |
@@ -129,6 +131,8 @@ struct mlx5_ib_ucontext { | |||
129 | /* Transport Domain number */ | 131 | /* Transport Domain number */ |
130 | u32 tdn; | 132 | u32 tdn; |
131 | struct list_head vma_private_list; | 133 | struct list_head vma_private_list; |
134 | /* protect vma_private_list add/del */ | ||
135 | struct mutex vma_private_list_mutex; | ||
132 | 136 | ||
133 | unsigned long upd_xlt_page; | 137 | unsigned long upd_xlt_page; |
134 | /* protect ODP/KSM */ | 138 | /* protect ODP/KSM */ |