From: Dennis Zhou <dennis@kernel.org>
To: Tejun Heo <tj@kernel.org>, Christoph Lameter <cl@linux.com>,
Andrew Morton <akpm@linux-foundation.org>
Cc: Chris Mason <clm@meta.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
Dennis Zhou <dennis@kernel.org>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Subject: [PATCH v2] percpu: add basic double free check
Date: Thu, 15 Jan 2026 18:32:16 -0800 [thread overview]
Message-ID: <20260116023216.14515-1-dennis@kernel.org> (raw)
This adds a basic double free check by validating the first bit of the
allocation in alloc_map and bound_map are set. If the alloc_map bit is
not set, then this means the area is currently unallocated. If the
bound_map bit is not set, then we are not freeing from the beginning of
the allocation.
This is a respin of [1] adding the requested changes from me and
Christoph.
[1] https://lore.kernel.org/linux-mm/20250904143514.Yk6Ap-jy@linutronix.de/
Signed-off-by: Dennis Zhou <dennis@kernel.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
v2:
- moved pcpu_stats_area_dealloc()
- added additional check for bit_off out of bounds
mm/percpu.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/mm/percpu.c b/mm/percpu.c
index 81462ce5866e..2f1ac2059a15 100644
--- a/mm/percpu.c
+++ b/mm/percpu.c
@@ -79,6 +79,7 @@
#include <linux/mutex.h>
#include <linux/percpu.h>
#include <linux/pfn.h>
+#include <linux/ratelimit.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/vmalloc.h>
@@ -1276,18 +1277,24 @@ 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 region_bits = pcpu_chunk_map_bits(chunk);
int bit_off, bits, end, oslot, freed;
lockdep_assert_held(&pcpu_lock);
- pcpu_stats_area_dealloc(chunk);
oslot = pcpu_chunk_slot(chunk);
bit_off = off / PCPU_MIN_ALLOC_SIZE;
+ if (unlikely(bit_off < 0 || bit_off >= region_bits))
+ return 0;
+
+ /* check double free */
+ if (!test_bit(bit_off, chunk->alloc_map) ||
+ !test_bit(bit_off, chunk->bound_map))
+ return 0;
/* find end index */
- end = find_next_bit(chunk->bound_map, pcpu_chunk_map_bits(chunk),
- bit_off + 1);
+ end = find_next_bit(chunk->bound_map, region_bits, bit_off + 1);
bits = end - bit_off;
bitmap_clear(chunk->alloc_map, bit_off, bits);
@@ -1303,6 +1310,8 @@ static int pcpu_free_area(struct pcpu_chunk *chunk, int off)
pcpu_chunk_relocate(chunk, oslot);
+ pcpu_stats_area_dealloc(chunk);
+
return freed;
}
@@ -2225,6 +2234,7 @@ static void pcpu_balance_workfn(struct work_struct *work)
*/
void free_percpu(void __percpu *ptr)
{
+ static DEFINE_RATELIMIT_STATE(_rs, 60 * HZ, DEFAULT_RATELIMIT_BURST);
void *addr;
struct pcpu_chunk *chunk;
unsigned long flags;
@@ -2242,6 +2252,13 @@ void free_percpu(void __percpu *ptr)
spin_lock_irqsave(&pcpu_lock, flags);
size = pcpu_free_area(chunk, off);
+ if (size == 0) {
+ spin_unlock_irqrestore(&pcpu_lock, flags);
+
+ if (__ratelimit(&_rs))
+ WARN(1, "percpu double free or bad ptr\n");
+ return;
+ }
pcpu_alloc_tag_free_hook(chunk, off, size);
--
2.43.0
next reply other threads:[~2026-01-16 2:32 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-16 2:32 Dennis Zhou [this message]
2026-01-17 3:15 ` [PATCH v2] percpu: add basic double free check Andrew Morton
2026-01-17 5:15 ` Dennis Zhou
2026-01-18 1:09 ` Andrew Morton
2026-01-19 7:48 ` Sebastian Andrzej Siewior
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260116023216.14515-1-dennis@kernel.org \
--to=dennis@kernel.org \
--cc=akpm@linux-foundation.org \
--cc=bigeasy@linutronix.de \
--cc=cl@linux.com \
--cc=clm@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.