From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Ruipeng Qi <ruipengqi3@gmail.com>, Kees Cook <kees@kernel.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH AUTOSEL 6.19-5.10] pstore: ram_core: fix incorrect success return when vmap() fails
Date: Wed, 11 Feb 2026 20:09:42 -0500 [thread overview]
Message-ID: <20260212010955.3480391-19-sashal@kernel.org> (raw)
In-Reply-To: <20260212010955.3480391-1-sashal@kernel.org>
From: Ruipeng Qi <ruipengqi3@gmail.com>
[ Upstream commit 05363abc7625cf18c96e67f50673cd07f11da5e9 ]
In persistent_ram_vmap(), vmap() may return NULL on failure.
If offset is non-zero, adding offset_in_page(start) causes the function
to return a non-NULL pointer even though the mapping failed.
persistent_ram_buffer_map() therefore incorrectly returns success.
Subsequent access to prz->buffer may dereference an invalid address
and cause crashes.
Add proper NULL checking for vmap() failures.
Signed-off-by: Ruipeng Qi <ruipengqi3@gmail.com>
Link: https://patch.msgid.link/20260203020358.3315299-1-ruipengqi3@gmail.com
Signed-off-by: Kees Cook <kees@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
Now I have all the information needed for a thorough analysis. Let me
summarize my findings.
---
## Detailed Analysis
### 1. COMMIT MESSAGE ANALYSIS
The commit subject is explicit: "fix incorrect success return when
vmap() fails". The message clearly explains the bug mechanism:
- `vmap()` may return NULL on failure
- When `offset_in_page(start)` is non-zero, adding it to NULL produces a
non-NULL pointer
- The caller `persistent_ram_buffer_map()` checks `if (!prz->vaddr)`,
which passes because the returned pointer is non-NULL (e.g., `0x100`)
- Subsequent access to `prz->buffer` dereferences an invalid address,
causing a **kernel crash**
The commit is signed off by Kees Cook, the pstore subsystem maintainer,
indicating proper review.
### 2. CODE CHANGE ANALYSIS
The fix is exactly **7 lines added** (4 lines of comment + 2 lines of
code + 1 blank line) to a single file:
```449:455:fs/pstore/ram_core.c
/*
- vmap() may fail and return NULL. Do not add the offset in this
- case, otherwise a NULL mapping would appear successful.
*/
if (!vaddr)
return NULL;
```
**Bug mechanism in detail:**
In `persistent_ram_vmap()` (line 403-455), the function maps physical
pages via `vmap()`, then returns the virtual address with a sub-page
offset added:
```454:454:fs/pstore/ram_core.c
return vaddr + offset_in_page(start);
```
When `vmap()` returns NULL (memory pressure, vmalloc space exhaustion),
and `offset_in_page(start)` is non-zero (the physical `start` address is
not page-aligned), the return value becomes `NULL + offset` = a small
non-zero invalid pointer.
The caller `persistent_ram_buffer_map()` has a NULL check at line 494:
```494:500:fs/pstore/ram_core.c
if (!prz->vaddr) {
pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n",
__func__,
(unsigned long long)size, (unsigned long
long)start);
return -ENOMEM;
}
prz->buffer = prz->vaddr;
```
This check passes (the pointer is non-NULL but invalid), so
`prz->buffer` is set to the invalid address. Then
`persistent_ram_post_init()` immediately dereferences it at line 520:
```520:520:fs/pstore/ram_core.c
if (prz->buffer->sig == sig) {
```
This dereferences `prz->buffer->sig` at the invalid address, causing a
**kernel crash/oops**.
### 3. BUG ORIGIN
The bug was introduced by commit `831b624df1b420` ("pstore: Fix
incorrect persistent ram buffer mapping") from September 2018. That
commit moved the `offset_in_page(start)` addition from
`persistent_ram_buffer_map()` into `persistent_ram_vmap()` to fix a
different bug (double-offset), but neglected to add a NULL check before
the offset addition. This means the bug has existed since **kernel
v4.19** and affects ALL currently supported stable kernels (5.4.y,
5.10.y, 5.15.y, 6.1.y, 6.6.y, 6.12.y).
### 4. CLASSIFICATION
This is a clear **NULL pointer dereference / invalid pointer dereference
bug fix**. The consequence is a kernel crash. It falls squarely into the
category of "fixes crashes, panics, oopses."
### 5. SCOPE AND RISK ASSESSMENT
- **Lines changed:** 7 lines added, 0 lines modified, 0 lines removed
- **Files changed:** 1 (`fs/pstore/ram_core.c`)
- **Complexity:** Trivially simple - a NULL check before pointer
arithmetic
- **Risk of regression:** Essentially zero. The fix adds an early return
on an error path that was previously incorrectly handled. It cannot
break any correct behavior.
- **Subsystem:** pstore/ramoops - used for preserving kernel crash logs
across reboots, important for debugging and production systems
### 6. USER IMPACT
- **Who is affected:** Any system using pstore/ramoops with a non-page-
aligned persistent RAM region where `vmap()` fails (memory pressure,
vmalloc space exhaustion)
- **Severity:** Kernel crash/oops - HIGH. The system crashes instead of
gracefully handling the mapping failure
- **Practical trigger:** When ramoops is configured (common on
embedded/Android/IoT), if the reserved memory region is not page-
aligned AND vmalloc space is low or fragmented, `vmap()` fails and the
kernel crashes
- **pstore's importance:** pstore is widely used on Android devices,
embedded systems, and enterprise servers for crash diagnostics
### 7. STABILITY INDICATORS
- Signed off by **Kees Cook**, the pstore maintainer - high trust
- The fix is obviously correct by inspection
- The pattern (NULL check before pointer arithmetic) is a well-
established defensive programming practice
### 8. DEPENDENCY CHECK
- **No dependencies.** This is a completely self-contained fix
- The affected code (`persistent_ram_vmap()` with `return vaddr +
offset_in_page(start)`) exists identically in all stable trees since
v4.19
- The fix applies cleanly - no surrounding code context has changed
### 9. MEETS STABLE CRITERIA
| Criterion | Met? |
|-----------|------|
| Obviously correct and tested | YES - trivial NULL check |
| Fixes a real bug | YES - kernel crash |
| Important issue (crash) | YES |
| Small and contained | YES - 7 lines, 1 file |
| No new features | YES |
| No new APIs | YES |
**YES**
fs/pstore/ram_core.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index f1848cdd6d348..f8b9b47e8b244 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -446,6 +446,13 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
vaddr = vmap(pages, page_count, VM_MAP | VM_IOREMAP, prot);
kfree(pages);
+ /*
+ * vmap() may fail and return NULL. Do not add the offset in this
+ * case, otherwise a NULL mapping would appear successful.
+ */
+ if (!vaddr)
+ return NULL;
+
/*
* Since vmap() uses page granularity, we must add the offset
* into the page here, to get the byte granularity address
--
2.51.0
next prev parent reply other threads:[~2026-02-12 1:10 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-12 1:09 [PATCH AUTOSEL 6.19-5.10] clocksource/drivers/sh_tmu: Always leave device running after probe Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] gendwarfksyms: Fix build on 32-bit hosts Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] arm64/ftrace,bpf: Fix partial regs after bpf_prog_run Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] bpftool: Fix dependencies for static build Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.12] perf/x86/msr: Add Airmont NP Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] genirq/cpuhotplug: Notify about affinity changes breaking the affinity mask Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-5.15] char: tpm: cr50: Remove IRQF_ONESHOT Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.6] crypto: hisilicon/qm - move the barrier before writing to the mailbox register Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.12] sched/debug: Fix updating of ppos on server write ops Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] perf/x86/intel: Add Airmont NP Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] bpf: Properly mark live registers for indirect jumps Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-5.10] mailbox: bcm-ferxrm-mailbox: Use default primary handler Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] perf/core: Fix slow perf_event_task_exit() with LBR callstacks Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.12] perf/x86/cstate: Add Airmont NP Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-5.10] clocksource/drivers/timer-integrator-ap: Add missing Kconfig dependency on OF Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-5.10] bpf: verifier improvement in 32bit shift sign extension pattern Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.12] bpf: Recognize special arithmetic shift in the verifier Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.12] bpf: crypto: Use the correct destructor kfunc type Sasha Levin
2026-02-12 1:09 ` Sasha Levin [this message]
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] bpf: net_sched: " Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] irqchip/riscv-imsic: Add a CPU pm notifier to restore the IMSIC on exit Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.1] PCI/MSI: Unmap MSI-X region on error Sasha Levin
2026-02-12 1:09 ` [PATCH AUTOSEL 6.19-6.18] rust: sync: Implement Unpin for ARef Sasha Levin
2026-02-12 12:11 ` Miguel Ojeda
2026-02-26 13:45 ` Sasha Levin
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=20260212010955.3480391-19-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=kees@kernel.org \
--cc=patches@lists.linux.dev \
--cc=ruipengqi3@gmail.com \
--cc=stable@vger.kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox