summaryrefslogtreecommitdiffstats
path: root/lib/cpu_rmap.c
diff options
context:
space:
mode:
authorEli Cohen <elic@nvidia.com>2023-02-14 08:29:46 +0100
committerSaeed Mahameed <saeedm@nvidia.com>2023-03-25 00:04:10 +0100
commit9821d8d4628e630ab56f47a8e6b878a2576e069b (patch)
tree06cbe34a046e0ec777302047d7b710b724f6f73e /lib/cpu_rmap.c
parentlib: cpu_rmap: Avoid use after free on rmap->obj array entries (diff)
downloadlinux-9821d8d4628e630ab56f47a8e6b878a2576e069b.tar.xz
linux-9821d8d4628e630ab56f47a8e6b878a2576e069b.zip
lib: cpu_rmap: Use allocator for rmap entries
Use a proper allocator for rmap entries using a naive for loop. The allocator relies on whether an entry is NULL to be considered free. Remove the used field of rmap which is not needed. Also, avoid crashing the kernel if an entry is not available. Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Eli Cohen <elic@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com> Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Diffstat (limited to 'lib/cpu_rmap.c')
-rw-r--r--lib/cpu_rmap.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/lib/cpu_rmap.c b/lib/cpu_rmap.c
index e77f12bb3c77..5d4bf7a8b926 100644
--- a/lib/cpu_rmap.c
+++ b/lib/cpu_rmap.c
@@ -128,19 +128,31 @@ debug_print_rmap(const struct cpu_rmap *rmap, const char *prefix)
}
#endif
+static int get_free_index(struct cpu_rmap *rmap)
+{
+ int i;
+
+ for (i = 0; i < rmap->size; i++)
+ if (!rmap->obj[i])
+ return i;
+
+ return -ENOSPC;
+}
+
/**
* cpu_rmap_add - add object to a rmap
* @rmap: CPU rmap allocated with alloc_cpu_rmap()
* @obj: Object to add to rmap
*
- * Return index of object.
+ * Return index of object or -ENOSPC if no free entry was found
*/
int cpu_rmap_add(struct cpu_rmap *rmap, void *obj)
{
- u16 index;
+ int index = get_free_index(rmap);
+
+ if (index < 0)
+ return index;
- BUG_ON(rmap->used >= rmap->size);
- index = rmap->used++;
rmap->obj[index] = obj;
return index;
}
@@ -230,7 +242,7 @@ void free_irq_cpu_rmap(struct cpu_rmap *rmap)
if (!rmap)
return;
- for (index = 0; index < rmap->used; index++) {
+ for (index = 0; index < rmap->size; index++) {
glue = rmap->obj[index];
if (glue)
irq_set_affinity_notifier(glue->notify.irq, NULL);
@@ -295,13 +307,22 @@ int irq_cpu_rmap_add(struct cpu_rmap *rmap, int irq)
glue->notify.release = irq_cpu_rmap_release;
glue->rmap = rmap;
cpu_rmap_get(rmap);
- glue->index = cpu_rmap_add(rmap, glue);
+ rc = cpu_rmap_add(rmap, glue);
+ if (rc < 0)
+ goto err_add;
+
+ glue->index = rc;
rc = irq_set_affinity_notifier(irq, &glue->notify);
- if (rc) {
- cpu_rmap_put(glue->rmap);
- rmap->obj[glue->index] = NULL;
- kfree(glue);
- }
+ if (rc)
+ goto err_set;
+
+ return rc;
+
+err_set:
+ rmap->obj[glue->index] = NULL;
+err_add:
+ cpu_rmap_put(glue->rmap);
+ kfree(glue);
return rc;
}
EXPORT_SYMBOL(irq_cpu_rmap_add);