Skip to content

Commit f0ae4af

Browse files
alaahljgunthorpe
authored andcommitted
RDMA/mlx5: Fix releasing unallocated memory in dereg MR flow
For the case of IB_MR_TYPE_DM the mr does doesn't have a umem, even though it is a user MR. This causes function mlx5_free_priv_descs() to think that it is a kernel MR, leading to wrongly accessing mr->descs that will get wrong values in the union which leads to attempt to release resources that were not allocated in the first place. For example: DMA-API: mlx5_core 0000:08:00.1: device driver tries to free DMA memory it has not allocated [device address=0x0000000000000000] [size=0 bytes] WARNING: CPU: 8 PID: 1021 at kernel/dma/debug.c:961 check_unmap+0x54f/0x8b0 RIP: 0010:check_unmap+0x54f/0x8b0 Call Trace: debug_dma_unmap_page+0x57/0x60 mlx5_free_priv_descs+0x57/0x70 [mlx5_ib] mlx5_ib_dereg_mr+0x1fb/0x3d0 [mlx5_ib] ib_dereg_mr_user+0x60/0x140 [ib_core] uverbs_destroy_uobject+0x59/0x210 [ib_uverbs] uobj_destroy+0x3f/0x80 [ib_uverbs] ib_uverbs_cmd_verbs+0x435/0xd10 [ib_uverbs] ? uverbs_finalize_object+0x50/0x50 [ib_uverbs] ? lock_acquire+0xc4/0x2e0 ? lock_acquired+0x12/0x380 ? lock_acquire+0xc4/0x2e0 ? lock_acquire+0xc4/0x2e0 ? ib_uverbs_ioctl+0x7c/0x140 [ib_uverbs] ? lock_release+0x28a/0x400 ib_uverbs_ioctl+0xc0/0x140 [ib_uverbs] ? ib_uverbs_ioctl+0x7c/0x140 [ib_uverbs] __x64_sys_ioctl+0x7f/0xb0 do_syscall_64+0x38/0x90 Fix it by reorganizing the dereg flow and mlx5_ib_mr structure: - Move the ib_umem field into the user MRs structure in the union as it's applicable only there. - Function mlx5_ib_dereg_mr() will now call mlx5_free_priv_descs() only in case there isn't udata, which indicates that this isn't a user MR. Fixes: f18ec42 ("RDMA/mlx5: Use a union inside mlx5_ib_mr") Link: https://lore.kernel.org/r/66bb1dd253c1fd7ceaa9fc411061eefa457b86fb.1637581144.git.leonro@nvidia.com Signed-off-by: Alaa Hleihel <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 84b0172 commit f0ae4af

File tree

2 files changed

+15
-17
lines changed

2 files changed

+15
-17
lines changed

drivers/infiniband/hw/mlx5/mlx5_ib.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,6 @@ struct mlx5_ib_mr {
664664

665665
/* User MR data */
666666
struct mlx5_cache_ent *cache_ent;
667-
struct ib_umem *umem;
668667

669668
/* This is zero'd when the MR is allocated */
670669
union {
@@ -676,7 +675,7 @@ struct mlx5_ib_mr {
676675
struct list_head list;
677676
};
678677

679-
/* Used only by kernel MRs (umem == NULL) */
678+
/* Used only by kernel MRs */
680679
struct {
681680
void *descs;
682681
void *descs_alloc;
@@ -697,8 +696,9 @@ struct mlx5_ib_mr {
697696
int data_length;
698697
};
699698

700-
/* Used only by User MRs (umem != NULL) */
699+
/* Used only by User MRs */
701700
struct {
701+
struct ib_umem *umem;
702702
unsigned int page_shift;
703703
/* Current access_flags */
704704
int access_flags;

drivers/infiniband/hw/mlx5/mr.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,19 +1904,18 @@ mlx5_alloc_priv_descs(struct ib_device *device,
19041904
return ret;
19051905
}
19061906

1907-
static void
1908-
mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
1907+
static void mlx5_free_priv_descs(struct mlx5_ib_mr *mr)
19091908
{
1910-
if (!mr->umem && mr->descs) {
1911-
struct ib_device *device = mr->ibmr.device;
1912-
int size = mr->max_descs * mr->desc_size;
1913-
struct mlx5_ib_dev *dev = to_mdev(device);
1909+
struct mlx5_ib_dev *dev = to_mdev(mr->ibmr.device);
1910+
int size = mr->max_descs * mr->desc_size;
19141911

1915-
dma_unmap_single(&dev->mdev->pdev->dev, mr->desc_map, size,
1916-
DMA_TO_DEVICE);
1917-
kfree(mr->descs_alloc);
1918-
mr->descs = NULL;
1919-
}
1912+
if (!mr->descs)
1913+
return;
1914+
1915+
dma_unmap_single(&dev->mdev->pdev->dev, mr->desc_map, size,
1916+
DMA_TO_DEVICE);
1917+
kfree(mr->descs_alloc);
1918+
mr->descs = NULL;
19201919
}
19211920

19221921
int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
@@ -1992,7 +1991,8 @@ int mlx5_ib_dereg_mr(struct ib_mr *ibmr, struct ib_udata *udata)
19921991
if (mr->cache_ent) {
19931992
mlx5_mr_cache_free(dev, mr);
19941993
} else {
1995-
mlx5_free_priv_descs(mr);
1994+
if (!udata)
1995+
mlx5_free_priv_descs(mr);
19961996
kfree(mr);
19971997
}
19981998
return 0;
@@ -2079,7 +2079,6 @@ static struct mlx5_ib_mr *mlx5_ib_alloc_pi_mr(struct ib_pd *pd,
20792079
if (err)
20802080
goto err_free_in;
20812081

2082-
mr->umem = NULL;
20832082
kfree(in);
20842083

20852084
return mr;
@@ -2206,7 +2205,6 @@ static struct ib_mr *__mlx5_ib_alloc_mr(struct ib_pd *pd,
22062205
}
22072206

22082207
mr->ibmr.device = pd->device;
2209-
mr->umem = NULL;
22102208

22112209
switch (mr_type) {
22122210
case IB_MR_TYPE_MEM_REG:

0 commit comments

Comments
 (0)