From: Fedor Pchelkin <pchelkin@ispras.ru>
To: Harry Yoo <harry.yoo@oracle.com>,
David Hildenbrand <david@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
stable@vger.kernel.org
Cc: Fedor Pchelkin <pchelkin@ispras.ru>,
Andrew Morton <akpm@linux-foundation.org>,
Hugh Dickins <hughd@google.com>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org,
lvc-project@linuxtesting.org
Subject: [PATCH 6.1] mm/mprotect: restore pmd stability check in change_pte_range()
Date: Wed, 14 Jan 2026 21:57:45 +0300 [thread overview]
Message-ID: <20260114185746.816527-1-pchelkin@ispras.ru> (raw)
No upstream commit exists for this patch.
There is a crash which started to be observed on 6.1.y kernel after
backporting a modified version of commit 670ddd8cdcbd ("mm/mprotect:
delete pmd_none_or_clear_bad_unless_trans_huge()").
general protection fault, probably for non-canonical address 0xdffffc0000000003: 0000 [#1] PREEMPT SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000018-0x000000000000001f]
CPU: 0 PID: 23316 Comm: syz-executor.6 Not tainted 6.1.160-syzkaller-00409-g94ae58088937 #0
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
RIP: 0010:__lock_acquire+0xdc2/0x5320 kernel/locking/lockdep.c:4919
Call Trace:
<TASK>
lock_acquire kernel/locking/lockdep.c:5662 [inline]
lock_acquire+0x194/0x4b0 kernel/locking/lockdep.c:5627
__raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock+0x27/0x40 kernel/locking/spinlock.c:154
spin_lock include/linux/spinlock.h:351 [inline]
change_pte_range mm/mprotect.c:91 [inline]
change_pmd_range mm/mprotect.c:401 [inline]
change_pud_range mm/mprotect.c:432 [inline]
change_p4d_range mm/mprotect.c:453 [inline]
change_protection_range mm/mprotect.c:477 [inline]
change_protection+0xa1f/0x35e0 mm/mprotect.c:499
uffd_wp_range+0xf8/0x190 mm/userfaultfd.c:748
userfaultfd_unregister fs/userfaultfd.c:1646 [inline]
userfaultfd_ioctl+0x38a7/0x46d0 fs/userfaultfd.c:2037
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:870 [inline]
__se_sys_ioctl fs/ioctl.c:856 [inline]
__x64_sys_ioctl+0x19a/0x210 fs/ioctl.c:856
do_syscall_x64 arch/x86/entry/common.c:46 [inline]
do_syscall_64+0x35/0x80 arch/x86/entry/common.c:76
The reason is that a pmd_none entry made its way into
pte_offset_map_lock(). It crashes when USE_SPLIT_PTE_PTLOCKS is set.
It seems that pmd_trans_unstable() check shouldn't have been removed from
the 6.1.y version of the patch, restore it. Upstream code, starting with
commit 0d940a9b270b ("mm/pgtable: allow pte_offset_map[_lock]() to fail"),
has internal checks for that inside pte_offset_map_lock() itself.
Found by Linux Verification Center (linuxtesting.org) with Syzkaller.
Fixes: 670ddd8cdcbd ("mm/mprotect: delete pmd_none_or_clear_bad_unless_trans_huge()")
Signed-off-by: Fedor Pchelkin <pchelkin@ispras.ru>
---
I've tried to follow the original discussion [1] regarding the problem
this backport is supposed to solve and how it was tweaked for stable
inclusion but failed to find whether the pmd_trans_unstable() check was
dropped accidentaly (because upstream commit does remove it as well) or
there was some reasoning behind it.
The backport patch is already in 6.1.160 release so I guess the fix should
be added to 6.1.y branch directly. Looking forward for your review and
comments on the problem, thanks! I can provide .config and reproducer if
needed.
The backport patches are currently in queue for 5.10 and 5.15 kernels
inclusion so they still may be dropped from there and reworked accordingly.
[1]: https://lore.kernel.org/linux-mm/20250921232709.1608699-1-harry.yoo@oracle.com/
[2]: https://git.kernel.org/pub/scm/linux/kernel/git/stable/stable-queue.git/
mm/mprotect.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/mm/mprotect.c b/mm/mprotect.c
index f09229fbcf6c..ef6a360ec088 100644
--- a/mm/mprotect.c
+++ b/mm/mprotect.c
@@ -88,6 +88,15 @@ static long change_pte_range(struct mmu_gather *tlb,
tlb_change_page_size(tlb, PAGE_SIZE);
+ /*
+ * Can be called with only the mmap_lock for reading by
+ * prot_numa so we must check the pmd isn't constantly
+ * changing from under us from pmd_none to pmd_trans_huge
+ * and/or the other way around.
+ */
+ if (pmd_trans_unstable(pmd))
+ return 0;
+
pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
/* Make sure pmd didn't change after acquiring ptl */
_pmd = pmd_read_atomic(pmd);
--
2.51.0
reply other threads:[~2026-01-15 0:54 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20260114185746.816527-1-pchelkin@ispras.ru \
--to=pchelkin@ispras.ru \
--cc=akpm@linux-foundation.org \
--cc=david@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=harry.yoo@oracle.com \
--cc=hughd@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=lvc-project@linuxtesting.org \
--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