* [BUG] mm/ksm: KSM merge drops userfaultfd RWP markers
@ 2026-10-20 11:07 shaos
2026-10-20 12:59 ` David Hildenbrand (Arm)
0 siblings, 1 reply; 2+ messages in thread
From: shaos @ 2026-10-20 11:07 UTC (permalink / raw)
To: akpm; +Cc: David Hildenbrand, linux-mm, linux-kernel
Hello,
KSM can merge anonymous pages in a VMA registered for userfaultfd write-protect (RWP), then replace an armed PTE with an ordinary accessible PTE. The VMA remains registered, but a read of the replaced page completes without the expected UFFD_PAGEFAULT_FLAG_RWP event.
The RWP PTE is represented by PAGE_NONE plus the architecture's _PAGE_UFFD marker. In replace_page(), KSM creates the replacement with mk_pte(kpage, vma->vm_page_prot) and does not preserve that state from orig_pte. The PoC observes pages_sharing increase, reads the replaced page without an event, then re-arms it and receives the RWP event again. A non-merging control keeps the marker and continues to fault.
The same replacement path also loses soft-dirty state; that separate observable is documented at https://gist.github.com/shaos26/9db36768f01eb83c6aa14ee9fc057388. This report focuses on userfaultfd RWP tracking.
HEAD commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
source version: Linux 7.3.0-rc7
architecture: x86-64
compiler: gcc 11.4.0, GNU ld 2.38
QEMU: 6.2.0
console output: https://gist.githubusercontent.com/shaos26/e887665d7868dc323d73a1d678cacd3d/raw/e3e39212903e5bd5ba12f55a94ba7ae5b25bb238/console-output.txt
kernel config: https://gist.githubusercontent.com/shaos26/e887665d7868dc323d73a1d678cacd3d/raw/3cd943ba8c6026b43ef016a37d07efd2533a317a/kernel-config.txt
reproducer: https://gist.githubusercontent.com/shaos26/e887665d7868dc323d73a1d678cacd3d/raw/7fc8685bb0cc01fca488fc096d4859b8b70af3fc/poc.c
Build the kernel from the revision above with the attached config. Build the static PoC with:
gcc -static -O2 -pthread -Wall -Wextra -o poc poc.c
The program is intended to run as /init in a disposable initramfs and mounts procfs and sysfs itself. Boot it with:
qemu-system-x86_64 -m 1G -smp 2 -machine q35 -nographic -no-reboot \
-kernel build/arch/x86/boot/bzImage -initrd initramfs.cpio.gz \
-append "console=ttyS0 rdinit=/init panic=-1 oops=panic loglevel=6"
Two fresh positive boots reported RESULT=KSM_RWP_MARKER_LOSS_CONFIRMED; the close non-merging control reported RESULT=KSM_CONTROL_TRAPS_PRESERVED. No privilege escalation, memory corruption, or cross-process access is claimed; the defect is loss of the caller's RWP access tracking. I checked the affected code against upstream master f47d223627f8; this source path appears unchanged there, but I have only reproduced the behavior on v7.3-rc7.
Thanks,
shaos
^ permalink raw reply [flat|nested] 2+ messages in thread* Re: [BUG] mm/ksm: KSM merge drops userfaultfd RWP markers
2026-10-20 11:07 [BUG] mm/ksm: KSM merge drops userfaultfd RWP markers shaos
@ 2026-10-20 12:59 ` David Hildenbrand (Arm)
0 siblings, 0 replies; 2+ messages in thread
From: David Hildenbrand (Arm) @ 2026-10-20 12:59 UTC (permalink / raw)
To: shaos, akpm; +Cc: linux-mm, linux-kernel
On 10/20/26 13:07, shaos wrote:
> Hello,
>
> KSM can merge anonymous pages in a VMA registered for userfaultfd write-protect (RWP), then replace an armed PTE with an ordinary accessible PTE. The VMA remains registered, but a read of the replaced page completes without the expected UFFD_PAGEFAULT_FLAG_RWP event.
>
> The RWP PTE is represented by PAGE_NONE plus the architecture's _PAGE_UFFD marker. In replace_page(), KSM creates the replacement with mk_pte(kpage, vma->vm_page_prot) and does not preserve that state from orig_pte. The PoC observes pages_sharing increase, reads the replaced page without an event, then re-arms it and receives the RWP event again. A non-merging control keeps the marker and continues to fault.
>
> The same replacement path also loses soft-dirty state; that separate observable is documented at https://gist.github.com/shaos26/9db36768f01eb83c6aa14ee9fc057388. This report focuses on userfaultfd RWP tracking.
>
> HEAD commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
> source version: Linux 7.3.0-rc7
> architecture: x86-64
> compiler: gcc 11.4.0, GNU ld 2.38
> QEMU: 6.2.0
>
> console output: https://gist.githubusercontent.com/shaos26/e887665d7868dc323d73a1d678cacd3d/raw/e3e39212903e5bd5ba12f55a94ba7ae5b25bb238/console-output.txt
> kernel config: https://gist.githubusercontent.com/shaos26/e887665d7868dc323d73a1d678cacd3d/raw/3cd943ba8c6026b43ef016a37d07efd2533a317a/kernel-config.txt
> reproducer: https://gist.githubusercontent.com/shaos26/e887665d7868dc323d73a1d678cacd3d/raw/7fc8685bb0cc01fca488fc096d4859b8b70af3fc/poc.c
>
> Build the kernel from the revision above with the attached config. Build the static PoC with:
>
> gcc -static -O2 -pthread -Wall -Wextra -o poc poc.c
>
> The program is intended to run as /init in a disposable initramfs and mounts procfs and sysfs itself. Boot it with:
>
> qemu-system-x86_64 -m 1G -smp 2 -machine q35 -nographic -no-reboot \
> -kernel build/arch/x86/boot/bzImage -initrd initramfs.cpio.gz \
> -append "console=ttyS0 rdinit=/init panic=-1 oops=panic loglevel=6"
>
> Two fresh positive boots reported RESULT=KSM_RWP_MARKER_LOSS_CONFIRMED; the close non-merging control reported RESULT=KSM_CONTROL_TRAPS_PRESERVED. No privilege escalation, memory corruption, or cross-process access is claimed; the defect is loss of the caller's RWP access tracking. I checked the affected code against upstream master f47d223627f8; this source path appears unchanged there, but I have only reproduced the behavior on v7.3-rc7.
>
> Thanks,
>
> shaos
>
Always a good idea to look at the list before posting stuff.
https://lore.kernel.org/all/20261019010934.697895-1-samarth.colleges@gmail.com/
--
Cheers,
David
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-20 12:59 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-20 11:07 [BUG] mm/ksm: KSM merge drops userfaultfd RWP markers shaos
2026-10-20 12:59 ` David Hildenbrand (Arm)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®