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

Commit 1c636f80 authored by Eli Cohen's avatar Eli Cohen Committed by Roland Dreier
Browse files

IB/core: Encorce MR access rights rules on kernel consumers



Enforce the rule that when requesting remote write or atomic permissions, local
write must be indicated as well. See IB spec 11.2.8.2.

Spotted by: Hagay Abramovsky <hagaya@mellanox.com>
Signed-off-by: default avatarEli Cohen <eli@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 180771a3
Loading
Loading
Loading
Loading
+3 −7
Original line number Original line Diff line number Diff line
@@ -939,13 +939,9 @@ ssize_t ib_uverbs_reg_mr(struct ib_uverbs_file *file,
	if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
	if ((cmd.start & ~PAGE_MASK) != (cmd.hca_va & ~PAGE_MASK))
		return -EINVAL;
		return -EINVAL;


	/*
	ret = ib_check_mr_access(cmd.access_flags);
	 * Local write permission is required if remote write or
	if (ret)
	 * remote atomic permission is also requested.
		return ret;
	 */
	if (cmd.access_flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) &&
	    !(cmd.access_flags & IB_ACCESS_LOCAL_WRITE))
		return -EINVAL;


	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
	uobj = kmalloc(sizeof *uobj, GFP_KERNEL);
	if (!uobj)
	if (!uobj)
+14 −0
Original line number Original line Diff line number Diff line
@@ -961,6 +961,11 @@ EXPORT_SYMBOL(ib_resize_cq);
struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
struct ib_mr *ib_get_dma_mr(struct ib_pd *pd, int mr_access_flags)
{
{
	struct ib_mr *mr;
	struct ib_mr *mr;
	int err;

	err = ib_check_mr_access(mr_access_flags);
	if (err)
		return ERR_PTR(err);


	mr = pd->device->get_dma_mr(pd, mr_access_flags);
	mr = pd->device->get_dma_mr(pd, mr_access_flags);


@@ -983,6 +988,11 @@ struct ib_mr *ib_reg_phys_mr(struct ib_pd *pd,
			     u64 *iova_start)
			     u64 *iova_start)
{
{
	struct ib_mr *mr;
	struct ib_mr *mr;
	int err;

	err = ib_check_mr_access(mr_access_flags);
	if (err)
		return ERR_PTR(err);


	if (!pd->device->reg_phys_mr)
	if (!pd->device->reg_phys_mr)
		return ERR_PTR(-ENOSYS);
		return ERR_PTR(-ENOSYS);
@@ -1013,6 +1023,10 @@ int ib_rereg_phys_mr(struct ib_mr *mr,
	struct ib_pd *old_pd;
	struct ib_pd *old_pd;
	int ret;
	int ret;


	ret = ib_check_mr_access(mr_access_flags);
	if (ret)
		return ret;

	if (!mr->device->rereg_phys_mr)
	if (!mr->device->rereg_phys_mr)
		return -ENOSYS;
		return -ENOSYS;


+13 −0
Original line number Original line Diff line number Diff line
@@ -2386,4 +2386,17 @@ struct ib_flow *ib_create_flow(struct ib_qp *qp,
			       struct ib_flow_attr *flow_attr, int domain);
			       struct ib_flow_attr *flow_attr, int domain);
int ib_destroy_flow(struct ib_flow *flow_id);
int ib_destroy_flow(struct ib_flow *flow_id);


static inline int ib_check_mr_access(int flags)
{
	/*
	 * Local write permission is required if remote write or
	 * remote atomic permission is also requested.
	 */
	if (flags & (IB_ACCESS_REMOTE_ATOMIC | IB_ACCESS_REMOTE_WRITE) &&
	    !(flags & IB_ACCESS_LOCAL_WRITE))
		return -EINVAL;

	return 0;
}

#endif /* IB_VERBS_H */
#endif /* IB_VERBS_H */