From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 099266FC5; Thu, 12 Feb 2026 01:10:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770858628; cv=none; b=FuC8L7y3Q9QINfnBhSYWbbqWOLQd3ShPMDMbEFhAsgHTd4WUSgOpmgb3/zK2dcVU20rhUImxA8Ann79msn2WbVNd5CGRdZU2dCRvcXf2JngT7/R6cPUQg3cJZO8q0QW0zutKMOiGL57YtWdq7J9V83qp/pTAkCWDcXItYi7BWdc= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770858628; c=relaxed/simple; bh=WNxUeTuNFXUVQA1DrmQq6BohaFxGzQljrENvmt4XfJw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IQbLfNGfRuBL+QGm5TMb2hDFEh6M5043pHNANKJWiB3HmmLvJjzRFXL2dLE5DKR/j5KTNgcGPltOkgAjNnPFfuFN+EKsk/D5lChuA2r6rlJAAVg52cdH0EnqxuL8th6hCnu0OR2XuyxRjy9UToIFg7AbpP6xFCyU+Cxhkq431bg= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J5NvKxCc; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="J5NvKxCc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3FE00C4CEF7; Thu, 12 Feb 2026 01:10:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1770858627; bh=WNxUeTuNFXUVQA1DrmQq6BohaFxGzQljrENvmt4XfJw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J5NvKxCczKA/fsG9BI1Rtfe0RoM/iA/kTSbPZx8BIK1WtD9w4teAQGe6hbaQ9JQnP u3tLEmrYrwhfcAW+VkY8Vxah8p6yOlX6rAE0rTK4uwN792S4Gw++BY7SbmSQtGMvUN phJ64tyytQh4Z97PgvZQnhIfor0tRh8E0BPdMCdQR7Y5WUyYafZetd24nDGSrxEwkm oyUGRUSzUG+xn8S+ou9P4I6VRKnQmY31ZVfa3XsLUU/BSt/gZMZ0UwqTtxKqGNJ6pa 1yxsNPvGH2CtGaG3ohrn+jPhJPclZRc5tUe/PeKVOwC7JUbWKtId742gpi5nissD4L Y619EOlj7XrgA== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Ruipeng Qi , Kees Cook , Sasha Levin 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 Message-ID: <20260212010955.3480391-19-sashal@kernel.org> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260212010955.3480391-1-sashal@kernel.org> References: <20260212010955.3480391-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.19 Content-Transfer-Encoding: 8bit From: Ruipeng Qi [ 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 Link: https://patch.msgid.link/20260203020358.3315299-1-ruipengqi3@gmail.com Signed-off-by: Kees Cook Signed-off-by: Sasha Levin --- 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