mm: add missing alloc_percpu() NULL check in hotplug init
PATCH 1/1 mm: add missing alloc_percpu() NULL check in hotplug init
From: Hongfu Li <[email protected]>
No NULL check is done for alloc_percpu() when initializing per-CPU nodestats. Allocation failure leads to NULL pointer dereference during later memset.
Make function return int, check alloc_percpu() result and return -ENOMEM on error. The caller chain already propagates this error correctly.
--- include/linux/memory_hotplug.h | 2 +- mm/memory_hotplug.c | 3 ++- mm/mm_init.c | 14 +++++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-)
include/linux/memory_hotplug.h +1 -1
@@ -289,7 +289,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); +extern 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,
mm/memory_hotplug.c +2 -1
@@ -1263,7 +1263,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
mm/mm_init.c +11 -3
@@ -1536,7 +1536,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;
@@ -1544,8 +1544,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 *new; + + new = alloc_percpu(struct per_cpu_nodestat); +if (!new) +return -ENOMEM ; + pgdat->per_cpu_nodestats = new; + }/* * Reset the nr_zones, order and highest_zoneidx before reuse.
@@ -1576,6 +1582,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
Signature · 1 line
2.54.0
Mike Rapoport
maintainerQuoted 9 lines · Hongfu Li
From: Hongfu Li <[email protected]>
No NULL check is done for
alloc_percpu()when initializing per-CPU nodestats. Allocation failure leads to NULL pointer dereference during later memset.Make function return int, check
alloc_percpu()result and return-ENOMEMon error. The caller chain already propagates this error correctly.
I already applied a fix from Gregory:
https://patch.msgid.link/[email protected]
It'll be unstreamed soon.
Quoted 6 lines
Signed-off-by Hongfu Li <[email protected]>--- include/linux/memory_hotplug.h | 2 +- mm/memory_hotplug.c | 3 ++- mm/mm_init.c | 14 +++++++++++--- 3 files changed, 14 insertions(+), 5 deletions(-)
Signature · 2 lines
Sincerely yours, Mike.
Quoted 7 lines · Mike Rapoport
Quoted 6 lines · Hongfu Li
From: Hongfu Li <[email protected]>
No NULL check is done for
alloc_percpu()when initializing per-CPU nodestats. Allocation failure leads to NULL pointer dereference during later memset.
Quoted 8 lines
Quoted 3 lines
Make function return int, check
alloc_percpu()result and return-ENOMEMon error. The caller chain already propagates this error correctly.I already applied a fix from Gregory:
https://patch.msgid.link/[email protected]
It'll be unstreamed soon.
Got it, I'll drop this patch as Gregory's fix is already on the way upstream.