On Sat,  3 Oct 2026 19:30:28 +0900 Donggeun Yoo <[email protected]> 
wrote:

> 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.

Thanks, I updated mm-hotfixes-unstable with this version.

> Changes in v4:
>  - patch 1: add Acked-by from David Hildenbrand and Mike Rapoport; no
>    code change
>  - patch 2: protect the source right after registering it, open pagemap
>    at the top, and use a designated initializer for the move (David
>    Hildenbrand)
>  - patch 2: fail only the test case, not the whole run, when UFFDIO_MOVE
>    fails (David Hildenbrand)

Here's how v4 altered mm.git:


 tools/testing/selftests/mm/uffd-unit-tests.c |   36 ++++++++---------
 1 file changed, 18 insertions(+), 18 deletions(-)

--- a/tools/testing/selftests/mm/uffd-unit-tests.c~b
+++ a/tools/testing/selftests/mm/uffd-unit-tests.c
@@ -2049,28 +2049,29 @@ static void uffd_move_swap_test_common(u
                                       bool rwp)
 {
        unsigned long page_size = gopts->page_size;
-       struct uffdio_move move = { };
-       int pagemap_fd;
+       struct uffdio_move move = {
+               .dst = (unsigned long)gopts->area_dst,
+               .src = (unsigned long)gopts->area_src,
+               .len = page_size,
+       };
+       int pagemap_fd = pagemap_open();
 
        if (rwp) {
                if (uffd_register_rwp(gopts->uffd, gopts->area_src, page_size))
                        err("register src failure");
-       } else if (uffd_register(gopts->uffd, gopts->area_src, page_size,
-                                false, true, false)) {
-               err("register src failure");
-       }
-       if (uffd_register(gopts->uffd, gopts->area_dst, page_size,
-                         true, false, false))
-               err("register dst failure");
-
-       if (rwp)
                rwprotect_range(gopts->uffd, (unsigned long)gopts->area_src,
                                page_size, true);
-       else
+       } else {
+               if (uffd_register(gopts->uffd, gopts->area_src, page_size,
+                                 false, true, false))
+                       err("register src failure");
                wp_range(gopts->uffd, (unsigned long)gopts->area_src,
                         page_size, true);
+       }
+       if (uffd_register(gopts->uffd, gopts->area_dst, page_size,
+                         true, false, false))
+               err("register dst failure");
 
-       pagemap_fd = pagemap_open();
        if (madvise(gopts->area_src, page_size, MADV_PAGEOUT))
                err("MADV_PAGEOUT");
        if (!pagemap_is_swapped(pagemap_fd, gopts->area_src)) {
@@ -2078,11 +2079,10 @@ static void uffd_move_swap_test_common(u
                goto out;
        }
 
-       move.dst = (unsigned long)gopts->area_dst;
-       move.src = (unsigned long)gopts->area_src;
-       move.len = page_size;
-       if (ioctl(gopts->uffd, UFFDIO_MOVE, &move))
-               err("UFFDIO_MOVE");
+       if (ioctl(gopts->uffd, UFFDIO_MOVE, &move)) {
+               uffd_test_fail("UFFDIO_MOVE failed: %s", strerror(errno));
+               goto out;
+       }
 
        if (pagemap_get_entry(pagemap_fd, gopts->area_dst) & PM_UFFD_WP)
                uffd_test_fail("uffd bit moved into an area registered for 
missing faults only");
_


Reply via email to