Skip to content

Commit 303851e

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma
Pull rdma fixes from Jason Gunthorpe: "Not much exciting here, almost entirely syzkaller fixes. This is going to be on ongoing theme for some time, I think. Both Google and Mellanox are now running syzkaller on different parts of the user API. Summary: - Many bug fixes related to syzkaller from Leon Romanovsky. These are still for the mlx driver and ucma interface. - Fix a situation with port reuse for iWarp, discovered during scale-up testing - Bug fixes for the profile and restrack patches accepted during this merge window - Compile warning cleanups from Arnd, this is apparently the last warning to make 32 bit builds quiet" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: RDMA/ucma: Ensure that CM_ID exists prior to access it RDMA/verbs: Remove restrack entry from XRCD structure RDMA/ucma: Fix use-after-free access in ucma_close RDMA/ucma: Check AF family prior resolving address infiniband: bnxt_re: use BIT_ULL() for 64-bit bit masks infiniband: qplib_fp: fix pointer cast IB/mlx5: Fix cleanup order on unload RDMA/ucma: Don't allow join attempts for unsupported AF family RDMA/ucma: Fix access to non-initialized CM_ID object RDMA/core: Do not use invalid destination in determining port reuse RDMA/mlx5: Fix crash while accessing garbage pointer and freed memory IB/mlx5: Fix integer overflows in mlx5_ib_create_srq IB/mlx5: Fix out-of-bounds read in create_raw_packet_qp_rq
2 parents 76c0b6a + e8980d6 commit 303851e

File tree

12 files changed

+90
-53
lines changed

12 files changed

+90
-53
lines changed

drivers/infiniband/core/cma.c

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3069,7 +3069,8 @@ static int cma_port_is_unique(struct rdma_bind_list *bind_list,
30693069
continue;
30703070

30713071
/* different dest port -> unique */
3072-
if (!cma_any_port(cur_daddr) &&
3072+
if (!cma_any_port(daddr) &&
3073+
!cma_any_port(cur_daddr) &&
30733074
(dport != cur_dport))
30743075
continue;
30753076

@@ -3080,7 +3081,8 @@ static int cma_port_is_unique(struct rdma_bind_list *bind_list,
30803081
continue;
30813082

30823083
/* different dst address -> unique */
3083-
if (!cma_any_addr(cur_daddr) &&
3084+
if (!cma_any_addr(daddr) &&
3085+
!cma_any_addr(cur_daddr) &&
30843086
cma_addr_cmp(daddr, cur_daddr))
30853087
continue;
30863088

@@ -3378,13 +3380,13 @@ int rdma_bind_addr(struct rdma_cm_id *id, struct sockaddr *addr)
33783380
}
33793381
#endif
33803382
}
3383+
daddr = cma_dst_addr(id_priv);
3384+
daddr->sa_family = addr->sa_family;
3385+
33813386
ret = cma_get_port(id_priv);
33823387
if (ret)
33833388
goto err2;
33843389

3385-
daddr = cma_dst_addr(id_priv);
3386-
daddr->sa_family = addr->sa_family;
3387-
33883390
return 0;
33893391
err2:
33903392
if (id_priv->cma_dev)
@@ -4173,6 +4175,9 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
41734175
struct cma_multicast *mc;
41744176
int ret;
41754177

4178+
if (!id->device)
4179+
return -EINVAL;
4180+
41764181
id_priv = container_of(id, struct rdma_id_private, id);
41774182
if (!cma_comp(id_priv, RDMA_CM_ADDR_BOUND) &&
41784183
!cma_comp(id_priv, RDMA_CM_ADDR_RESOLVED))

drivers/infiniband/core/ucma.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ static inline struct ucma_context *_ucma_find_context(int id,
132132
ctx = idr_find(&ctx_idr, id);
133133
if (!ctx)
134134
ctx = ERR_PTR(-ENOENT);
135-
else if (ctx->file != file)
135+
else if (ctx->file != file || !ctx->cm_id)
136136
ctx = ERR_PTR(-EINVAL);
137137
return ctx;
138138
}
@@ -456,6 +456,7 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
456456
struct rdma_ucm_create_id cmd;
457457
struct rdma_ucm_create_id_resp resp;
458458
struct ucma_context *ctx;
459+
struct rdma_cm_id *cm_id;
459460
enum ib_qp_type qp_type;
460461
int ret;
461462

@@ -476,10 +477,10 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
476477
return -ENOMEM;
477478

478479
ctx->uid = cmd.uid;
479-
ctx->cm_id = rdma_create_id(current->nsproxy->net_ns,
480-
ucma_event_handler, ctx, cmd.ps, qp_type);
481-
if (IS_ERR(ctx->cm_id)) {
482-
ret = PTR_ERR(ctx->cm_id);
480+
cm_id = rdma_create_id(current->nsproxy->net_ns,
481+
ucma_event_handler, ctx, cmd.ps, qp_type);
482+
if (IS_ERR(cm_id)) {
483+
ret = PTR_ERR(cm_id);
483484
goto err1;
484485
}
485486

@@ -489,14 +490,19 @@ static ssize_t ucma_create_id(struct ucma_file *file, const char __user *inbuf,
489490
ret = -EFAULT;
490491
goto err2;
491492
}
493+
494+
ctx->cm_id = cm_id;
492495
return 0;
493496

494497
err2:
495-
rdma_destroy_id(ctx->cm_id);
498+
rdma_destroy_id(cm_id);
496499
err1:
497500
mutex_lock(&mut);
498501
idr_remove(&ctx_idr, ctx->id);
499502
mutex_unlock(&mut);
503+
mutex_lock(&file->mut);
504+
list_del(&ctx->list);
505+
mutex_unlock(&file->mut);
500506
kfree(ctx);
501507
return ret;
502508
}
@@ -664,19 +670,23 @@ static ssize_t ucma_resolve_ip(struct ucma_file *file,
664670
int in_len, int out_len)
665671
{
666672
struct rdma_ucm_resolve_ip cmd;
673+
struct sockaddr *src, *dst;
667674
struct ucma_context *ctx;
668675
int ret;
669676

670677
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
671678
return -EFAULT;
672679

680+
src = (struct sockaddr *) &cmd.src_addr;
681+
dst = (struct sockaddr *) &cmd.dst_addr;
682+
if (!rdma_addr_size(src) || !rdma_addr_size(dst))
683+
return -EINVAL;
684+
673685
ctx = ucma_get_ctx(file, cmd.id);
674686
if (IS_ERR(ctx))
675687
return PTR_ERR(ctx);
676688

677-
ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
678-
(struct sockaddr *) &cmd.dst_addr,
679-
cmd.timeout_ms);
689+
ret = rdma_resolve_addr(ctx->cm_id, src, dst, cmd.timeout_ms);
680690
ucma_put_ctx(ctx);
681691
return ret;
682692
}
@@ -1349,7 +1359,7 @@ static ssize_t ucma_process_join(struct ucma_file *file,
13491359
return -ENOSPC;
13501360

13511361
addr = (struct sockaddr *) &cmd->addr;
1352-
if (!cmd->addr_size || (cmd->addr_size != rdma_addr_size(addr)))
1362+
if (cmd->addr_size != rdma_addr_size(addr))
13531363
return -EINVAL;
13541364

13551365
if (cmd->join_flags == RDMA_MC_JOIN_FLAG_FULLMEMBER)
@@ -1417,6 +1427,9 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
14171427
join_cmd.uid = cmd.uid;
14181428
join_cmd.id = cmd.id;
14191429
join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr);
1430+
if (!join_cmd.addr_size)
1431+
return -EINVAL;
1432+
14201433
join_cmd.join_flags = RDMA_MC_JOIN_FLAG_FULLMEMBER;
14211434
memcpy(&join_cmd.addr, &cmd.addr, join_cmd.addr_size);
14221435

@@ -1432,6 +1445,9 @@ static ssize_t ucma_join_multicast(struct ucma_file *file,
14321445
if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
14331446
return -EFAULT;
14341447

1448+
if (!rdma_addr_size((struct sockaddr *)&cmd.addr))
1449+
return -EINVAL;
1450+
14351451
return ucma_process_join(file, &cmd, out_len);
14361452
}
14371453

drivers/infiniband/hw/bnxt_re/bnxt_re.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
#define BNXT_RE_PAGE_SIZE_8M BIT(BNXT_RE_PAGE_SHIFT_8M)
5858
#define BNXT_RE_PAGE_SIZE_1G BIT(BNXT_RE_PAGE_SHIFT_1G)
5959

60-
#define BNXT_RE_MAX_MR_SIZE_LOW BIT(BNXT_RE_PAGE_SHIFT_1G)
61-
#define BNXT_RE_MAX_MR_SIZE_HIGH BIT(39)
60+
#define BNXT_RE_MAX_MR_SIZE_LOW BIT_ULL(BNXT_RE_PAGE_SHIFT_1G)
61+
#define BNXT_RE_MAX_MR_SIZE_HIGH BIT_ULL(39)
6262
#define BNXT_RE_MAX_MR_SIZE BNXT_RE_MAX_MR_SIZE_HIGH
6363

6464
#define BNXT_RE_MAX_QPC_COUNT (64 * 1024)

drivers/infiniband/hw/bnxt_re/ib_verbs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3598,7 +3598,7 @@ struct ib_mr *bnxt_re_reg_user_mr(struct ib_pd *ib_pd, u64 start, u64 length,
35983598
int umem_pgs, page_shift, rc;
35993599

36003600
if (length > BNXT_RE_MAX_MR_SIZE) {
3601-
dev_err(rdev_to_dev(rdev), "MR Size: %lld > Max supported:%ld\n",
3601+
dev_err(rdev_to_dev(rdev), "MR Size: %lld > Max supported:%lld\n",
36023602
length, BNXT_RE_MAX_MR_SIZE);
36033603
return ERR_PTR(-ENOMEM);
36043604
}

drivers/infiniband/hw/bnxt_re/qplib_fp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ static void bnxt_qplib_service_nq(unsigned long data)
243243
u32 sw_cons, raw_cons;
244244
u16 type;
245245
int budget = nq->budget;
246-
u64 q_handle;
246+
uintptr_t q_handle;
247247

248248
/* Service the NQ until empty */
249249
raw_cons = hwq->cons;
@@ -526,7 +526,7 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
526526

527527
/* Configure the request */
528528
req.dpi = cpu_to_le32(srq->dpi->dpi);
529-
req.srq_handle = cpu_to_le64(srq);
529+
req.srq_handle = cpu_to_le64((uintptr_t)srq);
530530

531531
req.srq_size = cpu_to_le16((u16)srq->hwq.max_elements);
532532
pbl = &srq->hwq.pbl[PBL_LVL_0];

drivers/infiniband/hw/mlx5/main.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4860,19 +4860,19 @@ static int mlx5_ib_stage_ib_reg_init(struct mlx5_ib_dev *dev)
48604860
return ib_register_device(&dev->ib_dev, NULL);
48614861
}
48624862

4863-
static void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)
4863+
static void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev)
48644864
{
4865-
ib_unregister_device(&dev->ib_dev);
4865+
destroy_umrc_res(dev);
48664866
}
48674867

4868-
static int mlx5_ib_stage_umr_res_init(struct mlx5_ib_dev *dev)
4868+
static void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)
48694869
{
4870-
return create_umr_res(dev);
4870+
ib_unregister_device(&dev->ib_dev);
48714871
}
48724872

4873-
static void mlx5_ib_stage_umr_res_cleanup(struct mlx5_ib_dev *dev)
4873+
static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
48744874
{
4875-
destroy_umrc_res(dev);
4875+
return create_umr_res(dev);
48764876
}
48774877

48784878
static int mlx5_ib_stage_delay_drop_init(struct mlx5_ib_dev *dev)
@@ -4982,12 +4982,15 @@ static const struct mlx5_ib_profile pf_profile = {
49824982
STAGE_CREATE(MLX5_IB_STAGE_BFREG,
49834983
mlx5_ib_stage_bfrag_init,
49844984
mlx5_ib_stage_bfrag_cleanup),
4985+
STAGE_CREATE(MLX5_IB_STAGE_PRE_IB_REG_UMR,
4986+
NULL,
4987+
mlx5_ib_stage_pre_ib_reg_umr_cleanup),
49854988
STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
49864989
mlx5_ib_stage_ib_reg_init,
49874990
mlx5_ib_stage_ib_reg_cleanup),
4988-
STAGE_CREATE(MLX5_IB_STAGE_UMR_RESOURCES,
4989-
mlx5_ib_stage_umr_res_init,
4990-
mlx5_ib_stage_umr_res_cleanup),
4991+
STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
4992+
mlx5_ib_stage_post_ib_reg_umr_init,
4993+
NULL),
49914994
STAGE_CREATE(MLX5_IB_STAGE_DELAY_DROP,
49924995
mlx5_ib_stage_delay_drop_init,
49934996
mlx5_ib_stage_delay_drop_cleanup),

drivers/infiniband/hw/mlx5/mlx5_ib.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,8 +739,9 @@ enum mlx5_ib_stages {
739739
MLX5_IB_STAGE_CONG_DEBUGFS,
740740
MLX5_IB_STAGE_UAR,
741741
MLX5_IB_STAGE_BFREG,
742+
MLX5_IB_STAGE_PRE_IB_REG_UMR,
742743
MLX5_IB_STAGE_IB_REG,
743-
MLX5_IB_STAGE_UMR_RESOURCES,
744+
MLX5_IB_STAGE_POST_IB_REG_UMR,
744745
MLX5_IB_STAGE_DELAY_DROP,
745746
MLX5_IB_STAGE_CLASS_ATTR,
746747
MLX5_IB_STAGE_MAX,

drivers/infiniband/hw/mlx5/mr.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,8 @@ static int mr_umem_get(struct ib_pd *pd, u64 start, u64 length,
838838
*umem = ib_umem_get(pd->uobject->context, start, length,
839839
access_flags, 0);
840840
err = PTR_ERR_OR_ZERO(*umem);
841-
if (err < 0) {
841+
if (err) {
842+
*umem = NULL;
842843
mlx5_ib_err(dev, "umem get failed (%d)\n", err);
843844
return err;
844845
}
@@ -1415,6 +1416,7 @@ int mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,
14151416
if (err) {
14161417
mlx5_ib_warn(dev, "Failed to rereg UMR\n");
14171418
ib_umem_release(mr->umem);
1419+
mr->umem = NULL;
14181420
clean_mr(dev, mr);
14191421
return err;
14201422
}
@@ -1498,14 +1500,11 @@ static int clean_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
14981500
u32 key = mr->mmkey.key;
14991501

15001502
err = destroy_mkey(dev, mr);
1501-
kfree(mr);
15021503
if (err) {
15031504
mlx5_ib_warn(dev, "failed to destroy mkey 0x%x (%d)\n",
15041505
key, err);
15051506
return err;
15061507
}
1507-
} else {
1508-
mlx5_mr_cache_free(dev, mr);
15091508
}
15101509

15111510
return 0;
@@ -1548,6 +1547,11 @@ static int dereg_mr(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
15481547
atomic_sub(npages, &dev->mdev->priv.reg_pages);
15491548
}
15501549

1550+
if (!mr->allocated_from_cache)
1551+
kfree(mr);
1552+
else
1553+
mlx5_mr_cache_free(dev, mr);
1554+
15511555
return 0;
15521556
}
15531557

drivers/infiniband/hw/mlx5/qp.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,7 @@ static void destroy_raw_packet_qp_sq(struct mlx5_ib_dev *dev,
11611161
ib_umem_release(sq->ubuffer.umem);
11621162
}
11631163

1164-
static int get_rq_pas_size(void *qpc)
1164+
static size_t get_rq_pas_size(void *qpc)
11651165
{
11661166
u32 log_page_size = MLX5_GET(qpc, qpc, log_page_size) + 12;
11671167
u32 log_rq_stride = MLX5_GET(qpc, qpc, log_rq_stride);
@@ -1177,7 +1177,8 @@ static int get_rq_pas_size(void *qpc)
11771177
}
11781178

11791179
static int create_raw_packet_qp_rq(struct mlx5_ib_dev *dev,
1180-
struct mlx5_ib_rq *rq, void *qpin)
1180+
struct mlx5_ib_rq *rq, void *qpin,
1181+
size_t qpinlen)
11811182
{
11821183
struct mlx5_ib_qp *mqp = rq->base.container_mibqp;
11831184
__be64 *pas;
@@ -1186,9 +1187,12 @@ static int create_raw_packet_qp_rq(struct mlx5_ib_dev *dev,
11861187
void *rqc;
11871188
void *wq;
11881189
void *qpc = MLX5_ADDR_OF(create_qp_in, qpin, qpc);
1189-
int inlen;
1190+
size_t rq_pas_size = get_rq_pas_size(qpc);
1191+
size_t inlen;
11901192
int err;
1191-
u32 rq_pas_size = get_rq_pas_size(qpc);
1193+
1194+
if (qpinlen < rq_pas_size + MLX5_BYTE_OFF(create_qp_in, pas))
1195+
return -EINVAL;
11921196

11931197
inlen = MLX5_ST_SZ_BYTES(create_rq_in) + rq_pas_size;
11941198
in = kvzalloc(inlen, GFP_KERNEL);
@@ -1277,7 +1281,7 @@ static void destroy_raw_packet_qp_tir(struct mlx5_ib_dev *dev,
12771281
}
12781282

12791283
static int create_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
1280-
u32 *in,
1284+
u32 *in, size_t inlen,
12811285
struct ib_pd *pd)
12821286
{
12831287
struct mlx5_ib_raw_packet_qp *raw_packet_qp = &qp->raw_packet_qp;
@@ -1309,7 +1313,7 @@ static int create_raw_packet_qp(struct mlx5_ib_dev *dev, struct mlx5_ib_qp *qp,
13091313
rq->flags |= MLX5_IB_RQ_CVLAN_STRIPPING;
13101314
if (qp->flags & MLX5_IB_QP_PCI_WRITE_END_PADDING)
13111315
rq->flags |= MLX5_IB_RQ_PCI_WRITE_END_PADDING;
1312-
err = create_raw_packet_qp_rq(dev, rq, in);
1316+
err = create_raw_packet_qp_rq(dev, rq, in, inlen);
13131317
if (err)
13141318
goto err_destroy_sq;
13151319

@@ -1872,11 +1876,16 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
18721876
}
18731877
}
18741878

1879+
if (inlen < 0) {
1880+
err = -EINVAL;
1881+
goto err;
1882+
}
1883+
18751884
if (init_attr->qp_type == IB_QPT_RAW_PACKET ||
18761885
qp->flags & MLX5_IB_QP_UNDERLAY) {
18771886
qp->raw_packet_qp.sq.ubuffer.buf_addr = ucmd.sq_buf_addr;
18781887
raw_packet_qp_copy_info(qp, &qp->raw_packet_qp);
1879-
err = create_raw_packet_qp(dev, qp, in, pd);
1888+
err = create_raw_packet_qp(dev, qp, in, inlen, pd);
18801889
} else {
18811890
err = mlx5_core_create_qp(dev->mdev, &base->mqp, in, inlen);
18821891
}

drivers/infiniband/hw/mlx5/srq.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,8 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
241241
{
242242
struct mlx5_ib_dev *dev = to_mdev(pd->device);
243243
struct mlx5_ib_srq *srq;
244-
int desc_size;
245-
int buf_size;
244+
size_t desc_size;
245+
size_t buf_size;
246246
int err;
247247
struct mlx5_srq_attr in = {0};
248248
__u32 max_srq_wqes = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz);
@@ -266,15 +266,18 @@ struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd,
266266

267267
desc_size = sizeof(struct mlx5_wqe_srq_next_seg) +
268268
srq->msrq.max_gs * sizeof(struct mlx5_wqe_data_seg);
269+
if (desc_size == 0 || srq->msrq.max_gs > desc_size)
270+
return ERR_PTR(-EINVAL);
269271
desc_size = roundup_pow_of_two(desc_size);
270-
desc_size = max_t(int, 32, desc_size);
272+
desc_size = max_t(size_t, 32, desc_size);
273+
if (desc_size < sizeof(struct mlx5_wqe_srq_next_seg))
274+
return ERR_PTR(-EINVAL);
271275
srq->msrq.max_avail_gather = (desc_size - sizeof(struct mlx5_wqe_srq_next_seg)) /
272276
sizeof(struct mlx5_wqe_data_seg);
273277
srq->msrq.wqe_shift = ilog2(desc_size);
274278
buf_size = srq->msrq.max * desc_size;
275-
mlx5_ib_dbg(dev, "desc_size 0x%x, req wr 0x%x, srq size 0x%x, max_gs 0x%x, max_avail_gather 0x%x\n",
276-
desc_size, init_attr->attr.max_wr, srq->msrq.max, srq->msrq.max_gs,
277-
srq->msrq.max_avail_gather);
279+
if (buf_size < desc_size)
280+
return ERR_PTR(-EINVAL);
278281
in.type = init_attr->srq_type;
279282

280283
if (pd->uobject)

0 commit comments

Comments
 (0)