From: sashiko-bot@kernel.org
To: "Gregory Price" <gourry@gourry.net>
Cc: linux-cxl@vger.kernel.org
Subject: Re: [PATCH v4 8/9] dax/kmem: add sysfs interface for atomic hotplug
Date: Fri, 05 Jun 2026 21:37:58 +0000 [thread overview]
Message-ID: <20260605213759.2B75F1F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260605211911.2160954-9-gourry@gourry.net>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Unbinding the device while memory is online causes a use-after-free of `data->res_name` and incorrectly clears the node memory type.
- [High] `dax_kmem_do_hotplug()` unconditionally adds memory regions to the system even if their physical address reservations failed.
- [Low] Lockless access to `data->state` in `hotplug_show` can race with concurrent updates.
--
commit 3599d063a2c3d29c40b1495050182e1083f34ccd
Author: Gregory Price <gourry@gourry.net>
dax/kmem: add sysfs interface for atomic hotplug
The dax kmem driver currently onlines memory automatically during
probe using the system's default online policy but provides no way
to control or query the entire region state at runtime.
This commit adds a 'hotplug' sysfs attribute allowing userspace to
control and query the entire memory region state. Unplug operations are
now atomic across the whole device.
> diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
> index 5bf36ab73f867..46ee06d9f56b3 100644
> --- a/drivers/dax/kmem.c
> +++ b/drivers/dax/kmem.c
[ ... ]
> @@ -63,23 +69,41 @@ static void kmem_put_memory_types(void)
> mt_put_memory_types(&kmem_memory_types);
> }
>
> +/* True for the online states a kmem dax device can hold. */
> +static bool dax_kmem_state_is_online(int state)
> +{
> + return state == MMOP_ONLINE ||
> + state == MMOP_ONLINE_KERNEL ||
> + state == MMOP_ONLINE_MOVABLE;
> +}
> +
> /**
> - * dax_kmem_do_hotplug - hotplug memory for dax kmem device
> + * dax_kmem_do_hotplug - add the dev_dax memory ranges as system memory
> * @dev_dax: the dev_dax instance
> * @data: the dax_kmem_data structure with resource tracking
> + * @online_type: MMOP_OFFLINE to add the blocks offline, otherwise the online
> + * state (MMOP_ONLINE, MMOP_ONLINE_KERNEL, MMOP_ONLINE_MOVABLE)
> + * to bring them online in.
> *
> - * Hotplugs all ranges in the dev_dax region as system memory.
> + * Adds all ranges in the dev_dax region as system memory, onlining them in
> + * the requested zone unless @online_type is MMOP_OFFLINE.
> *
> - * Returns the number of successfully mapped ranges, or negative error.
> */
> static int dax_kmem_do_hotplug(struct dev_dax *dev_dax,
> struct dax_kmem_data *data,
> int online_type)
> {
> struct device *dev = &dev_dax->dev;
> - int i, rc, onlined = 0;
> + int i, rc, added = 0;
> mhp_t mhp_flags;
>
> + if (dax_kmem_state_is_online(data->state))
> + return -EINVAL;
> +
> + if (online_type < MMOP_OFFLINE || online_type > MMOP_ONLINE_MOVABLE)
> + return -EINVAL;
> +
> for (i = 0; i < dev_dax->nr_range; i++) {
> struct range range;
>
> @@ -88,10 +112,10 @@ static int dax_kmem_do_hotplug(struct dev_dax *dev_dax,
> if (rc)
> continue;
>
> mhp_flags = MHP_NID_IS_MGID;
> if (dev_dax->memmap_on_memory)
> mhp_flags |= MHP_MEMMAP_ON_MEMORY;
>
> /*
> * Ensure that future kexec'd kernels will not treat
> * this as RAM automatically.
> */
> rc = __add_memory_driver_managed(data->mgid, range.start,
> range_len(&range), kmem_name, mhp_flags,
> online_type);
[Severity: High]
Does this code unconditionally add memory regions to the system even if their
physical address reservations failed?
If `request_mem_region()` fails in `dax_kmem_init_resources()`, it skips
reserving the region (leaving `data->res[i] = NULL`), but continues the loop
if previous ranges succeeded.
However, `dax_kmem_do_hotplug()` iterates over all ranges and blindly calls
`__add_memory_driver_managed()` without checking if `data->res[i]` is valid.
This attempts to forcibly online unreserved physical addresses as System RAM.
If these address ranges overlap with active MMIO or firmware regions, could
this lead to severe system stability issues and memory corruption?
[ ... ]
> +static ssize_t hotplug_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct dax_kmem_data *data = dev_get_drvdata(dev);
> + const char *state_str;
> +
> + if (!data)
> + return -ENXIO;
> +
> + switch (data->state) {
[Severity: Low]
Does this lockless read of `data->state` race with concurrent updates?
`hotplug_show()` reads `data->state` locklessly to return the current state
string to userspace. Concurrently, `hotplug_store()` modifies `data->state`
while holding `data->lock`.
Should this be protected by the lock, or properly annotated with
`READ_ONCE()`/`WRITE_ONCE()` to prevent compiler tearing?
> + case DAX_KMEM_UNPLUGGED:
> + state_str = "unplugged";
> + break;
[ ... ]
> @@ -345,23 +516,20 @@ static int dev_dax_kmem_probe(struct dev_dax *dev_dax)
> #ifdef CONFIG_MEMORY_HOTREMOVE
> static void dev_dax_kmem_remove(struct dev_dax *dev_dax)
> {
> - int success;
> int node = dev_dax->target_node;
> struct device *dev = &dev_dax->dev;
> struct dax_kmem_data *data = dev_get_drvdata(dev);
>
> + device_remove_file(dev, &dev_attr_hotplug);
> /*
> - * We have one shot for removing memory, if some memory blocks were not
> - * offline prior to calling this function remove_memory() will fail, and
> - * there is no way to hotremove this memory until reboot because device
> - * unbind will succeed even if we return failure.
> + * Blocks added under the legacy offline policy are present but offline;
> + * remove them on unbind as the driver always has. If removal fails,
> + * leak the resources rather than freeing state that still backs present
> + * memory. Online memory is left alone (dax_kmem_cleanup_resources()
> + * warns and leaks it) since offlining it here could deadlock the unbind.
> */
> - success = dax_kmem_do_hotremove(dev_dax, data);
> - if (success < dev_dax->nr_range) {
> - dev_err(dev, "Hotplug regions stuck online until reboot\n");
> + if (data->state == MMOP_OFFLINE && dax_kmem_do_hotremove(dev_dax, data))
> return;
> - }
> -
> dax_kmem_cleanup_resources(dev_dax, data);
> memory_group_unregister(data->mgid);
> kfree(data->res_name);
[Severity: High]
Can unbinding the device while memory is online cause a use-after-free
of `data->res_name` and incorrectly clear the node memory type?
When `data->state != MMOP_OFFLINE`, `dev_dax_kmem_remove()` skips
`dax_kmem_do_hotremove()` and calls `dax_kmem_cleanup_resources()`.
`dax_kmem_cleanup_resources()` intentionally warns and returns early to leave
the `struct resource` objects active to prevent unbind deadlocks.
However, `dev_dax_kmem_remove()` unconditionally proceeds to call
`kfree(data->res_name)` and `kfree(data)`. Since the leaked `struct resource`
objects' name fields still point to `data->res_name`, will any subsequent
read of `/proc/iomem` trigger a KASAN Use-After-Free?
Additionally, does the unconditional continuation improperly call
`clear_node_memory_type()`, corrupting the memtype association while the
memory blocks are still active?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605211911.2160954-1-gourry@gourry.net?part=8
next prev parent reply other threads:[~2026-06-05 21:37 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 21:19 [PATCH v4 0/9] dax/kmem: atomic whole-device hotplug via sysfs Gregory Price
2026-06-05 21:19 ` [PATCH v4 1/9] mm/memory: add memory_block_aligned_range() helper Gregory Price
2026-06-09 9:50 ` David Hildenbrand (Arm)
2026-06-05 21:19 ` [PATCH v4 2/9] mm/memory_hotplug: pass online_type to online_memory_block() via arg Gregory Price
2026-06-05 21:19 ` [PATCH v4 3/9] mm/memory_hotplug: export mhp_get_default_online_type Gregory Price
2026-06-05 21:29 ` sashiko-bot
2026-06-05 21:43 ` Gregory Price
2026-06-09 9:52 ` David Hildenbrand (Arm)
2026-06-09 15:11 ` Gregory Price
2026-06-05 21:19 ` [PATCH v4 4/9] mm/memory_hotplug: add __add_memory_driver_managed() with online_type arg Gregory Price
2026-06-09 9:55 ` David Hildenbrand (Arm)
2026-06-09 15:12 ` Gregory Price
2026-06-05 21:19 ` [PATCH v4 5/9] mm/memory_hotplug: add multi-range hotunplug Gregory Price
2026-06-05 21:30 ` sashiko-bot
2026-06-09 10:06 ` David Hildenbrand (Arm)
2026-06-09 15:15 ` Gregory Price
2026-06-05 21:19 ` [PATCH v4 6/9] dax: plumb hotplug online_type through dax Gregory Price
2026-06-05 21:31 ` sashiko-bot
2026-06-05 21:54 ` Gregory Price
2026-06-09 10:21 ` David Hildenbrand (Arm)
2026-06-09 15:33 ` Gregory Price
2026-06-05 21:19 ` [PATCH v4 7/9] dax/kmem: extract hotplug/hotremove helper functions Gregory Price
2026-06-05 21:36 ` sashiko-bot
2026-06-05 22:03 ` Gregory Price
2026-06-05 21:19 ` [PATCH v4 8/9] dax/kmem: add sysfs interface for atomic hotplug Gregory Price
2026-06-05 21:37 ` sashiko-bot [this message]
2026-06-09 10:26 ` David Hildenbrand (Arm)
2026-06-09 15:35 ` Gregory Price
2026-06-09 18:11 ` David Hildenbrand (Arm)
2026-06-09 18:19 ` Gregory Price
2026-06-09 18:22 ` David Hildenbrand (Arm)
2026-06-09 18:33 ` Gregory Price
2026-06-05 21:19 ` [PATCH v4 9/9] selftests/dax: add dax/kmem hotplug sysfs regression test Gregory Price
2026-06-05 21:34 ` sashiko-bot
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=20260605213759.2B75F1F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=gourry@gourry.net \
--cc=linux-cxl@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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.