From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 6B77D343893; Sat, 12 Sep 2026 12:05:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789214721; cv=none; b=clEQ1wGoAi50A7lpouJ1DH8y1G4kyA+g0T4Xhbc8V/CvJaBUNj14SooGIe2LDEgRrsYUsNOSYJh8Szbb97mZUKx9KUFbkNsvYGwZlsO8PMgHk86cV23+WgMb6ETneOelwBszvk21XcnriwCqFBRXOH6FyjElW/C0g34Vq86w9V4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789214721; c=relaxed/simple; bh=ZhnBsHC9AhvIag1WaIaTzDZCLWcz4eU3nxGBaiU60lY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jBVQc/SecN1RYrMKjvlTmdldAnhOam1j3zNkGn7Sc4I0ZX+Oaqwk/M85TftO5+8e7ueIlQLdOhZqLbhe4Cl0sP7i0yp3bfqz57nIANgpmwvNU4z1TyoJKHQHpYIuWcH4J1+YKn91Alhc/qgfrQWuaBixTKgvKvcy1HMe3eV7xdU= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=1P0qbr6B; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="1P0qbr6B" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 706581F000FF; Sat, 12 Sep 2026 12:05:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1789214720; bh=DhnPK3uEZCbruPRUmvgiIaRwKnXgGOdO4+2AGjdYJl4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=1P0qbr6BlnCJIUlNnFRozhwNC/webLbp1dICeIrHRQmudLJEZ7MZQ1QfM7DLGFgdk DnkQqwZXlukpXk08KNBpSbIrhbURCMGK1T6WyQx9EkK9GjOdWPxgYmeJ1pCEG6NI/6 YKkz+7+/EkWzdy4yJNhG88ysQwsiZSL5jrRqlhNg= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Sashiko , Gregory Price , "David Hildenbrand (Arm)" , "Mike Rapoport (Microsoft)" , Sasha Levin Subject: [PATCH 6.12 0385/1376] mm/mm_init: handle alloc_percpu failure in free_area_init_core_hotplug Date: Sat, 12 Sep 2026 08:46:51 +0200 Message-ID: <20260912065616.128651204@linuxfoundation.org> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260912065607.535295758@linuxfoundation.org> References: <20260912065607.535295758@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 6.12-stable review patch. If anyone has any objections, please let me know. ------------------ From: Gregory Price [ Upstream commit 2ebce860bdd7ae5e13002811bc9bbbf33fcfc221 ] We miss a failed allocation check for pgdat->per_cpu_nodestats, which results in a NULL deref when we offset into the per-cpu area. Propagate -ENOMEM up the stack and leave per_cpu_nodestats pointing at boot_nodestats so a later online can retry the allocation. hotadd_init_pgdat() returns NULL on failure, which __try_online_node() already maps to -ENOMEM. On failure nothing needs to be unwound: - the node is never marked online - per_cpu_nodestats is left pointing at boot_nodestats - __add_memory_resource() cleans up pending memblock resources - later online attempts retry the per_cpu_nodestats allocation Reported-by: Sashiko Link: https://sashiko.dev/#/patchset/20260627202243.758289-1-gourry%40gourry.net Fixes: 75ef71840539 ("mm, vmstat: add infrastructure for per-node vmstats") Signed-off-by: Gregory Price Acked-by: David Hildenbrand (Arm) Link: https://patch.msgid.link/20260701221613.2818148-1-gourry@gourry.net Signed-off-by: Mike Rapoport (Microsoft) Signed-off-by: Sasha Levin --- include/linux/memory_hotplug.h | 2 +- mm/memory_hotplug.c | 3 ++- mm/mm_init.c | 14 +++++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h index 1b6b9ed7887db..d93a70c112ee8 100644 --- a/include/linux/memory_hotplug.h +++ b/include/linux/memory_hotplug.h @@ -305,7 +305,7 @@ static inline void __remove_memory(u64 start, u64 size) {} /* Default online_type (MMOP_*) when new memory blocks are added. */ extern enum mmop mhp_get_default_online_type(void); extern void mhp_set_default_online_type(enum mmop online_type); -extern void __ref free_area_init_core_hotplug(struct pglist_data *pgdat); +int __ref free_area_init_core_hotplug(struct pglist_data *pgdat); extern int __add_memory(int nid, u64 start, u64 size, mhp_t mhp_flags); extern int add_memory(int nid, u64 start, u64 size, mhp_t mhp_flags); extern int add_memory_resource(int nid, struct resource *resource, diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 4d764f4ec213b..e21f59cf29d9f 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -1266,7 +1266,8 @@ static pg_data_t *hotadd_init_pgdat(int nid) pgdat = NODE_DATA(nid); /* init node's zones as empty zones, we don't have any present pages.*/ - free_area_init_core_hotplug(pgdat); + if (free_area_init_core_hotplug(pgdat)) + return NULL; /* * The node we allocated has no zone fallback lists. For avoiding diff --git a/mm/mm_init.c b/mm/mm_init.c index c8ac7f206f941..65f997ddd740d 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c @@ -1519,7 +1519,7 @@ void __init set_pageblock_order(void) * NOTE: this function is only called during memory hotplug */ #ifdef CONFIG_MEMORY_HOTPLUG -void __ref free_area_init_core_hotplug(struct pglist_data *pgdat) +int __ref free_area_init_core_hotplug(struct pglist_data *pgdat) { int nid = pgdat->node_id; enum zone_type z; @@ -1527,8 +1527,14 @@ void __ref free_area_init_core_hotplug(struct pglist_data *pgdat) pgdat_init_internals(pgdat); - if (pgdat->per_cpu_nodestats == &boot_nodestats) - pgdat->per_cpu_nodestats = alloc_percpu(struct per_cpu_nodestat); + if (pgdat->per_cpu_nodestats == &boot_nodestats) { + struct per_cpu_nodestat __percpu *p; + + p = alloc_percpu(struct per_cpu_nodestat); + if (!p) + return -ENOMEM; + pgdat->per_cpu_nodestats = p; + } /* * Reset the nr_zones, order and highest_zoneidx before reuse. @@ -1566,6 +1572,8 @@ void __ref free_area_init_core_hotplug(struct pglist_data *pgdat) zone->present_pages = 0; zone_init_internals(zone, z, nid, 0); } + + return 0; } #endif -- 2.53.0