Commit 87d93e9a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Jason Gunthorpe:
 "Several regression fixes from work that landed in the merge window,
  particularly in the mlx5 driver:

   - Various static checker and warning fixes

   - General bug fixes in rvt, qedr, hns, mlx5 and hfi1

   - Several regression fixes related to the ECE and QP changes in last
     cycle

   - Fixes for a few long standing crashers in CMA, uverbs ioctl, and
     xrc"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (25 commits)
  IB/hfi1: Add atomic triggered sleep/wakeup
  IB/hfi1: Correct -EBUSY handling in tx code
  IB/hfi1: Fix module use count flaw due to leftover module put calls
  IB/hfi1: Restore kfree in dummy_netdev cleanup
  IB/mad: Fix use after free when destroying MAD agent
  RDMA/mlx5: Protect from kernel crash if XRC_TGT doesn't have udata
  RDMA/counter: Query a counter before release
  RDMA/mad: Fix possible memory leak in ib_mad_post_receive_mads()
  RDMA/mlx5: Fix integrity enabled QP creation
  RDMA/mlx5: Remove ECE limitation from the RAW_PACKET QPs
  RDMA/mlx5: Fix remote gid value in query QP
  RDMA/mlx5: Don't access ib_qp fields in internal destroy QP path
  RDMA/core: Check that type_attrs is not NULL prior access
  RDMA/hns: Fix an cmd queue issue when resetting
  RDMA/hns: Fix a calltrace when registering MR from userspace
  RDMA/mlx5: Add missed RST2INIT and INIT2INIT steps during ECE handshake
  RDMA/cma: Protect bind_list and listen_list while finding matching cm id
  RDMA/qedr: Fix KASAN: use-after-free in ucma_event_handler+0x532
  RDMA/efa: Set maximum pkeys device attribute
  RDMA/rvt: Fix potential memory leak caused by rvt_alloc_rq
  ...
parents 908f7d12 38fd98af
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -918,6 +918,7 @@ static void cm_free_work(struct cm_work *work)

static void cm_queue_work_unlock(struct cm_id_private *cm_id_priv,
				 struct cm_work *work)
	__releases(&cm_id_priv->lock)
{
	bool immediate;

+18 −0
Original line number Diff line number Diff line
@@ -1624,6 +1624,8 @@ static struct rdma_id_private *cma_find_listener(
{
	struct rdma_id_private *id_priv, *id_priv_dev;

	lockdep_assert_held(&lock);

	if (!bind_list)
		return ERR_PTR(-EINVAL);

@@ -1670,6 +1672,7 @@ cma_ib_id_from_event(struct ib_cm_id *cm_id,
		}
	}

	mutex_lock(&lock);
	/*
	 * Net namespace might be getting deleted while route lookup,
	 * cm_id lookup is in progress. Therefore, perform netdevice
@@ -1711,6 +1714,7 @@ cma_ib_id_from_event(struct ib_cm_id *cm_id,
	id_priv = cma_find_listener(bind_list, cm_id, ib_event, req, *net_dev);
err:
	rcu_read_unlock();
	mutex_unlock(&lock);
	if (IS_ERR(id_priv) && *net_dev) {
		dev_put(*net_dev);
		*net_dev = NULL;
@@ -2492,6 +2496,8 @@ static void cma_listen_on_dev(struct rdma_id_private *id_priv,
	struct net *net = id_priv->id.route.addr.dev_addr.net;
	int ret;

	lockdep_assert_held(&lock);

	if (cma_family(id_priv) == AF_IB && !rdma_cap_ib_cm(cma_dev->device, 1))
		return;

@@ -3342,6 +3348,8 @@ static void cma_bind_port(struct rdma_bind_list *bind_list,
	u64 sid, mask;
	__be16 port;

	lockdep_assert_held(&lock);

	addr = cma_src_addr(id_priv);
	port = htons(bind_list->port);

@@ -3370,6 +3378,8 @@ static int cma_alloc_port(enum rdma_ucm_port_space ps,
	struct rdma_bind_list *bind_list;
	int ret;

	lockdep_assert_held(&lock);

	bind_list = kzalloc(sizeof *bind_list, GFP_KERNEL);
	if (!bind_list)
		return -ENOMEM;
@@ -3396,6 +3406,8 @@ static int cma_port_is_unique(struct rdma_bind_list *bind_list,
	struct sockaddr  *saddr = cma_src_addr(id_priv);
	__be16 dport = cma_port(daddr);

	lockdep_assert_held(&lock);

	hlist_for_each_entry(cur_id, &bind_list->owners, node) {
		struct sockaddr  *cur_daddr = cma_dst_addr(cur_id);
		struct sockaddr  *cur_saddr = cma_src_addr(cur_id);
@@ -3435,6 +3447,8 @@ static int cma_alloc_any_port(enum rdma_ucm_port_space ps,
	unsigned int rover;
	struct net *net = id_priv->id.route.addr.dev_addr.net;

	lockdep_assert_held(&lock);

	inet_get_local_port_range(net, &low, &high);
	remaining = (high - low) + 1;
	rover = prandom_u32() % remaining + low;
@@ -3482,6 +3496,8 @@ static int cma_check_port(struct rdma_bind_list *bind_list,
	struct rdma_id_private *cur_id;
	struct sockaddr *addr, *cur_addr;

	lockdep_assert_held(&lock);

	addr = cma_src_addr(id_priv);
	hlist_for_each_entry(cur_id, &bind_list->owners, node) {
		if (id_priv == cur_id)
@@ -3512,6 +3528,8 @@ static int cma_use_port(enum rdma_ucm_port_space ps,
	unsigned short snum;
	int ret;

	lockdep_assert_held(&lock);

	snum = ntohs(cma_port(cma_src_addr(id_priv)));
	if (snum < PROT_SOCK && !capable(CAP_NET_BIND_SERVICE))
		return -EACCES;
+3 −1
Original line number Diff line number Diff line
@@ -202,7 +202,7 @@ static int __rdma_counter_unbind_qp(struct ib_qp *qp)
	return ret;
}

static void counter_history_stat_update(const struct rdma_counter *counter)
static void counter_history_stat_update(struct rdma_counter *counter)
{
	struct ib_device *dev = counter->device;
	struct rdma_port_counter *port_counter;
@@ -212,6 +212,8 @@ static void counter_history_stat_update(const struct rdma_counter *counter)
	if (!port_counter->hstats)
		return;

	rdma_counter_query_stats(counter);

	for (i = 0; i < counter->stats->num_counters; i++)
		port_counter->hstats->value[i] += counter->stats->value[i];
}
+2 −1
Original line number Diff line number Diff line
@@ -509,10 +509,10 @@ static void unregister_mad_agent(struct ib_mad_agent_private *mad_agent_priv)
	xa_erase(&ib_mad_clients, mad_agent_priv->agent.hi_tid);

	flush_workqueue(port_priv->wq);
	ib_cancel_rmpp_recvs(mad_agent_priv);

	deref_mad_agent(mad_agent_priv);
	wait_for_completion(&mad_agent_priv->comp);
	ib_cancel_rmpp_recvs(mad_agent_priv);

	ib_mad_agent_security_cleanup(&mad_agent_priv->agent);

@@ -2718,6 +2718,7 @@ static int ib_mad_post_receive_mads(struct ib_mad_qp_info *qp_info,
						 DMA_FROM_DEVICE);
		if (unlikely(ib_dma_mapping_error(qp_info->port_priv->device,
						  sg_list.addr))) {
			kfree(mad_priv);
			ret = -ENOMEM;
			break;
		}
+21 −15
Original line number Diff line number Diff line
@@ -470,40 +470,46 @@ static struct ib_uobject *
alloc_begin_fd_uobject(const struct uverbs_api_object *obj,
		       struct uverbs_attr_bundle *attrs)
{
	const struct uverbs_obj_fd_type *fd_type =
		container_of(obj->type_attrs, struct uverbs_obj_fd_type, type);
	const struct uverbs_obj_fd_type *fd_type;
	int new_fd;
	struct ib_uobject *uobj;
	struct ib_uobject *uobj, *ret;
	struct file *filp;

	uobj = alloc_uobj(attrs, obj);
	if (IS_ERR(uobj))
		return uobj;

	fd_type =
		container_of(obj->type_attrs, struct uverbs_obj_fd_type, type);
	if (WARN_ON(fd_type->fops->release != &uverbs_uobject_fd_release &&
		    fd_type->fops->release != &uverbs_async_event_release))
		return ERR_PTR(-EINVAL);
		    fd_type->fops->release != &uverbs_async_event_release)) {
		ret = ERR_PTR(-EINVAL);
		goto err_fd;
	}

	new_fd = get_unused_fd_flags(O_CLOEXEC);
	if (new_fd < 0)
		return ERR_PTR(new_fd);

	uobj = alloc_uobj(attrs, obj);
	if (IS_ERR(uobj))
	if (new_fd < 0) {
		ret = ERR_PTR(new_fd);
		goto err_fd;
	}

	/* Note that uverbs_uobject_fd_release() is called during abort */
	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_fd;
		ret = ERR_CAST(filp);
		goto err_getfile;
	}
	uobj->object = filp;

	uobj->id = new_fd;
	return uobj;

err_fd:
err_getfile:
	put_unused_fd(new_fd);
	return uobj;
err_fd:
	uverbs_uobject_put(uobj);
	return ret;
}

struct ib_uobject *rdma_alloc_begin_uobject(const struct uverbs_api_object *obj,
Loading