Commit edb98d16 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 3f777e19 f0abc761
Loading
Loading
Loading
Loading
+14 −12
Original line number Diff line number Diff line
@@ -862,7 +862,7 @@ static struct cm_id_private *cm_alloc_id_priv(struct ib_device *device,

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

@@ -1828,11 +1828,9 @@ static void cm_format_mra(struct cm_mra_msg *mra_msg,

static void cm_format_rej(struct cm_rej_msg *rej_msg,
			  struct cm_id_private *cm_id_priv,
			  enum ib_cm_rej_reason reason,
			  void *ari,
			  u8 ari_length,
			  const void *private_data,
			  u8 private_data_len)
			  enum ib_cm_rej_reason reason, void *ari,
			  u8 ari_length, const void *private_data,
			  u8 private_data_len, enum ib_cm_state state)
{
	lockdep_assert_held(&cm_id_priv->lock);

@@ -1840,7 +1838,7 @@ static void cm_format_rej(struct cm_rej_msg *rej_msg,
	IBA_SET(CM_REJ_REMOTE_COMM_ID, rej_msg,
		be32_to_cpu(cm_id_priv->id.remote_id));

	switch(cm_id_priv->id.state) {
	switch (state) {
	case IB_CM_REQ_RCVD:
		IBA_SET(CM_REJ_LOCAL_COMM_ID, rej_msg, be32_to_cpu(0));
		IBA_SET(CM_REJ_MESSAGE_REJECTED, rej_msg, CM_MSG_RESPONSE_REQ);
@@ -1906,7 +1904,8 @@ static void cm_dup_req_handler(struct cm_work *work,
		break;
	case IB_CM_TIMEWAIT:
		cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv,
			      IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0);
			      IB_CM_REJ_STALE_CONN, NULL, 0, NULL, 0,
			      IB_CM_TIMEWAIT);
		break;
	default:
		goto unlock;
@@ -2904,6 +2903,7 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
			      u8 ari_length, const void *private_data,
			      u8 private_data_len)
{
	enum ib_cm_state state = cm_id_priv->id.state;
	struct ib_mad_send_buf *msg;
	int ret;

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

	switch (cm_id_priv->id.state) {
	switch (state) {
	case IB_CM_REQ_SENT:
	case IB_CM_MRA_REQ_RCVD:
	case IB_CM_REQ_RCVD:
@@ -2925,7 +2925,8 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
		if (ret)
			return ret;
		cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
			      ari, ari_length, private_data, private_data_len);
			      ari, ari_length, private_data, private_data_len,
			      state);
		break;
	case IB_CM_REP_SENT:
	case IB_CM_MRA_REP_RCVD:
@@ -2934,7 +2935,8 @@ static int cm_send_rej_locked(struct cm_id_private *cm_id_priv,
		if (ret)
			return ret;
		cm_format_rej((struct cm_rej_msg *)msg->mad, cm_id_priv, reason,
			      ari, ari_length, private_data, private_data_len);
			      ari, ari_length, private_data, private_data_len,
			      state);
		break;
	default:
		pr_debug("%s: local_id %d, cm_id->state: %d\n", __func__,
+4 −5
Original line number Diff line number Diff line
@@ -360,7 +360,7 @@ lookup_get_fd_uobject(const struct uverbs_api_object *obj,
	 * uverbs_uobject_fd_release(), and the caller is expected to ensure
	 * that release is never done while a call to lookup is possible.
	 */
	if (f->f_op != fd_type->fops) {
	if (f->f_op != fd_type->fops || uobject->ufile != ufile) {
		fput(f);
		return ERR_PTR(-EBADF);
	}
@@ -474,16 +474,15 @@ alloc_begin_fd_uobject(const struct uverbs_api_object *obj,
	filp = anon_inode_getfile(fd_type->name, fd_type->fops, NULL,
				  fd_type->flags);
	if (IS_ERR(filp)) {
		uverbs_uobject_put(uobj);
		uobj = ERR_CAST(filp);
		goto err_uobj;
		goto err_fd;
	}
	uobj->object = filp;

	uobj->id = new_fd;
	return uobj;

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

	uobj->uapi_object->type_class->lookup_put(uobj, mode);
	/* Pairs with the kref obtained by type->lookup_get */
	uverbs_uobject_put(uobj);
}
+4 −0
Original line number Diff line number Diff line
@@ -820,6 +820,10 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
			ret = mmget_not_zero(mm);
			if (!ret) {
				list_del_init(&priv->list);
				if (priv->entry) {
					rdma_user_mmap_entry_put(priv->entry);
					priv->entry = NULL;
				}
				mm = NULL;
				continue;
			}
+1 −1
Original line number Diff line number Diff line
@@ -1046,7 +1046,7 @@ i40iw_sc_query_rdma_features(struct i40iw_sc_cqp *cqp,
	u64 header;

	wqe = i40iw_sc_cqp_get_next_send_wqe(cqp, scratch);
	if (wqe)
	if (!wqe)
		return I40IW_ERR_RING_FULL;

	set_64bit_val(wqe, 32, feat_mem->pa);
+2 −1
Original line number Diff line number Diff line
@@ -1499,8 +1499,9 @@ static int __mlx4_ib_create_default_rules(
	int i;

	for (i = 0; i < ARRAY_SIZE(pdefault_rules->rules_create_list); i++) {
		union ib_flow_spec ib_spec = {};
		int ret;
		union ib_flow_spec ib_spec;

		switch (pdefault_rules->rules_create_list[i]) {
		case 0:
			/* no rule */
Loading