Commit adac4cb3 authored by Jason Gunthorpe's avatar Jason Gunthorpe
Browse files

RDMA/uverbs: Check ODP in ib_check_mr_access() as well

No reason only one caller checks this. This properly blocks ODP
from the rereg flow if the device does not support ODP.

Link: https://lore.kernel.org/r/20201130075839.278575-3-leon@kernel.org


Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent b9653b31
Loading
Loading
Loading
Loading
+5 −14
Original line number Diff line number Diff line
@@ -709,29 +709,20 @@ static int ib_uverbs_reg_mr(struct uverbs_attr_bundle *attrs)
	if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
		return -EINVAL;

	ret = ib_check_mr_access(cmd.access_flags);
	if (ret)
		return ret;

	uobj = uobj_alloc(UVERBS_OBJECT_MR, attrs, &ib_dev);
	if (IS_ERR(uobj))
		return PTR_ERR(uobj);

	ret = ib_check_mr_access(ib_dev, cmd.access_flags);
	if (ret)
		goto err_free;

	pd = uobj_get_obj_read(pd, UVERBS_OBJECT_PD, cmd.pd_handle, attrs);
	if (!pd) {
		ret = -EINVAL;
		goto err_free;
	}

	if (cmd.access_flags & IB_ACCESS_ON_DEMAND) {
		if (!(pd->device->attrs.device_cap_flags &
		      IB_DEVICE_ON_DEMAND_PAGING)) {
			pr_debug("ODP support not available\n");
			ret = -EINVAL;
			goto err_put;
		}
	}

	mr = pd->device->ops.reg_user_mr(pd, cmd.start, cmd.length, cmd.hca_va,
					 cmd.access_flags,
					 &attrs->driver_udata);
@@ -805,7 +796,7 @@ static int ib_uverbs_rereg_mr(struct uverbs_attr_bundle *attrs)
	}

	if (cmd.flags & IB_MR_REREG_ACCESS) {
		ret = ib_check_mr_access(cmd.access_flags);
		ret = ib_check_mr_access(mr->device, cmd.access_flags);
		if (ret)
			goto put_uobjs;
	}
+1 −1
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ static int UVERBS_HANDLER(UVERBS_METHOD_DM_MR_REG)(
	if (!(attr.access_flags & IB_ZERO_BASED))
		return -EINVAL;

	ret = ib_check_mr_access(attr.access_flags);
	ret = ib_check_mr_access(ib_dev, attr.access_flags);
	if (ret)
		return ret;

+1 −1
Original line number Diff line number Diff line
@@ -2068,7 +2068,7 @@ static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
	if (err)
		return err;

	err = ib_check_mr_access(access);
	err = ib_check_mr_access(&dev->ib_dev, access);
	if (err)
		return err;

+5 −1
Original line number Diff line number Diff line
@@ -4183,7 +4183,8 @@ struct ib_xrcd *ib_alloc_xrcd_user(struct ib_device *device,
				   struct inode *inode, struct ib_udata *udata);
int ib_dealloc_xrcd_user(struct ib_xrcd *xrcd, struct ib_udata *udata);

static inline int ib_check_mr_access(int flags)
static inline int ib_check_mr_access(struct ib_device *ib_dev,
				     unsigned int flags)
{
	/*
	 * Local write permission is required if remote write or
@@ -4196,6 +4197,9 @@ static inline int ib_check_mr_access(int flags)
	if (flags & ~IB_ACCESS_SUPPORTED)
		return -EINVAL;

	if (flags & IB_ACCESS_ON_DEMAND &&
	    !(ib_dev->attrs.device_cap_flags & IB_DEVICE_ON_DEMAND_PAGING))
		return -EINVAL;
	return 0;
}