From nobody Sat Feb 7 17:55:00 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B26061DF980 for ; Sat, 20 Dec 2025 00:27:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766190472; cv=none; b=Gnsy+shbEKLOiwPuDda04B69J2VmpSzbDDqiE1qCnqW5x3RyFuVWZd9fEWipwT52woVOasPgc2RvYxhthN1moVYopeFFOF10Ir9+GeysOi/h8SD9I5EbD/WufIrXtpHNykhLo7JvusOcvIJXsu/MbJR+aK6AqyxMusaz35rLAKc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1766190472; c=relaxed/simple; bh=7Z2OUXbptO/NfN1gs7yJUEVPzBYeU2xaHDk1S3Mo/cg=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=knBvSVmBCjbDdgXixPUkzegYwIyIAwaWCUmZDZUeXxX67zLr6z6hEK44ubyDilutnC3k7Y6yi6FIxdVMPNdrVBV92kBKBL35kRj0sJR5TRE/R4a8c4S/YjkFuRKQj9B7QSWQGHlEghTKocKEM8SrB5CTYAZVFtj0yQF2CIJrINE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IFDFGDQn; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="IFDFGDQn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 13C86C116C6; Sat, 20 Dec 2025 00:27:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1766190472; bh=7Z2OUXbptO/NfN1gs7yJUEVPzBYeU2xaHDk1S3Mo/cg=; h=From:To:Cc:Subject:Date:From; b=IFDFGDQncdyg7irsjOsa/9aWsv/+Acb26f0qgrg8YAxrs22pQGTxDChAWem+2bFrJ EbRLXyi+lW0tTs3xp138QclAIRiecBbtUcuicSE3UerdJujDsUK+Kse0YgWF6JYBXG Z00G1TMsYgnQSs23ADduzsthRm6vD2AfS0RUSGLJvg7aNLE1SRsOrfvmb4KbEgPO3a KHnm7ehQyGxlcZul4ihITO/zG71ScxvHHFnamV/9Vi6HN4QXVIQcqCIzFbKVXCJRVU ZItKb54c4kt/vXb5W8tztQV5r/vXOuXqL2uXzh4gEb2ZAOlWD/zwWpMIx8PlCNUsVz ALcxI5JsrqqeA== From: Dennis Zhou To: Tejun Heo , Christoph Lameter , Andrew Morton Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org, Dennis Zhou , Sebastian Andrzej Siewior Subject: [PATCH] percpu: add basic double free check Date: Fri, 19 Dec 2025 16:27:37 -0800 Message-ID: <20251220002737.84100-1-dennis@kernel.org> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" 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 Cc: Sebastian Andrzej Siewior --- mm/percpu.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mm/percpu.c b/mm/percpu.c index 81462ce5866e..c9f8df6c34c3 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -79,6 +79,7 @@ #include #include #include +#include #include #include #include @@ -1285,6 +1286,11 @@ static int pcpu_free_area(struct pcpu_chunk *chunk, = int off) =20 bit_off =3D off / PCPU_MIN_ALLOC_SIZE; =20 + /* check double free */ + if (!test_bit(bit_off, chunk->alloc_map) || + !test_bit(bit_off, chunk->bound_map)) + return 0; + /* find end index */ end =3D find_next_bit(chunk->bound_map, pcpu_chunk_map_bits(chunk), bit_off + 1); @@ -2225,6 +2231,7 @@ static void pcpu_balance_workfn(struct work_struct *w= ork) */ 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 +2249,13 @@ void free_percpu(void __percpu *ptr) =20 spin_lock_irqsave(&pcpu_lock, flags); size =3D pcpu_free_area(chunk, off); + if (size =3D=3D 0) { + spin_unlock_irqrestore(&pcpu_lock, flags); + + if (__ratelimit(&_rs)) + WARN(1, "percpu double free\n"); + return; + } =20 pcpu_alloc_tag_free_hook(chunk, off, size); =20 --=20 2.43.0