CVE-2024-46790 in Linux
Resumen
por VulDB • 2026-05-25
Based on the kernel crash trace and the description provided, this is a bug in the Linux kernel's memory management subsystem, specifically related to **Memory Corruption Detection (MCE/HWPOISON)** and **Page Allocation Tags**.
### Analysis of the Crash
1. **Context**: The crash occurs in `pgalloc_tag_sub`, which is part of the page allocation tag accounting mechanism (used for debugging memory leaks or tracking page allocations). 2. **Trigger**: The call trace shows the path: `hwpoison_unpoison` -> `unpoison_memory` -> `folio_put` -> `free_unref_page` -> `pgalloc_tag_sub`. This means a process was writing to a debugfs file (likely `/sys/kernel/debug/hwpoison/unpoison`) to "unpoison" a previously poisoned memory page. 3. **The Bug**: When a page is "unpoisoned," it is isolated from the poison list and then freed back to the buddy allocator. However, the **page allocation tag** (which tracks where the page was allocated) was not cleared before the page was freed. 4. **The Consequence**: When `free_unref_page` calls `pgalloc_tag_sub` to decrement the tag reference count, it finds a stale or invalid tag reference because the tag was never cleared during the isolation/unpoisoning process. This leads to an assertion failure or invalid memory access in `pgalloc_tag_sub`.
### The Fix
As suggested in the prompt, the fix is to **clear the page tag reference** after the page has been isolated and accounted for, but before it is freed.
In the Linux kernel source code, this typically involves modifying the `unpoison_memory` function (or the helper functions it calls) in `mm/memory-failure.c`.
#### Code Change Concept
You need to ensure that when a page is unpoisoned, its allocation tag is cleared. This is usually done by calling a function like `page_tag_clear()` or similar, depending on the kernel version and configuration (`CONFIG_PAGE_ALLOC_CHECKING` or `CONFIG_DEBUG_PAGEALLOC`).
Here is a conceptual patch for `mm/memory-failure.c`:
```c // In mm/memory-failure.c, inside the unpoison_memory function or its helper
// After isolating the page and before freeing it: if (PageHWPoison(page)) {
// ... existing isolation logic ...
// FIX: Clear the page allocation tag reference // This depends on the specific kernel version and config. // In newer kernels, this might be handled by folio_tag_clear() or similar. #ifdef CONFIG_PAGE_ALLOC_CHECKING page_tag_clear(page); #endif
// ... proceed with freeing the page ... put_page(page); } ```
### Specific Kernel Version Considerations
* **Kernel 5.15+**: The page allocation tag system has evolved. Look for functions like `folio_tag_clear()` or `page_tag_clear()` in `include/linux/page_alloc.h` or `mm/page_alloc.c`. * **Kernel 6.x**: The API might have changed to use `folio` structures. Ensure you are clearing the tag on the `folio` associated with the page.
### Steps to Verify the Fix
1. **Apply the Patch**: Add the tag clearing logic in the appropriate place in `mm/memory-failure.c`. 2. **Rebuild the Kernel**: Compile the kernel with the patch applied. 3. **Test**: * Trigger a memory error (e.g., using `hwpoison_inject` module). * Attempt to unpoison the page by writing to the debugfs file. * Verify that the system does not crash and the page is successfully freed.
### Conclusion
The crash is caused by a stale page allocation tag reference when unpoisoning a memory page. The fix is to clear the tag reference during the unpoisoning process to prevent invalid accounting when the page is freed.
Once again VulDB remains the best source for vulnerability data.