Verify that a mapping created with MAP_DROPPABLE cannot be locked
via mlock(), and that it will not be locked if it's created after
mlockall(MCL_FUTURE).

Signed-off-by: Anthony Yznaga <[email protected]>
---
 tools/testing/selftests/mm/mlock2-tests.c | 78 ++++++++++++++++++++---
 1 file changed, 69 insertions(+), 9 deletions(-)

diff --git a/tools/testing/selftests/mm/mlock2-tests.c 
b/tools/testing/selftests/mm/mlock2-tests.c
index b474f2b20def..b5790e717dd6 100644
--- a/tools/testing/selftests/mm/mlock2-tests.c
+++ b/tools/testing/selftests/mm/mlock2-tests.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #define _GNU_SOURCE
 #include <sys/mman.h>
+#include <linux/mman.h>
 #include <stdint.h>
 #include <unistd.h>
 #include <string.h>
@@ -163,14 +164,17 @@ static int lock_check(unsigned long addr)
        return (vma_rss == vma_size);
 }
 
-static int unlock_lock_check(char *map)
+static int unlock_lock_check(char *map, bool mlock_supported)
 {
-       if (is_vmflag_set((unsigned long)map, LOCKED)) {
+       if (!is_vmflag_set((unsigned long)map, LOCKED))
+               return 0;
+
+       if (mlock_supported)
                ksft_print_msg("VMA flag %s is present on page 1 after 
unlock\n", LOCKED);
-               return 1;
-       }
+       else
+               ksft_print_msg("VMA flag %s is present on an unsupported 
VMA\n", LOCKED);
 
-       return 0;
+       return 1;
 }
 
 static void test_mlock_lock(void)
@@ -196,7 +200,7 @@ static void test_mlock_lock(void)
                ksft_exit_fail_msg("munlock(): %s\n", strerror(errno));
        }
 
-       ksft_test_result(!unlock_lock_check(map), "%s: Unlocked\n", __func__);
+       ksft_test_result(!unlock_lock_check(map, true), "%s: Unlocked\n", 
__func__);
        munmap(map, 2 * page_size);
 }
 
@@ -296,7 +300,7 @@ static void test_munlockall0(void)
                ksft_exit_fail_msg("munlockall(): %s\n", strerror(errno));
        }
 
-       ksft_test_result(!unlock_lock_check(map), "%s: No locked memory\n", 
__func__);
+       ksft_test_result(!unlock_lock_check(map, true), "%s: No locked 
memory\n", __func__);
        munmap(map, 2 * page_size);
 }
 
@@ -336,7 +340,61 @@ static void test_munlockall1(void)
                ksft_exit_fail_msg("munlockall() %s\n", strerror(errno));
        }
 
-       ksft_test_result(!unlock_lock_check(map), "%s: No locked memory\n", 
__func__);
+       ksft_test_result(!unlock_lock_check(map, true), "%s: No locked 
memory\n", __func__);
+       munmap(map, 2 * page_size);
+}
+
+/*
+ * Droppable memory should not be lockable.
+ */
+static void test_mlock_droppable(void)
+{
+       char *map;
+       unsigned long page_size = getpagesize();
+
+       /*
+        * Ensure MCL_FUTURE is not set.
+        */
+       if (mlockall(MCL_CURRENT))
+               ksft_exit_fail_msg("mlockall(MCL_CURRENT): %s\n", 
strerror(errno));
+       if (munlockall())
+               ksft_exit_fail_msg("munlockall() %s\n", strerror(errno));
+
+       map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
+                  MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
+       if (map == MAP_FAILED)
+               ksft_exit_fail_msg("mmap error: %s", strerror(errno));
+
+       if (mlock2_(map, 2 * page_size, 0)) {
+               munmap(map, 2 * page_size);
+               ksft_exit_fail_msg("mlock2(0): %s\n", strerror(errno));
+       }
+
+       ksft_test_result(!unlock_lock_check(map, false), "%s: droppable memory 
not locked\n",
+                       __func__);
+
+       munmap(map, 2 * page_size);
+}
+
+static void test_mlockall_future_droppable(void)
+{
+       char *map;
+       unsigned long page_size = getpagesize();
+
+       if (mlockall(MCL_CURRENT | MCL_FUTURE))
+               ksft_exit_fail_msg("mlockall(MCL_CURRENT | MCL_FUTURE): %s\n", 
strerror(errno));
+
+       map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
+                  MAP_ANONYMOUS | MAP_DROPPABLE, -1, 0);
+
+       ksft_test_result(!unlock_lock_check(map, false), "%s: droppable memory 
not locked\n",
+                       __func__);
+
+       if (munlockall()) {
+               munmap(map, 2 * page_size);
+               ksft_exit_fail_msg("munlockall() %s\n", strerror(errno));
+       }
+
        munmap(map, 2 * page_size);
 }
 
@@ -442,7 +500,7 @@ int main(int argc, char **argv)
 
        munmap(map, size);
 
-       ksft_set_plan(13);
+       ksft_set_plan(15);
 
        test_mlock_lock();
        test_mlock_onfault();
@@ -451,6 +509,8 @@ int main(int argc, char **argv)
        test_lock_onfault_of_present();
        test_vma_management(true);
        test_mlockall();
+       test_mlock_droppable();
+       test_mlockall_future_droppable();
 
        ksft_finished();
 }
-- 
2.47.3


Reply via email to