diff mbox series

[rdma-next,v1,1/6] RDMA/restrack: Fortify source by ensuring that restrack type is set

Message ID 20190120130600.8788-2-leon@kernel.org (mailing list archive)
State Changes Requested
Headers show
Series Annotate mlx5 driver to reuse restrack IDs | expand

Commit Message

Leon Romanovsky Jan. 20, 2019, 1:05 p.m. UTC
From: Leon Romanovsky <leonro@mellanox.com>

Allowance to use rdma_restrack_add() by the drivers can potentially
create situations where restrack entry is used without type initialized
before. This patch adds various checks and warnings to survive such
situation, which are not supposed to be if driver authors don't do
mistake.

Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
---
 drivers/infiniband/core/nldev.c    |  2 +-
 drivers/infiniband/core/restrack.c | 32 ++++++++++++++++++++++++------
 include/rdma/restrack.h            | 20 +++++++++++++++++--
 3 files changed, 45 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index de3e90d6fb5a..69b04fbb6e8e 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -324,7 +324,7 @@  static int fill_res_info(struct sk_buff *msg, struct ib_device *device)
 	if (!table_attr)
 		return -EMSGSIZE;
 
-	for (i = 0; i < RDMA_RESTRACK_MAX; i++) {
+	for (i = RDMA_RESTRACK_START; i < RDMA_RESTRACK_MAX; i++) {
 		if (!names[i])
 			continue;
 		curr = rdma_restrack_count(device, i,
diff --git a/drivers/infiniband/core/restrack.c b/drivers/infiniband/core/restrack.c
index 415a534873fe..78f9df74396f 100644
--- a/drivers/infiniband/core/restrack.c
+++ b/drivers/infiniband/core/restrack.c
@@ -87,7 +87,7 @@  int rdma_restrack_init(struct ib_device *dev)
 
 	rt = dev->res;
 
-	for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) {
+	for (i = RDMA_RESTRACK_START; i < RDMA_RESTRACK_MAX; i++) {
 		init_rwsem(&rt[i].rwsem);
 		xa_init_flags(&rt[i].xa, XA_FLAGS_ALLOC);
 		rt[i].range.max = U32_MAX;
@@ -171,7 +171,7 @@  void rdma_restrack_clean(struct ib_device *dev)
 	const char *owner;
 	int i;
 
-	for (i = 0 ; i < RDMA_RESTRACK_MAX; i++) {
+	for (i = RDMA_RESTRACK_START; i < RDMA_RESTRACK_MAX; i++) {
 		struct xarray *xa = rdma_dev_to_xa(dev, i);
 
 		if (!xa_empty(xa)) {
@@ -307,10 +307,20 @@  EXPORT_SYMBOL(rdma_restrack_set_task);
 int rdma_restrack_add(struct rdma_restrack_entry *res)
 {
 	struct ib_device *dev = res_to_dev(res);
-	struct xarray *xa = rdma_dev_to_xa(dev, res->type);
-	struct rdma_restrack_root *rt = dev->res;
+	struct rdma_restrack_root *rt;
+	struct xarray *xa;
 	int ret;
 
+	if (!dev)
+		/*
+		 * Someone forgot to set resource type,
+		 * never should occur in real life
+		 */
+		return -EINVAL;
+
+	xa = rdma_dev_to_xa(dev, res->type);
+	rt = dev->res;
+
 	/*
 	 * Once all drivers are converted, we can remove this check
 	 * and remove call to rdma_restrack_add() from rdma_restrack_kadd()
@@ -380,7 +390,12 @@  EXPORT_SYMBOL(rdma_restrack_kadd);
 void rdma_restrack_uadd(struct rdma_restrack_entry *res)
 {
 	struct ib_device *dev = res_to_dev(res);
-	struct xarray *xa = rdma_dev_to_xa(dev, res->type);
+	struct xarray *xa;
+
+	if (!dev)
+		return;
+
+	xa = rdma_dev_to_xa(dev, res->type);
 
 	if (res->type != RDMA_RESTRACK_CM_ID)
 		res->task = NULL;
@@ -520,7 +535,12 @@  EXPORT_SYMBOL(rdma_rt_set_id_range);
 int rdma_rt_set_id(struct rdma_restrack_entry *res, u32 id)
 {
 	struct ib_device *dev = res_to_dev(res);
-	struct xarray *xa = rdma_dev_to_xa(dev, res->type);
+	struct xarray *xa;
+
+	if (!dev)
+		return -EINVAL;
+
+	xa = rdma_dev_to_xa(dev, res->type);
 
 	if (xa_load(xa, id) == res) {
 		WARN_ONCE(true, "Tried to add non-unique %s entry %u\n",
diff --git a/include/rdma/restrack.h b/include/rdma/restrack.h
index aa741907d1f4..be1936b54f98 100644
--- a/include/rdma/restrack.h
+++ b/include/rdma/restrack.h
@@ -18,10 +18,23 @@ 
  * enum rdma_restrack_type - HW objects to track
  */
 enum rdma_restrack_type {
+	/**
+	 * @RDMA_RESTRACK_NOT_VALID: Initial value
+	 *
+	 * We assume that all objects below were zeroed in the initialization
+	 * phase and 0 as rdma_restrack_type will help us to catch unset type.
+	 */
+	RDMA_RESTRACK_NOT_VALID,
+	/**
+	 * @RDMA_RESTRACK_START: Initial entry needed for iterators
+	 */
+	RDMA_RESTRACK_START,
+
+	/* SUPPORTED OBJECTS */
 	/**
 	 * @RDMA_RESTRACK_PD: Protection domain (PD)
 	 */
-	RDMA_RESTRACK_PD,
+	RDMA_RESTRACK_PD = RDMA_RESTRACK_START,
 	/**
 	 * @RDMA_RESTRACK_CQ: Completion queue (CQ)
 	 */
@@ -43,7 +56,7 @@  enum rdma_restrack_type {
 	 */
 	RDMA_RESTRACK_CTX,
 	/**
-	 * @RDMA_RESTRACK_MAX: Last entry, used for array dclarations
+	 * @RDMA_RESTRACK_MAX: Last entry, used for array declarations
 	 */
 	RDMA_RESTRACK_MAX
 };
@@ -192,6 +205,9 @@  int rdma_rt_set_id(struct rdma_restrack_entry *res, u32 id);
 static inline void rdma_rt_set_type(struct rdma_restrack_entry *res,
 				    enum rdma_restrack_type type)
 {
+	WARN_ONCE((type == RDMA_RESTRACK_NOT_VALID ||
+		   type == RDMA_RESTRACK_MAX),
+		  "There is attempt to set not valid restrack type\n");
 	res->type = type;
 }
 #endif /* _RDMA_RESTRACK_H_ */