UFFDIO_MOVE on a swapped-out page installs the source PTE at the destination unchanged, so a uffd bit set on a write-protected or RWP-protected source lands in a destination VMA that was never registered for either, and nothing clears it afterwards. Patch 1 clears the bit, then re-arms it if the destination is RWP-registered, which is what the present-page and zeropage move paths already do. Patch 2 adds the tests that catch it.
v1: https://lore.kernel.org/all/[email protected]/ v2: https://lore.kernel.org/all/[email protected]/ Changes in v3: - patch 1: describe the userspace-visible effects and the backport (Andrew Morton, David Hildenbrand) - patch 2: drop the MADV_PAGEOUT retry loop (David Hildenbrand) - patch 2: add an RWP case (David Hildenbrand) Changes in v2: - patch 1: clear the bit unconditionally (Kiryl Shutsemau) - patch 1: rewrite the changelog for readability (Mike Rapoport) - add Assisted-by: LLM (Mike Rapoport) x86_64 defconfig plus USERFAULTFD, TRANSPARENT_HUGEPAGE, PAGE_TABLE_CHECK_ENFORCED and a swap device, under QEMU, on 6812ce4e4379: uffd-unit-tests before after move-swap-wp on anon not ok ok move-swap-rwp on anon not ok ok the other 103 unit tests ok ok uffd-wp-mremap, 38 tests ok ok 11 unit tests skip on both, as CONFIG_GUP_TEST is not set. pagemap bit 57 at the destination before after swapped page, dst not armed set clear swapped page, dst WP-armed set clear swapped page, dst RWP-armed set set resident page, dst WP-armed clear clear MADV_COLLAPSE over 2 MB at dst EINVAL 0 fault on the moved page at dst WARNING none Donggeun Yoo (2): userfaultfd: clear the inherited uffd bit in move_swap_pte() selftests/mm: add tests for UFFDIO_MOVE of a uffd-protected swap entry mm/userfaultfd.c | 1 + tools/testing/selftests/mm/uffd-unit-tests.c | 84 ++++++++++++++++++++ 2 files changed, 85 insertions(+) -- 2.53.0

