Re: [PATCH v5 04/36] numa: introduce N_MEMORY_PRIVATE
[email protected] Tue, 21 Jul 2026 18:18:13 +0000
| Newsgroups | dev.linux.lists.nvdimm,dev.linux.lists.damon,org.kernel.vger.kvm,org.kernel.vger.linux-cxl |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] Missing bounds validation on `nid` in `node_private_register()` and `node_private_unregister()` leads to out-of-bounds reads. - [Medium] Lockless read of an `__rcu` pointer in `pgdat_is_private()` without using `rcu_access_pointer()`. -- --- Patch [4]: [PATCH v5 04/36] numa: introduce N_MEMORY_PRIVATE --- commit 69b3cbf2395b52c525233c59376e585ae83c3f31 Author: Gregory Price <[email protected]> numa: introduce N_MEMORY_PRIVATE Some devices want to hotplug their memory onto a node, but not have it exposed as "general purpose". This commit adds basic infrastructure for N_MEMORY_PRIVATE nodes, intended for memory isolated from the page allocator's normal and fallback zonelists. > diff --git a/drivers/base/node.c b/drivers/base/node.c > index 3da91929ad4e3..94cd51f51b7e8 100644 > --- a/drivers/base/node.c > +++ b/drivers/base/node.c [ ... ] > @@ -868,6 +869,116 @@ void register_memory_blocks_under_node_hotplug(int nid, unsigned long start_pfn, > (void *)&nid, register_mem_block_under_node_hotplug); > return; > } > + > +static DEFINE_MUTEX(node_private_lock); > + > +/** > + * node_private_register - Register a private node > + * @nid: Node identifier [ ... ] > + */ > +int node_private_register(int nid, struct node_private *np) > +{ > + struct node_private *existing; > + pg_data_t *pgdat; > + int ret = 0; > + > + if (!np || !node_possible(nid)) > + return -EINVAL; [Severity: Medium] Could this lead to an out-of-bounds read if a driver passes an invalid nid like NUMA_NO_NODE (-1)? node_possible() and NODE_DATA() do not perform bounds checking internally. Should we verify nid >= 0 && nid < MAX_NUMNODES before using it? > + > + mutex_lock(&node_private_lock); > + mem_hotplug_begin(); > + > + /* N_MEMORY_PRIVATE and N_MEMORY are mutually exclusive */ > + if (node_state(nid, N_MEMORY)) { > + ret = -EBUSY; > + goto out; > + } > + > + pgdat = NODE_DATA(nid); [ ... ] > +/** > + * node_private_unregister - Unregister a private node > + * @nid: Node identifier [ ... ] > + */ > +int node_private_unregister(int nid) > +{ > + struct node_private *np; > + pg_data_t *pgdat; > + > + if (!node_possible(nid)) > + return 0; [Severity: Medium] Is it possible for a driver to pass NUMA_NO_NODE here as well, leading to the same out-of-bounds read issue when node_possible() and NODE_DATA() are evaluated? > + > + mutex_lock(&node_private_lock); > + mem_hotplug_begin(); > + > + pgdat = NODE_DATA(nid); [ ... ] > diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h > index 0507193b3ae34..9815e48c03b97 100644 > --- a/include/linux/mmzone.h > +++ b/include/linux/mmzone.h [ ... ] > @@ -1596,12 +1598,25 @@ typedef struct pglist_data { > atomic_long_t vm_stat[NR_VM_NODE_STAT_ITEMS]; > #ifdef CONFIG_NUMA > struct memory_tier __rcu *memtier; > + struct node_private __rcu *node_private; > #endif > #ifdef CONFIG_MEMORY_FAILURE > struct memory_failure_stats mf_stats; > #endif > } pg_data_t; > > +#ifdef CONFIG_NUMA > +static inline bool pgdat_is_private(pg_data_t *pgdat) > +{ > + return !!pgdat->node_private; [Severity: Medium] Does this lockless read of the __rcu pointer require rcu_access_pointer()? Without it, sparse will likely complain about an __rcu address space violation, and we might be missing the READ_ONCE() barrier that prevents compiler load tearing. > +} > +#else > +static inline bool pgdat_is_private(pg_data_t *pgdat) > +{ > + return false; > +} > +#endif -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=4