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

Commit 659067b0 authored by Leon Romanovsky's avatar Leon Romanovsky Committed by Jason Gunthorpe
Browse files

RDMA/nldev: Prepare CAP_NET_ADMIN checks for .doit callbacks



The .doit callbacks don't have a netlink_callback to check capabilities so
in order to use the same fill_res_func for both .dump and .doit, we need
to do the capability check outside of those functions.

For .doit callbacks, it is possible to check CAP_NET_ADMIN directly on the
received sk_buff.

Signed-off-by: default avatarLeon Romanovsky <leonro@mellanox.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 8be565e6
Loading
Loading
Loading
Loading
+12 −10
Original line number Original line Diff line number Diff line
@@ -361,7 +361,7 @@ static int fill_res_name_pid(struct sk_buff *msg,
	return 0;
	return 0;
}
}


static int fill_res_qp_entry(struct sk_buff *msg, struct netlink_callback *cb,
static int fill_res_qp_entry(struct sk_buff *msg, bool has_cap_net_admin,
			     struct rdma_restrack_entry *res, uint32_t port)
			     struct rdma_restrack_entry *res, uint32_t port)
{
{
	struct ib_qp *qp = container_of(res, struct ib_qp, res);
	struct ib_qp *qp = container_of(res, struct ib_qp, res);
@@ -427,8 +427,7 @@ static int fill_res_qp_entry(struct sk_buff *msg, struct netlink_callback *cb,
	return -EMSGSIZE;
	return -EMSGSIZE;
}
}


static int fill_res_cm_id_entry(struct sk_buff *msg,
static int fill_res_cm_id_entry(struct sk_buff *msg, bool has_cap_net_admin,
				struct netlink_callback *cb,
				struct rdma_restrack_entry *res, uint32_t port)
				struct rdma_restrack_entry *res, uint32_t port)
{
{
	struct rdma_id_private *id_priv =
	struct rdma_id_private *id_priv =
@@ -487,7 +486,7 @@ static int fill_res_cm_id_entry(struct sk_buff *msg,
	return -EMSGSIZE;
	return -EMSGSIZE;
}
}


static int fill_res_cq_entry(struct sk_buff *msg, struct netlink_callback *cb,
static int fill_res_cq_entry(struct sk_buff *msg, bool has_cap_net_admin,
			     struct rdma_restrack_entry *res, uint32_t port)
			     struct rdma_restrack_entry *res, uint32_t port)
{
{
	struct ib_cq *cq = container_of(res, struct ib_cq, res);
	struct ib_cq *cq = container_of(res, struct ib_cq, res);
@@ -524,7 +523,7 @@ static int fill_res_cq_entry(struct sk_buff *msg, struct netlink_callback *cb,
	return -EMSGSIZE;
	return -EMSGSIZE;
}
}


static int fill_res_mr_entry(struct sk_buff *msg, struct netlink_callback *cb,
static int fill_res_mr_entry(struct sk_buff *msg, bool has_cap_net_admin,
			     struct rdma_restrack_entry *res, uint32_t port)
			     struct rdma_restrack_entry *res, uint32_t port)
{
{
	struct ib_mr *mr = container_of(res, struct ib_mr, res);
	struct ib_mr *mr = container_of(res, struct ib_mr, res);
@@ -535,7 +534,7 @@ static int fill_res_mr_entry(struct sk_buff *msg, struct netlink_callback *cb,
	if (!entry_attr)
	if (!entry_attr)
		goto out;
		goto out;


	if (netlink_capable(cb->skb, CAP_NET_ADMIN)) {
	if (has_cap_net_admin) {
		if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RKEY, mr->rkey))
		if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_RKEY, mr->rkey))
			goto err;
			goto err;
		if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LKEY, mr->lkey))
		if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LKEY, mr->lkey))
@@ -561,7 +560,7 @@ static int fill_res_mr_entry(struct sk_buff *msg, struct netlink_callback *cb,
	return -EMSGSIZE;
	return -EMSGSIZE;
}
}


static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb,
static int fill_res_pd_entry(struct sk_buff *msg, bool has_cap_net_admin,
			     struct rdma_restrack_entry *res, uint32_t port)
			     struct rdma_restrack_entry *res, uint32_t port)
{
{
	struct ib_pd *pd = container_of(res, struct ib_pd, res);
	struct ib_pd *pd = container_of(res, struct ib_pd, res);
@@ -572,7 +571,7 @@ static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb,
	if (!entry_attr)
	if (!entry_attr)
		goto out;
		goto out;


	if (netlink_capable(cb->skb, CAP_NET_ADMIN)) {
	if (has_cap_net_admin) {
		if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY,
		if (nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY,
				pd->local_dma_lkey))
				pd->local_dma_lkey))
			goto err;
			goto err;
@@ -909,7 +908,7 @@ static int nldev_res_get_dumpit(struct sk_buff *skb,
}
}


struct nldev_fill_res_entry {
struct nldev_fill_res_entry {
	int (*fill_res_func)(struct sk_buff *msg, struct netlink_callback *cb,
	int (*fill_res_func)(struct sk_buff *msg, bool has_cap_net_admin,
			     struct rdma_restrack_entry *res, u32 port);
			     struct rdma_restrack_entry *res, u32 port);
	enum rdma_nldev_attr nldev_attr;
	enum rdma_nldev_attr nldev_attr;
	enum rdma_nldev_command nldev_cmd;
	enum rdma_nldev_command nldev_cmd;
@@ -965,6 +964,7 @@ static int res_get_common_dumpit(struct sk_buff *skb,
	struct nlattr *table_attr;
	struct nlattr *table_attr;
	struct ib_device *device;
	struct ib_device *device;
	int start = cb->args[0];
	int start = cb->args[0];
	bool has_cap_net_admin;
	struct nlmsghdr *nlh;
	struct nlmsghdr *nlh;
	u32 index, port = 0;
	u32 index, port = 0;
	bool filled = false;
	bool filled = false;
@@ -1013,6 +1013,8 @@ static int res_get_common_dumpit(struct sk_buff *skb,
		goto err;
		goto err;
	}
	}


	has_cap_net_admin = netlink_capable(cb->skb, CAP_NET_ADMIN);

	down_read(&device->res.rwsem);
	down_read(&device->res.rwsem);
	hash_for_each_possible(device->res.hash, res, node, res_type) {
	hash_for_each_possible(device->res.hash, res, node, res_type) {
		if (idx < start)
		if (idx < start)
@@ -1032,7 +1034,7 @@ static int res_get_common_dumpit(struct sk_buff *skb,
		filled = true;
		filled = true;


		up_read(&device->res.rwsem);
		up_read(&device->res.rwsem);
		ret = fe->fill_res_func(skb, cb, res, port);
		ret = fe->fill_res_func(skb, has_cap_net_admin, res, port);
		down_read(&device->res.rwsem);
		down_read(&device->res.rwsem);
		/*
		/*
		 * Return resource back, but it won't be released till
		 * Return resource back, but it won't be released till