From: Leon Romanovsky <leonro@xxxxxxxxxxxx> 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@xxxxxxxxxxxx> --- 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 --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c index b9756a5cdf4f..1cf74b28d0f2 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_ */ -- 2.19.1