Skip to content

Commit edb98d1

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: "A couple of regressions were found in rc1, as well as another set of races and bugs: - A regression where RDMA_CM_EVENT_REJECTED was lost in some cases - Bad error handling in the CM, uverbs, rvt, siw and i40iw - Kernel stack memory leak to user space in mlx4 - Missing data in a uapi query for mlx5 - Three races found by syzkaller in the ib core code" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: RDMA/core: Fix race between destroy and release FD object IB/rdmavt: Always return ERR_PTR from rvt_create_mmap_info() RDMA/core: Fix overwriting of uobj in case of error RDMA/core: Prevent mixed use of FDs between shared ufiles RDMA/uverbs: Fix a race with disassociate and exit_mmap() RDMA/mlx5: Set GRH fields in query QP on RoCE RDMA/siw: Fix potential siw_mem refcnt leak in siw_fastreg_mr() RDMA/mlx4: Initialize ib_spec on the stack RDMA/cm: Fix an error check in cm_alloc_id_priv() RDMA/cm: Fix missing RDMA_CM_EVENT_REJECTED event after receiving REJ message i40iw: fix null pointer dereference on a null wqe pointer
2 parents 3f777e1 + f0abc76 commit edb98d1

File tree

11 files changed

+47
-32
lines changed

11 files changed

+47
-32
lines changed

drivers/infiniband/core/cm.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -862,7 +862,7 @@ static struct cm_id_private *cm_alloc_id_priv(struct ib_device *device,
862862

863863
ret = xa_alloc_cyclic_irq(&cm.local_id_table, &id, NULL, xa_limit_32b,
864864
&cm.local_id_next, GFP_KERNEL);
865-
if (ret)
865+
if (ret < 0)
866866
goto error;
867867
cm_id_priv->id.local_id = (__force __be32)id ^ cm.random_id_operand;
868868

@@ -1828,19 +1828,17 @@ static void cm_format_mra(struct cm_mra_msg *mra_msg,
18281828

18291829
static void cm_format_rej(struct cm_rej_msg *rej_msg,
18301830
struct cm_id_private *cm_id_priv,
1831-
enum ib_cm_rej_reason reason,
1832-
void *ari,
1833-
u8 ari_length,
1834-
const void *private_data,
1835-
u8 private_data_len)
1831+
enum ib_cm_rej_reason reason, void *ari,
1832+
u8 ari_length, const void *private_data,
1833+
u8 private_data_len, enum ib_cm_state state)
18361834
{
18371835
lockdep_assert_held(&cm_id_priv->lock);
18381836

18391837
cm_format_mad_hdr(&rej_msg->hdr, CM_REJ_ATTR_ID, cm_id_priv->tid);
18401838
IBA_SET(CM_REJ_REMOTE_COMM_ID, rej_msg,
18411839
be32_to_cpu(cm_id_priv->id.remote_id));
18421840

1843-
switch(cm_id_priv->id.state) {
1841+
switch (state) {
18441842
case IB_CM_REQ_RCVD:
18451843
IBA_SET(CM_REJ_LOCAL_COMM_ID, rej_msg, be32_to_cpu(0));
18461844
IBA_SET(CM_REJ_MESSAGE_REJECTED, rej_msg, CM_MSG_RESPONSE_REQ);
@@ -1905,8 +1903,9 @@ static void cm_dup_req_handler(struct cm_work *work,
19051903
cm_id_priv->private_data_len);
19061904
break;
19071905
case IB_CM_TIMEWAIT:
1908-
cm_format_rej((struct cm_rej_msg *) msg->mad, cm_id_priv,
1909-
IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0);
1906+
cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv,
1907+
IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0,
1908+
IB_CM_TIMEWAIT);
19101909
break;
19111910
default:
19121911
goto unlock;
@@ -2904,6 +2903,7 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
29042903
u8 ari_length, const void *private_data,
29052904
u8 private_data_len)
29062905
{
2906+
enum ib_cm_state state = cm_id_priv->id.state;
29072907
struct ib_mad_send_buf *msg;
29082908
int ret;
29092909

@@ -2913,7 +2913,7 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
29132913
(ari && ari_length > IB_CM_REJ_ARI_LENGTH))
29142914
return -EINVAL;
29152915

2916-
switch (cm_id_priv->id.state) {
2916+
switch (state) {
29172917
case IB_CM_REQ_SENT:
29182918
case IB_CM_MRA_REQ_RCVD:
29192919
case IB_CM_REQ_RCVD:
@@ -2925,7 +2925,8 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
29252925
if (ret)
29262926
return ret;
29272927
cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
2928-
ari, ari_length, private_data, private_data_len);
2928+
ari, ari_length, private_data, private_data_len,
2929+
state);
29292930
break;
29302931
case IB_CM_REP_SENT:
29312932
case IB_CM_MRA_REP_RCVD:
@@ -2934,7 +2935,8 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
29342935
if (ret)
29352936
return ret;
29362937
cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
2937-
ari, ari_length, private_data, private_data_len);
2938+
ari, ari_length, private_data, private_data_len,
2939+
state);
29382940
break;
29392941
default:
29402942
pr_debug("%s: local_id %d, cm_id->state: %d\n", __func__,

drivers/infiniband/core/rdma_core.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ lookup_get_fd_uobject(const struct uverbs_api_object *obj,
360360
* uverbs_uobject_fd_release(), and the caller is expected to ensure
361361
* that release is never done while a call to lookup is possible.
362362
*/
363-
if (f->f_op != fd_type->fops) {
363+
if (f->f_op != fd_type->fops || uobject->ufile != ufile) {
364364
fput(f);
365365
return ERR_PTR(-EBADF);
366366
}
@@ -474,16 +474,15 @@ alloc_begin_fd_uobject(const struct uverbs_api_object *obj,
474474
filp = anon_inode_getfile(fd_type->name, fd_type->fops, NULL,
475475
fd_type->flags);
476476
if (IS_ERR(filp)) {
477+
uverbs_uobject_put(uobj);
477478
uobj = ERR_CAST(filp);
478-
goto err_uobj;
479+
goto err_fd;
479480
}
480481
uobj->object = filp;
481482

482483
uobj->id = new_fd;
483484
return uobj;
484485

485-
err_uobj:
486-
uverbs_uobject_put(uobj);
487486
err_fd:
488487
put_unused_fd(new_fd);
489488
return uobj;
@@ -679,7 +678,6 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj,
679678
enum rdma_lookup_mode mode)
680679
{
681680
assert_uverbs_usecnt(uobj, mode);
682-
uobj->uapi_object->type_class->lookup_put(uobj, mode);
683681
/*
684682
* In order to unlock an object, either decrease its usecnt for
685683
* read access or zero it in case of exclusive access. See
@@ -696,6 +694,7 @@ void rdma_lookup_put_uobject(struct ib_uobject *uobj,
696694
break;
697695
}
698696

697+
uobj->uapi_object->type_class->lookup_put(uobj, mode);
699698
/* Pairs with the kref obtained by type->lookup_get */
700699
uverbs_uobject_put(uobj);
701700
}

drivers/infiniband/core/uverbs_main.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
820820
ret = mmget_not_zero(mm);
821821
if (!ret) {
822822
list_del_init(&priv->list);
823+
if (priv->entry) {
824+
rdma_user_mmap_entry_put(priv->entry);
825+
priv->entry = NULL;
826+
}
823827
mm = NULL;
824828
continue;
825829
}

drivers/infiniband/hw/i40iw/i40iw_ctrl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1046,7 +1046,7 @@ i40iw_sc_query_rdma_features(struct i40iw_sc_cqp *cqp,
10461046
u64 header;
10471047

10481048
wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
1049-
if (wqe)
1049+
if (!wqe)
10501050
return I40IW_ERR_RING_FULL;
10511051

10521052
set_64bit_val(wqe, 32, feat_mem->pa);

drivers/infiniband/hw/mlx4/main.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,8 +1499,9 @@ static int __mlx4_ib_create_default_rules(
14991499
int i;
15001500

15011501
for (i = 0; i < ARRAY_SIZE(pdefault_rules->rules_create_list); i++) {
1502+
union ib_flow_spec ib_spec = {};
15021503
int ret;
1503-
union ib_flow_spec ib_spec;
1504+
15041505
switch (pdefault_rules->rules_create_list[i]) {
15051506
case 0:
15061507
/* no rule */

drivers/infiniband/hw/mlx5/qp.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5558,7 +5558,9 @@ static void to_rdma_ah_attr(struct mlx5_ib_dev *ibdev,
55585558
rdma_ah_set_path_bits(ah_attr, path->grh_mlid & 0x7f);
55595559
rdma_ah_set_static_rate(ah_attr,
55605560
path->static_rate ? path->static_rate - 5 : 0);
5561-
if (path->grh_mlid & (1 << 7)) {
5561+
5562+
if (path->grh_mlid & (1 << 7) ||
5563+
ah_attr->type == RDMA_AH_ATTR_TYPE_ROCE) {
55625564
u32 tc_fl = be32_to_cpu(path->tclass_flowlabel);
55635565

55645566
rdma_ah_set_grh(ah_attr, NULL,

drivers/infiniband/sw/rdmavt/cq.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,8 @@ int rvt_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
248248
*/
249249
if (udata && udata->outlen >= sizeof(__u64)) {
250250
cq->ip = rvt_create_mmap_info(rdi, sz, udata, u_wc);
251-
if (!cq->ip) {
252-
err = -ENOMEM;
251+
if (IS_ERR(cq->ip)) {
252+
err = PTR_ERR(cq->ip);
253253
goto bail_wc;
254254
}
255255

drivers/infiniband/sw/rdmavt/mmap.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ int rvt_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
154154
* @udata: user data (must be valid!)
155155
* @obj: opaque pointer to a cq, wq etc
156156
*
157-
* Return: rvt_mmap struct on success
157+
* Return: rvt_mmap struct on success, ERR_PTR on failure
158158
*/
159159
struct rvt_mmap_info *rvt_create_mmap_info(struct rvt_dev_info *rdi, u32 size,
160160
struct ib_udata *udata, void *obj)
@@ -166,7 +166,7 @@ struct rvt_mmap_info *rvt_create_mmap_info(struct rvt_dev_info *rdi, u32 size,
166166

167167
ip = kmalloc_node(sizeof(*ip), GFP_KERNEL, rdi->dparms.node);
168168
if (!ip)
169-
return ip;
169+
return ERR_PTR(-ENOMEM);
170170

171171
size = PAGE_ALIGN(size);
172172

drivers/infiniband/sw/rdmavt/qp.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,8 +1244,8 @@ struct ib_qp *rvt_create_qp(struct ib_pd *ibpd,
12441244

12451245
qp->ip = rvt_create_mmap_info(rdi, s, udata,
12461246
qp->r_rq.wq);
1247-
if (!qp->ip) {
1248-
ret = ERR_PTR(-ENOMEM);
1247+
if (IS_ERR(qp->ip)) {
1248+
ret = ERR_CAST(qp->ip);
12491249
goto bail_qpn;
12501250
}
12511251

drivers/infiniband/sw/rdmavt/srq.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,8 @@ int rvt_create_srq(struct ib_srq *ibsrq, struct ib_srq_init_attr *srq_init_attr,
111111
u32 s = sizeof(struct rvt_rwq) + srq->rq.size * sz;
112112

113113
srq->ip = rvt_create_mmap_info(dev, s, udata, srq->rq.wq);
114-
if (!srq->ip) {
115-
ret = -ENOMEM;
114+
if (IS_ERR(srq->ip)) {
115+
ret = PTR_ERR(srq->ip);
116116
goto bail_wq;
117117
}
118118

0 commit comments

Comments
 (0)