]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm/percpu: add a simple double-free check for per-CPU memory
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>
Thu, 4 Sep 2025 14:35:14 +0000 (16:35 +0200)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 12 Sep 2025 00:25:50 +0000 (17:25 -0700)
The free path clears the allocation bits in pcpu_chunk::alloc_map.  A
simple double free check would be to check if the bits, which are about to
be cleared, are already cleared.

Check if the bit is already cleared. Issue a warning and abort free in
that case.

Link: https://lkml.kernel.org/r/20250904143514.Yk6Ap-jy@linutronix.de
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Christoph Lameter (Ampere) <cl@gentwo.org>
Cc: Dennis Zhou <dennis@kernel.org>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/percpu.c

index 81462ce5866e1665a1ab13a86584610c355890b3..9d3f1a8d908d2ce308dd89118957c512e164996a 100644 (file)
@@ -1276,7 +1276,7 @@ static int pcpu_alloc_area(struct pcpu_chunk *chunk, int alloc_bits,
 static int pcpu_free_area(struct pcpu_chunk *chunk, int off)
 {
        struct pcpu_block_md *chunk_md = &chunk->chunk_md;
-       int bit_off, bits, end, oslot, freed;
+       int bit_off, bits, end, oslot, freed, free_bit;
 
        lockdep_assert_held(&pcpu_lock);
        pcpu_stats_area_dealloc(chunk);
@@ -1289,6 +1289,11 @@ static int pcpu_free_area(struct pcpu_chunk *chunk, int off)
        end = find_next_bit(chunk->bound_map, pcpu_chunk_map_bits(chunk),
                            bit_off + 1);
        bits = end - bit_off;
+
+       free_bit = find_next_bit(chunk->alloc_map, end, bit_off);
+       if (WARN(free_bit != bit_off, "Trying to free already free memory"))
+               return 0;
+
        bitmap_clear(chunk->alloc_map, bit_off, bits);
 
        freed = bits * PCPU_MIN_ALLOC_SIZE;