[PATCH rdma-next 3/7] RDMA/mlx5: Avoid use after free in allocate MEMIC bad flow
From: Leon Romanovsky <leon@kernel.org>
Date: 2021-03-18 11:16:43
Also in:
linux-rdma
Subsystem:
infiniband subsystem, mellanox mlx5 ib driver, the rest · Maintainers:
Jason Gunthorpe, Leon Romanovsky, Linus Torvalds
From: Maor Gottlieb <redacted>
When driver fails to copy the MEMIC address to the user, we
call to rdma_user_mmap_entry_remove on the mmap entry. Since in this
state the refcount of the mmap entry is decreased to zero, mmap_free
is triggered and release the dm object. Therefore we need to avoid
the explicit call to free the dm.
Fixes: dc2316eba73f ("IB/mlx5: Fix device memory flows")
Signed-off-by: Maor Gottlieb <redacted>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
---
drivers/infiniband/hw/mlx5/main.c | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index 5226664f1bda..d652af720036 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c@@ -2375,13 +2375,18 @@ static int handle_alloc_dm_memic(struct ib_ucontext *ctx, err = mlx5_cmd_alloc_memic(dm_db, &dm->dev_addr, dm->size, attr->alignment); - if (err) + if (err) { + kfree(dm); return err; + } address = dm->dev_addr & PAGE_MASK; err = add_dm_mmap_entry(ctx, dm, address); - if (err) - goto err_dealloc; + if (err) { + mlx5_cmd_dealloc_memic(dm_db, dm->dev_addr, dm->size); + kfree(dm); + return err; + } page_idx = dm->mentry.rdma_entry.start_pgoff & 0xFFFF; err = uverbs_copy_to(attrs,
@@ -2402,8 +2407,6 @@ static int handle_alloc_dm_memic(struct ib_ucontext *ctx, err_copy: rdma_user_mmap_entry_remove(&dm->mentry.rdma_entry); -err_dealloc: - mlx5_cmd_dealloc_memic(dm_db, dm->dev_addr, dm->size); return err; }
@@ -2472,9 +2475,7 @@ struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev, switch (type) { case MLX5_IB_UAPI_DM_TYPE_MEMIC: - err = handle_alloc_dm_memic(context, dm, - attr, - attrs); + err = handle_alloc_dm_memic(context, dm, attr, attrs); break; case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM: err = handle_alloc_dm_sw_icm(context, dm,
@@ -2496,7 +2497,9 @@ struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev, return &dm->ibdm; err_free: - kfree(dm); + /* In MEMIC error flow, dm will be freed internally */ + if (type != MLX5_IB_UAPI_DM_TYPE_MEMIC) + kfree(dm); return ERR_PTR(err); } --
2.30.2