Published: June 2024

Overview

A newly-resolved vulnerability, CVE-2023-52451, was found in the Linux kernel's PowerPC (pseries) platform code related to the memory hotplug (dynamic memory addition/removal) subsystem. This bug occurs when attempting to remove logical memory blocks (LMBs), which can cause the Linux kernel to read out-of-bounds memory. This flaw was exposed through KASAN (the Kernel Address SANitizer) and could theoretically be used for local denial-of-service, information leak, or worse — depending on kernel configuration and threat model.

If you’re deploying or maintaining PowerPC servers with hotplug memory, upgrading your kernel is strongly recommended. This article breaks down what went wrong, how you might exploit it, and how it is fixed.

What’s the Problem?

When the kernel removes memory by a specific DRC (Dynamic Resource Connector) index, it searches through an array (drmem_info->lmbs[]) for the right LMB. If there’s no match, the code previously left the search pointer one slot past the allocated space — then tried to dereference it in a debug print line. That means a simple failure in the lookup could lead to kernel out-of-bounds memory access.

The Problem Code (Before Patch)

The function at the center of the problem is dlpar_memory_remove_by_index(). Here’s a simplified version of the buggy snippet:

// Find the LMB by DRC index
for (i = ; i < drmem_info->n_lmbs; i++) {
    lmb = &drmem_info->lmbs[i];
    if (lmb->drc_index == target_drc_index)
        break; // Found
}

// The search failed if we exhaust the loop...
// But we still dereference lmb->base_addr
pr_debug("Failed to hot-remove memory at %llx\n", lmb->base_addr);

If no entry is found, i == drmem_info->n_lmbs, so lmb = &drmem_info->lmbs[i]; points one element past the valid array. *This is undefined behavior in C!* When the debug message prints lmb->base_addr, we access random memory.

The flaw was discovered by inspection and triggered by KASAN. Here’s part of the KASAN report

BUG: KASAN: slab-out-of-bounds in dlpar_memory+x298/x1658
Read of size 8 at addr c000000364e97fd by task bash/949

pseries-hotplug-mem: Failed to hot-remove memory at 
...
The buggy address is located  bytes to the right of
allocated 98256-byte region c000000364e80000, c000000364e97fd)

This means the kernel has tried to read exactly at the end of a drmem array allocated in the heap.

*For full log, see [commit link
.*

Exploitation: What Can an Attacker Do?

This bug is most useful as a local Denial of Service — an unprivileged user with the right sysfs access could potentially trigger it by requesting to hot-remove a non-existent LMB. On systems where powerpc memory hotplug is enabled and untrusted userspace code can access /sys/firmware/memmap/* or related sysfs interfaces, this could cause:

In rare cases, corruption of adjacent kernel heap objects.

Proof-of-Concept:

You could trigger the bug by simply echoing an invalid DRC index into the right sysfs file

echo invalid_drc_index > /sys/firmware/memory/remove

*(Note: Actual sysfs paths may vary by platform and kernel version. Test carefully in a VM!)*

In code, this is roughly what would happen inside the kernel

int remove_memory_by_drc(u32 drc_index) {
    struct drmem_lmb *lmb = NULL;
    int i;
    for (i = ; i < drmem_info->n_lmbs; i++) {
        lmb = &drmem_info->lmbs[i];
        if (lmb->drc_index == drc_index)
            break;
    }
    // If not found, lmb points past the array!
    pr_debug("Failed to hot-remove memory at %llx\n", lmb->base_addr);
}

The Official Fix

The kernel fix is simple and effective:
Log the failure with a different message, and only dereference lmb if it actually points to a valid entry.

From the official patch:

if (found) {
    pr_debug("Hot-removed memory at %llx\n", lmb->base_addr);
} else {
    pr_debug("Failed to find LMB for hot-remove, DRC index %x\n", drc_index);
}

This avoids any out-of-bounds access, regardless of what is provided by userspace.

Security Takeaways

- Memory hotplug code is security-sensitive, as off-by-one errors can easily lead to kernel memory corruptions.

Even a debug print statement can introduce a dangerous bug in kernel C code.

- Use security tools like KASAN for kernel debugging — this caught the bug before exploitation in the wild.

References

- CVE Record at Mitre
- Upstream kernel fix commit
- Linux kernel mailing list report
- KASAN documentation

Conclusion

CVE-2023-52451 is a nasty little example of how a small oversight in C pointer arithmetic — especially in array traversals — can have serious consequences in the Linux kernel. If you rely on PowerPC hotplug features, patch promptly. And if you’re developing kernel code, always double-check pointer bounds before dereferencing.

Timeline

Published on: 02/22/2024 17:15:08 UTC
Last modified on: 03/18/2024 18:33:31 UTC