Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d89b9f50 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull rdma fixes from Jason Gunthorpe:
 "It has been fairly silent lately on our -rc front. Big queue of
  patches on the mailing list going to for-next though.

  Bug fixes:
   - qedr driver bugfixes causing application hangs, wrong uapi errnos,
     and a race condition
   - three syzkaller found bugfixes in the ucma uapi

  Regression fixes for things introduced in 4.16:
   - Crash on error introduced in mlx5 UMR flow
   - Crash on module unload/etc introduced by bad interaction of
     restrack and mlx5 patches this cycle
   - Typo in a two line syzkaller bugfix causing a bad regression
   - Coverity report of nonsense code in hns driver"

* tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma:
  RDMA/ucma: Introduce safer rdma_addr_size() variants
  RDMA/hns: ensure for-loop actually iterates and free's buffers
  RDMA/ucma: Check that device exists prior to accessing it
  RDMA/ucma: Check that device is connected prior to access it
  RDMA/rdma_cm: Fix use after free race with process_one_req
  RDMA/qedr: Fix QP state initialization race
  RDMA/qedr: Fix rc initialization on CNQ allocation failure
  RDMA/qedr: fix QP's ack timeout configuration
  RDMA/ucma: Correct option size check using optlen
  RDMA/restrack: Move restrack_clean to be symmetrical to restrack_init
  IB/mlx5: Don't clean uninitialized UMR resources
parents ab12762b 84652aef
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -207,6 +207,22 @@ int rdma_addr_size(struct sockaddr *addr)
}
EXPORT_SYMBOL(rdma_addr_size);

int rdma_addr_size_in6(struct sockaddr_in6 *addr)
{
	int ret = rdma_addr_size((struct sockaddr *) addr);

	return ret <= sizeof(*addr) ? ret : 0;
}
EXPORT_SYMBOL(rdma_addr_size_in6);

int rdma_addr_size_kss(struct __kernel_sockaddr_storage *addr)
{
	int ret = rdma_addr_size((struct sockaddr *) addr);

	return ret <= sizeof(*addr) ? ret : 0;
}
EXPORT_SYMBOL(rdma_addr_size_kss);

static struct rdma_addr_client self;

void rdma_addr_register_client(struct rdma_addr_client *client)
@@ -586,6 +602,15 @@ static void process_one_req(struct work_struct *_work)
	list_del(&req->list);
	mutex_unlock(&lock);

	/*
	 * Although the work will normally have been canceled by the
	 * workqueue, it can still be requeued as long as it is on the
	 * req_list, so it could have been requeued before we grabbed &lock.
	 * We need to cancel it after it is removed from req_list to really be
	 * sure it is safe to free.
	 */
	cancel_delayed_work(&req->work);

	req->callback(req->status, (struct sockaddr *)&req->src_addr,
		req->addr, req->context);
	put_client(req->client);
+1 −2
Original line number Diff line number Diff line
@@ -290,6 +290,7 @@ void ib_dealloc_device(struct ib_device *device)
{
	WARN_ON(device->reg_state != IB_DEV_UNREGISTERED &&
		device->reg_state != IB_DEV_UNINITIALIZED);
	rdma_restrack_clean(&device->res);
	put_device(&device->dev);
}
EXPORT_SYMBOL(ib_dealloc_device);
@@ -600,8 +601,6 @@ void ib_unregister_device(struct ib_device *device)
	}
	up_read(&lists_rwsem);

	rdma_restrack_clean(&device->res);

	ib_device_unregister_rdmacg(device);
	ib_device_unregister_sysfs(device);

+27 −20
Original line number Diff line number Diff line
@@ -632,6 +632,9 @@ static ssize_t ucma_bind_ip(struct ucma_file *file, const char __user *inbuf,
	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
		return -EFAULT;

	if (!rdma_addr_size_in6(&cmd.addr))
		return -EINVAL;

	ctx = ucma_get_ctx(file, cmd.id);
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);
@@ -645,22 +648,21 @@ static ssize_t ucma_bind(struct ucma_file *file, const char __user *inbuf,
			 int in_len, int out_len)
{
	struct rdma_ucm_bind cmd;
	struct sockaddr *addr;
	struct ucma_context *ctx;
	int ret;

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

	addr = (struct sockaddr *) &cmd.addr;
	if (cmd.reserved || !cmd.addr_size || (cmd.addr_size != rdma_addr_size(addr)))
	if (cmd.reserved || !cmd.addr_size ||
	    cmd.addr_size != rdma_addr_size_kss(&cmd.addr))
		return -EINVAL;

	ctx = ucma_get_ctx(file, cmd.id);
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

	ret = rdma_bind_addr(ctx->cm_id, addr);
	ret = rdma_bind_addr(ctx->cm_id, (struct sockaddr *) &cmd.addr);
	ucma_put_ctx(ctx);
	return ret;
}
@@ -670,23 +672,22 @@ static ssize_t ucma_resolve_ip(struct ucma_file *file,
			       int in_len, int out_len)
{
	struct rdma_ucm_resolve_ip cmd;
	struct sockaddr *src, *dst;
	struct ucma_context *ctx;
	int ret;

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

	src = (struct sockaddr *) &cmd.src_addr;
	dst = (struct sockaddr *) &cmd.dst_addr;
	if (!rdma_addr_size(src) || !rdma_addr_size(dst))
	if (!rdma_addr_size_in6(&cmd.src_addr) ||
	    !rdma_addr_size_in6(&cmd.dst_addr))
		return -EINVAL;

	ctx = ucma_get_ctx(file, cmd.id);
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

	ret = rdma_resolve_addr(ctx->cm_id, src, dst, cmd.timeout_ms);
	ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
				(struct sockaddr *) &cmd.dst_addr, cmd.timeout_ms);
	ucma_put_ctx(ctx);
	return ret;
}
@@ -696,24 +697,23 @@ static ssize_t ucma_resolve_addr(struct ucma_file *file,
				 int in_len, int out_len)
{
	struct rdma_ucm_resolve_addr cmd;
	struct sockaddr *src, *dst;
	struct ucma_context *ctx;
	int ret;

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

	src = (struct sockaddr *) &cmd.src_addr;
	dst = (struct sockaddr *) &cmd.dst_addr;
	if (cmd.reserved || (cmd.src_size && (cmd.src_size != rdma_addr_size(src))) ||
	    !cmd.dst_size || (cmd.dst_size != rdma_addr_size(dst)))
	if (cmd.reserved ||
	    (cmd.src_size && (cmd.src_size != rdma_addr_size_kss(&cmd.src_addr))) ||
	    !cmd.dst_size || (cmd.dst_size != rdma_addr_size_kss(&cmd.dst_addr)))
		return -EINVAL;

	ctx = ucma_get_ctx(file, cmd.id);
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

	ret = rdma_resolve_addr(ctx->cm_id, src, dst, cmd.timeout_ms);
	ret = rdma_resolve_addr(ctx->cm_id, (struct sockaddr *) &cmd.src_addr,
				(struct sockaddr *) &cmd.dst_addr, cmd.timeout_ms);
	ucma_put_ctx(ctx);
	return ret;
}
@@ -1166,6 +1166,11 @@ static ssize_t ucma_init_qp_attr(struct ucma_file *file,
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

	if (!ctx->cm_id->device) {
		ret = -EINVAL;
		goto out;
	}

	resp.qp_attr_mask = 0;
	memset(&qp_attr, 0, sizeof qp_attr);
	qp_attr.qp_state = cmd.qp_state;
@@ -1307,7 +1312,7 @@ static ssize_t ucma_set_option(struct ucma_file *file, const char __user *inbuf,
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

	if (unlikely(cmd.optval > KMALLOC_MAX_SIZE))
	if (unlikely(cmd.optlen > KMALLOC_MAX_SIZE))
		return -EINVAL;

	optval = memdup_user((void __user *) (unsigned long) cmd.optval,
@@ -1331,7 +1336,7 @@ static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
{
	struct rdma_ucm_notify cmd;
	struct ucma_context *ctx;
	int ret;
	int ret = -EINVAL;

	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
		return -EFAULT;
@@ -1340,7 +1345,9 @@ static ssize_t ucma_notify(struct ucma_file *file, const char __user *inbuf,
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

	if (ctx->cm_id->device)
		ret = rdma_notify(ctx->cm_id, (enum ib_event_type)cmd.event);

	ucma_put_ctx(ctx);
	return ret;
}
@@ -1426,7 +1433,7 @@ static ssize_t ucma_join_ip_multicast(struct ucma_file *file,
	join_cmd.response = cmd.response;
	join_cmd.uid = cmd.uid;
	join_cmd.id = cmd.id;
	join_cmd.addr_size = rdma_addr_size((struct sockaddr *) &cmd.addr);
	join_cmd.addr_size = rdma_addr_size_in6(&cmd.addr);
	if (!join_cmd.addr_size)
		return -EINVAL;

@@ -1445,7 +1452,7 @@ static ssize_t ucma_join_multicast(struct ucma_file *file,
	if (copy_from_user(&cmd, inbuf, sizeof(cmd)))
		return -EFAULT;

	if (!rdma_addr_size((struct sockaddr *)&cmd.addr))
	if (!rdma_addr_size_kss(&cmd.addr))
		return -EINVAL;

	return ucma_process_join(file, &cmd, out_len);
+1 −1
Original line number Diff line number Diff line
@@ -4383,7 +4383,7 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev,
	eq->l0_dma = 0;

	if (mhop_num == 1)
		for (i -= i; i >= 0; i--)
		for (i -= 1; i >= 0; i--)
			dma_free_coherent(dev, buf_chk_sz, eq->buf[i],
					  eq->buf_dma[i]);
	else if (mhop_num == 2) {
+9 −3
Original line number Diff line number Diff line
@@ -3448,8 +3448,11 @@ static void destroy_umrc_res(struct mlx5_ib_dev *dev)
	if (err)
		mlx5_ib_warn(dev, "mr cache cleanup failed\n");

	if (dev->umrc.qp)
		mlx5_ib_destroy_qp(dev->umrc.qp);
	if (dev->umrc.cq)
		ib_free_cq(dev->umrc.cq);
	if (dev->umrc.pd)
		ib_dealloc_pd(dev->umrc.pd);
}

@@ -3552,12 +3555,15 @@ static int create_umr_res(struct mlx5_ib_dev *dev)

error_4:
	mlx5_ib_destroy_qp(qp);
	dev->umrc.qp = NULL;

error_3:
	ib_free_cq(cq);
	dev->umrc.cq = NULL;

error_2:
	ib_dealloc_pd(pd);
	dev->umrc.pd = NULL;

error_0:
	kfree(attr);
Loading