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. Signed-off-by: Sebastian Andrzej Siewior --- I managed accidentally a double free recently. This would have noticed it. It looks low overhead so there might be no need to hide it behind a debug switch. mm/percpu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mm/percpu.c b/mm/percpu.c index d9cbaee92b605..a2abddd85294a 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -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; -- 2.51.0