linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/4] Increase mseal test coverage
@ 2024-08-29 21:43 jeffxu
  2024-08-29 21:43 ` [PATCH v2 1/4] selftests/mm: mseal_test, add vma size check jeffxu
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: jeffxu @ 2024-08-29 21:43 UTC (permalink / raw)
  To: akpm
  Cc: linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	pedro.falcato, willy, lorenzo.stoakes, broonie, vbabka,
	Liam.Howlett, rientjes, keescook, Jeff Xu

From: Jeff Xu <jeffxu@chromium.org>

This series increase the test coverage of mseal_test by:

Add check for vma_size, prot, and error code for existing tests.
Add more testcases for madvise, munmap, mmap and mremap to cover
sealing in different scenarios.

The increase test coverage hopefully help to prevent future regression.
It doesn't change any existing mm api's semantics, i.e. it will pass on
linux main and 6.10 branch.

Note: in order to pass this test in mm-unstable, mm-unstable must have
Liam's fix on mmap [1]

[1] https://lore.kernel.org/linux-kselftest/vyllxuh5xbqmaoyl2mselebij5ox7cseekjcvl5gmzoxxwd2he@hxi4mpjanxzt/#t

History:
V2:
- remove the mmap fix (Liam R. Howlett will fix it separately)
- Add cover letter (Lorenzo Stoakes)
- split the testcase for ease of review (Mark Brown)

V1:
- https://lore.kernel.org/linux-kselftest/20240828225522.684774-1-jeffxu@chromium.org/

Jeff Xu (4):
  selftests/mm: mseal_test, add vma size check
  selftests/mm: mseal_test add sealed madvise type
  selftests/mm: mseal_test add more tests for mmap
  selftests/mm: mseal_test add more tests for mremap

 tools/testing/selftests/mm/mseal_test.c | 829 ++++++++++++++++++++++--
 1 file changed, 762 insertions(+), 67 deletions(-)

-- 
2.46.0.469.g59c65b2a67-goog



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/4] selftests/mm: mseal_test, add vma size check
  2024-08-29 21:43 [PATCH v2 0/4] Increase mseal test coverage jeffxu
@ 2024-08-29 21:43 ` jeffxu
  2024-08-30 12:45   ` Pedro Falcato
  2024-08-29 21:43 ` [PATCH v2 2/4] selftests/mm: mseal_test add sealed madvise type jeffxu
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: jeffxu @ 2024-08-29 21:43 UTC (permalink / raw)
  To: akpm
  Cc: linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	pedro.falcato, willy, lorenzo.stoakes, broonie, vbabka,
	Liam.Howlett, rientjes, keescook, Jeff Xu

From: Jeff Xu <jeffxu@chromium.org>

Add check for vma size, prot bits and error return.

Signed-off-by: Jeff Xu <jeffxu@chromium.org>
---
 tools/testing/selftests/mm/mseal_test.c | 398 ++++++++++++++++++++----
 1 file changed, 332 insertions(+), 66 deletions(-)

diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
index e7991e5fdcf3..adc646cf576c 100644
--- a/tools/testing/selftests/mm/mseal_test.c
+++ b/tools/testing/selftests/mm/mseal_test.c
@@ -170,18 +170,31 @@ static void set_pkey(int pkey, unsigned long pkey_value)
 static void setup_single_address(int size, void **ptrOut)
 {
 	void *ptr;
+	unsigned long page_size = getpagesize();
 
-	ptr = mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
-	*ptrOut = ptr;
+	*ptrOut = (void *)-1;
+	ptr = mmap(NULL, size + 2 * page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+	if (ptr != (void *) -1) {
+		/* add 2 page at the beginning and end to avoid auto-merge of mapping */
+		sys_mprotect(ptr, page_size, PROT_NONE);
+		sys_mprotect(ptr + size + page_size, page_size, PROT_NONE);
+		*ptrOut = ptr + page_size;
+	}
 }
 
 static void setup_single_address_rw(int size, void **ptrOut)
 {
 	void *ptr;
 	unsigned long mapflags = MAP_ANONYMOUS | MAP_PRIVATE;
+	unsigned long page_size = getpagesize();
 
-	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mapflags, -1, 0);
-	*ptrOut = ptr;
+	*ptrOut = (void *)-1;
+	ptr = mmap(NULL, size + 2 * page_size, PROT_READ | PROT_WRITE, mapflags, -1, 0);
+	if (ptr != (void *) -1) {
+		sys_mprotect(ptr, page_size, PROT_NONE);
+		sys_mprotect(ptr + size + page_size, page_size, PROT_NONE);
+		*ptrOut = ptr + page_size;
+	}
 }
 
 static int clean_single_address(void *ptr, int size)
@@ -226,6 +239,21 @@ bool pkey_supported(void)
 	return false;
 }
 
+bool get_vma_size_supported(void)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 4 * page_size;
+	int prot;
+
+	setup_single_address(size, &ptr);
+	size = get_vma_size(ptr, &prot);
+	if (size == 4 * page_size && prot == 0x4)
+		return true;
+
+	return false;
+}
+
 static void test_seal_addseal(void)
 {
 	int ret;
@@ -419,11 +447,17 @@ static void test_seal_invalid_input(void)
 	unsigned long size = 4 * page_size;
 	int ret;
 
-	setup_single_address(8 * page_size, &ptr);
+	setup_single_address(9 * page_size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
-	ret = clean_single_address(ptr + 4 * page_size, 4 * page_size);
+
+	ret = clean_single_address(ptr, page_size);
 	FAIL_TEST_IF_FALSE(!ret);
 
+	ret = clean_single_address(ptr + 5 * page_size, 4 * page_size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	ptr = ptr + page_size;
+
 	/* invalid flag */
 	ret = syscall(__NR_mseal, ptr, size, 0x20);
 	FAIL_TEST_IF_FALSE(ret < 0);
@@ -523,6 +557,7 @@ static void test_seal_mprotect(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -533,9 +568,14 @@ static void test_seal_mprotect(bool seal)
 	}
 
 	ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
@@ -547,6 +587,7 @@ static void test_seal_start_mprotect(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -558,9 +599,14 @@ static void test_seal_start_mprotect(bool seal)
 
 	/* the first page is sealed. */
 	ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	/* pages after the first page is not sealed. */
@@ -577,6 +623,7 @@ static void test_seal_end_mprotect(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -593,9 +640,14 @@ static void test_seal_end_mprotect(bool seal)
 	/* last 3 page are sealed */
 	ret = sys_mprotect(ptr + page_size, page_size * 3,
 			PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr + page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 3 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
@@ -607,6 +659,7 @@ static void test_seal_mprotect_unalign_len(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -618,9 +671,14 @@ static void test_seal_mprotect_unalign_len(bool seal)
 
 	/* 2 pages are sealed. */
 	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	ret = sys_mprotect(ptr + page_size * 2, page_size,
@@ -636,6 +694,7 @@ static void test_seal_mprotect_unalign_len_variant_2(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -646,9 +705,14 @@ static void test_seal_mprotect_unalign_len_variant_2(bool seal)
 
 	/* 3 pages are sealed. */
 	ret = sys_mprotect(ptr, page_size * 3, PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 3 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	ret = sys_mprotect(ptr + page_size * 3, page_size,
@@ -664,6 +728,7 @@ static void test_seal_mprotect_two_vma(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -678,16 +743,26 @@ static void test_seal_mprotect_two_vma(bool seal)
 	}
 
 	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x6);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	ret = sys_mprotect(ptr + page_size * 2, page_size * 2,
 			PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr + page_size * 2, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
@@ -699,6 +774,7 @@ static void test_seal_mprotect_two_vma_with_split(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -719,17 +795,27 @@ static void test_seal_mprotect_two_vma_with_split(bool seal)
 
 	/* the second page is sealed. */
 	ret = sys_mprotect(ptr + page_size, page_size, PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x6);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	/* the third page is sealed. */
 	ret = sys_mprotect(ptr + 2 * page_size, page_size,
 			PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr + 2 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	/* the fouth page is not sealed. */
@@ -746,6 +832,7 @@ static void test_seal_mprotect_partial_mprotect(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -758,9 +845,14 @@ static void test_seal_mprotect_partial_mprotect(bool seal)
 
 	/* mprotect first 2 page will fail, since the first page are sealed. */
 	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
@@ -783,15 +875,15 @@ static void test_seal_mprotect_partial_mprotect_tail(bool seal)
 	}
 
 	ret = sys_mprotect(ptr, size, PROT_EXEC);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
-		FAIL_TEST_IF_FALSE(!ret);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
 
-	if (seal) {
-		FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0);
+		size = get_vma_size(ptr + page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
 		FAIL_TEST_IF_FALSE(prot == 0x4);
-	}
+	} else
+		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
 }
@@ -846,6 +938,7 @@ static void test_seal_mprotect_split(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -862,16 +955,34 @@ static void test_seal_mprotect_split(bool seal)
 
 	/* mprotect is sealed. */
 	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x6);
+
+		size = get_vma_size(ptr + page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 3 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 
 	ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x6);
+
+		size = get_vma_size(ptr + page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 3 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
@@ -883,6 +994,7 @@ static void test_seal_mprotect_merge(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -899,9 +1011,18 @@ static void test_seal_mprotect_merge(bool seal)
 
 	/* 2 pages are sealed. */
 	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x6);
+
+		size = get_vma_size(ptr + page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	/* last 2 pages are not sealed. */
@@ -917,6 +1038,7 @@ static void test_seal_munmap(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -928,9 +1050,14 @@ static void test_seal_munmap(bool seal)
 
 	/* 4 pages are sealed. */
 	ret = sys_munmap(ptr, size);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
@@ -948,6 +1075,7 @@ static void test_seal_munmap_two_vma(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -962,15 +1090,33 @@ static void test_seal_munmap_two_vma(bool seal)
 	}
 
 	ret = sys_munmap(ptr, page_size * 2);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x6);
+
+		size = get_vma_size(ptr + 2 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	ret = sys_munmap(ptr + page_size, page_size * 2);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x6);
+
+		size = get_vma_size(ptr + 2 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
@@ -1018,33 +1164,75 @@ static void test_seal_munmap_partial_across_vmas(bool seal)
 {
 	void *ptr;
 	unsigned long page_size = getpagesize();
-	unsigned long size = 2 * page_size;
+	unsigned long size = 12 * page_size;
 	int ret;
 	int prot;
 
-	/*
-	 * Check if a partial mseal (that results in two vmas) works correctly.
-	 * It might unmap the first, but it'll never unmap the second (msealed) vma.
-	 */
-
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
 
 	if (seal) {
-		ret = sys_mseal(ptr + page_size, page_size);
+		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
 		FAIL_TEST_IF_FALSE(!ret);
 	}
 
-	ret = sys_munmap(ptr, size);
-	if (seal)
+	ret = sys_munmap(ptr, 12 * page_size);
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+
+		size = get_vma_size(ptr + 4 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+
+		size = get_vma_size(ptr + 8 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
+
+	ret = sys_munmap(ptr, 6 * page_size);
 	if (seal) {
-		FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0);
+		FAIL_TEST_IF_FALSE(ret < 0);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+
+		size = get_vma_size(ptr + 4 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
 		FAIL_TEST_IF_FALSE(prot == 0x4);
-	}
+
+		size = get_vma_size(ptr + 8 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
+		FAIL_TEST_IF_FALSE(!ret);
+
+	ret = sys_munmap(ptr + 6 * page_size, 6 * page_size);
+	if (seal) {
+		FAIL_TEST_IF_FALSE(ret < 0);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+
+		size = get_vma_size(ptr + 4 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+
+		size = get_vma_size(ptr + 8 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
+		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
 }
@@ -1074,9 +1262,11 @@ static void test_munmap_start_freed(bool seal)
 	ret = sys_munmap(ptr, size);
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
 
 		size = get_vma_size(ptr + page_size, &prot);
-		FAIL_TEST_IF_FALSE(size == page_size * 3);
+		FAIL_TEST_IF_FALSE(size == 3 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else {
 		/* note: this will be OK, even the first page is */
 		/* already unmapped. */
@@ -1095,6 +1285,7 @@ static void test_munmap_end_freed(bool seal)
 	unsigned long page_size = getpagesize();
 	unsigned long size = 4 * page_size;
 	int ret;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1111,9 +1302,14 @@ static void test_munmap_end_freed(bool seal)
 
 	/* unmap all pages. */
 	ret = sys_munmap(ptr, size);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 3 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	REPORT_TEST_PASS();
@@ -1144,12 +1340,15 @@ static void test_munmap_middle_freed(bool seal)
 	ret = sys_munmap(ptr, size);
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
 
 		size = get_vma_size(ptr, &prot);
 		FAIL_TEST_IF_FALSE(size == page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 
 		size = get_vma_size(ptr + page_size * 3, &prot);
 		FAIL_TEST_IF_FALSE(size == page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else {
 		FAIL_TEST_IF_FALSE(!ret);
 
@@ -1170,6 +1369,7 @@ static void test_seal_mremap_shrink(bool seal)
 	unsigned long size = 4 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1184,6 +1384,10 @@ static void test_seal_mremap_shrink(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else {
 		FAIL_TEST_IF_FALSE(ret2 != (void *) MAP_FAILED);
 
@@ -1199,6 +1403,7 @@ static void test_seal_mremap_expand(bool seal)
 	unsigned long size = 4 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1216,6 +1421,10 @@ static void test_seal_mremap_expand(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else {
 		FAIL_TEST_IF_FALSE(ret2 == ptr);
 
@@ -1231,6 +1440,7 @@ static void test_seal_mremap_move(bool seal)
 	unsigned long size = page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1249,10 +1459,12 @@ static void test_seal_mremap_move(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
-	} else {
-		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
 
-	}
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size ==  page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
+		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
 
 	REPORT_TEST_PASS();
 }
@@ -1264,6 +1476,7 @@ static void test_seal_mmap_overwrite_prot(bool seal)
 	unsigned long size = page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1279,6 +1492,10 @@ static void test_seal_mmap_overwrite_prot(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else
 		FAIL_TEST_IF_FALSE(ret2 == ptr);
 
@@ -1292,6 +1509,7 @@ static void test_seal_mmap_expand(bool seal)
 	unsigned long size = 12 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1310,6 +1528,10 @@ static void test_seal_mmap_expand(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 8 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else
 		FAIL_TEST_IF_FALSE(ret2 == ptr);
 
@@ -1323,6 +1545,7 @@ static void test_seal_mmap_shrink(bool seal)
 	unsigned long size = 12 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1338,6 +1561,10 @@ static void test_seal_mmap_shrink(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 12 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else
 		FAIL_TEST_IF_FALSE(ret2 == ptr);
 
@@ -1352,6 +1579,7 @@ static void test_seal_mremap_shrink_fixed(bool seal)
 	unsigned long size = 4 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1369,6 +1597,10 @@ static void test_seal_mremap_shrink_fixed(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else
 		FAIL_TEST_IF_FALSE(ret2 == newAddr);
 
@@ -1383,6 +1615,7 @@ static void test_seal_mremap_expand_fixed(bool seal)
 	unsigned long size = 4 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(page_size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1400,6 +1633,10 @@ static void test_seal_mremap_expand_fixed(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(newAddr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else
 		FAIL_TEST_IF_FALSE(ret2 == newAddr);
 
@@ -1414,6 +1651,7 @@ static void test_seal_mremap_move_fixed(bool seal)
 	unsigned long size = 4 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1430,6 +1668,10 @@ static void test_seal_mremap_move_fixed(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(newAddr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else
 		FAIL_TEST_IF_FALSE(ret2 == newAddr);
 
@@ -1443,6 +1685,7 @@ static void test_seal_mremap_move_fixed_zero(bool seal)
 	unsigned long size = 4 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1460,9 +1703,12 @@ static void test_seal_mremap_move_fixed_zero(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
-	} else {
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
 		FAIL_TEST_IF_FALSE(ret2 == 0);
-	}
 
 	REPORT_TEST_PASS();
 }
@@ -1474,6 +1720,7 @@ static void test_seal_mremap_move_dontunmap(bool seal)
 	unsigned long size = 4 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1488,6 +1735,10 @@ static void test_seal_mremap_move_dontunmap(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else {
 		/* kernel will allocate a new address */
 		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
@@ -1503,6 +1754,7 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
 	unsigned long size = 4 * page_size;
 	int ret;
 	void *ret2;
+	int prot;
 
 	setup_single_address(size, &ptr);
 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
@@ -1529,6 +1781,10 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
 	if (seal) {
 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
 		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
 	} else {
 		/* remap success and return ptr2 */
 		FAIL_TEST_IF_FALSE(ret2 ==  ptr2);
@@ -1690,9 +1946,10 @@ static void test_seal_discard_ro_anon_on_pkey(bool seal)
 	/* sealing will take effect if PKRU deny write. */
 	set_pkey(pkey, PKEY_DISABLE_WRITE);
 	ret = sys_madvise(ptr, size, MADV_DONTNEED);
-	if (seal)
+	if (seal) {
 		FAIL_TEST_IF_FALSE(ret < 0);
-	else
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+	} else
 		FAIL_TEST_IF_FALSE(!ret);
 
 	/* base seal still apply. */
@@ -1876,6 +2133,15 @@ int main(int argc, char **argv)
 	if (!pkey_supported())
 		ksft_print_msg("PKEY not supported\n");
 
+	/*
+	 * Possible reasons:
+	 * - unable to read /proc/pid/maps (unlikely)
+	 * - parsing error when reading /proc/pid/maps,e.g. len is not expected.
+	 *   Is this "TOPDOWN" mapping or format change in /proc/pid/maps ?
+	 */
+	if (!get_vma_size_supported())
+		ksft_exit_skip("get_vma_size not supported\n");
+
 	ksft_set_plan(88);
 
 	test_seal_addseal();
-- 
2.46.0.469.g59c65b2a67-goog



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 2/4] selftests/mm: mseal_test add sealed madvise type
  2024-08-29 21:43 [PATCH v2 0/4] Increase mseal test coverage jeffxu
  2024-08-29 21:43 ` [PATCH v2 1/4] selftests/mm: mseal_test, add vma size check jeffxu
@ 2024-08-29 21:43 ` jeffxu
  2024-08-30 12:52   ` Pedro Falcato
  2024-08-29 21:43 ` [PATCH v2 3/4] selftests/mm: mseal_test add more tests for mmap jeffxu
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: jeffxu @ 2024-08-29 21:43 UTC (permalink / raw)
  To: akpm
  Cc: linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	pedro.falcato, willy, lorenzo.stoakes, broonie, vbabka,
	Liam.Howlett, rientjes, keescook, Jeff Xu

From: Jeff Xu <jeffxu@chromium.org>

Add a testcase to cover all sealed madvise type.

Signed-off-by: Jeff Xu <jeffxu@chromium.org>
---
 tools/testing/selftests/mm/mseal_test.c | 108 +++++++++++++++++++++++-
 1 file changed, 107 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
index adc646cf576c..ae06c354220d 100644
--- a/tools/testing/selftests/mm/mseal_test.c
+++ b/tools/testing/selftests/mm/mseal_test.c
@@ -2121,6 +2121,107 @@ static void test_seal_madvise_nodiscard(bool seal)
 	REPORT_TEST_PASS();
 }
 
+static void test_seal_discard_madvise_advice(void)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 4 * page_size;
+	int ret;
+	int sealed_advice[] = {MADV_FREE, MADV_DONTNEED,
+		MADV_DONTNEED_LOCKED, MADV_REMOVE,
+		MADV_DONTFORK, MADV_WIPEONFORK};
+	int size_sealed_advice = sizeof(sealed_advice) / sizeof(int);
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+
+	ret = seal_single_address(ptr, size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	for (int i = 0; i < size_sealed_advice; i++) {
+		ret = sys_madvise(ptr, size, sealed_advice[i]);
+		FAIL_TEST_IF_FALSE(ret < 0);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+	}
+
+	REPORT_TEST_PASS();
+}
+
+static void test_munmap_free_multiple_ranges(bool seal)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 8 * page_size;
+	int ret;
+	int prot;
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+
+	/* unmap one page from beginning. */
+	ret = sys_munmap(ptr, page_size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	/* unmap one page from middle. */
+	ret = sys_munmap(ptr + 4 * page_size, page_size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	size = get_vma_size(ptr + page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 3 * page_size);
+	FAIL_TEST_IF_FALSE(prot == 4);
+
+	size = get_vma_size(ptr +  5 * page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 3 * page_size);
+	FAIL_TEST_IF_FALSE(prot == 4);
+
+
+	/* seal the last page */
+	if (seal) {
+		ret = sys_mseal(ptr + 7 * page_size, page_size);
+		FAIL_TEST_IF_FALSE(!ret);
+
+		size = get_vma_size(ptr +  1 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 3 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 4);
+
+		size = get_vma_size(ptr +  5 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 4);
+
+		size = get_vma_size(ptr +  7 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 4);
+	}
+
+	/* munmap all 8  pages from beginning */
+	ret = sys_munmap(ptr, 8 * page_size);
+	if (seal) {
+		FAIL_TEST_IF_FALSE(ret);
+
+		/* verify mapping are not changed */
+		size = get_vma_size(ptr + 1 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 3 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 4);
+
+		size = get_vma_size(ptr +  5 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 4);
+
+		size = get_vma_size(ptr +  7 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 1 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 4);
+	} else {
+		FAIL_TEST_IF_FALSE(!ret);
+
+		for (int i = 0; i < 8; i++) {
+			size = get_vma_size(ptr, &prot);
+			FAIL_TEST_IF_FALSE(size == 0);
+		}
+	}
+
+	REPORT_TEST_PASS();
+}
+
 int main(int argc, char **argv)
 {
 	bool test_seal = seal_support();
@@ -2142,7 +2243,7 @@ int main(int argc, char **argv)
 	if (!get_vma_size_supported())
 		ksft_exit_skip("get_vma_size not supported\n");
 
-	ksft_set_plan(88);
+	ksft_set_plan(91);
 
 	test_seal_addseal();
 	test_seal_unmapped_start();
@@ -2251,5 +2352,10 @@ int main(int argc, char **argv)
 	test_seal_discard_ro_anon_on_pkey(false);
 	test_seal_discard_ro_anon_on_pkey(true);
 
+	test_seal_discard_madvise_advice();
+
+	test_munmap_free_multiple_ranges(false);
+	test_munmap_free_multiple_ranges(true);
+
 	ksft_finished();
 }
-- 
2.46.0.469.g59c65b2a67-goog



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 3/4] selftests/mm: mseal_test add more tests for mmap
  2024-08-29 21:43 [PATCH v2 0/4] Increase mseal test coverage jeffxu
  2024-08-29 21:43 ` [PATCH v2 1/4] selftests/mm: mseal_test, add vma size check jeffxu
  2024-08-29 21:43 ` [PATCH v2 2/4] selftests/mm: mseal_test add sealed madvise type jeffxu
@ 2024-08-29 21:43 ` jeffxu
  2024-08-30 12:57   ` Pedro Falcato
  2024-08-29 21:43 ` [PATCH v2 4/4] selftests/mm: mseal_test add more tests for mremap jeffxu
  2024-08-30 12:31 ` [PATCH v2 0/4] Increase mseal test coverage Pedro Falcato
  4 siblings, 1 reply; 13+ messages in thread
From: jeffxu @ 2024-08-29 21:43 UTC (permalink / raw)
  To: akpm
  Cc: linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	pedro.falcato, willy, lorenzo.stoakes, broonie, vbabka,
	Liam.Howlett, rientjes, keescook, Jeff Xu

From: Jeff Xu <jeffxu@chromium.org>

Add sealing test to cover mmap for
Expand/shrink across vmas.
Reuse the same address in !MAP_FIXED case.

Signed-off-by: Jeff Xu <jeffxu@chromium.org>
---
 tools/testing/selftests/mm/mseal_test.c | 125 +++++++++++++++++++++++-
 1 file changed, 124 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
index ae06c354220d..d83538039e76 100644
--- a/tools/testing/selftests/mm/mseal_test.c
+++ b/tools/testing/selftests/mm/mseal_test.c
@@ -2222,6 +2222,122 @@ static void test_munmap_free_multiple_ranges(bool seal)
 	REPORT_TEST_PASS();
 }
 
+static void test_seal_mmap_expand_seal_middle(bool seal)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 12 * page_size;
+	int ret;
+	void *ret2;
+	int prot;
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+	/* ummap last 4 pages. */
+	ret = sys_munmap(ptr + 8 * page_size, 4 * page_size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == 8 * page_size);
+	FAIL_TEST_IF_FALSE(prot == 0x4);
+
+	if (seal) {
+		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
+		FAIL_TEST_IF_FALSE(!ret);
+	}
+
+	/* use mmap to expand. */
+	ret2 = mmap(ptr, 12 * page_size, PROT_READ,
+			MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
+	if (seal) {
+		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+
+		size = get_vma_size(ptr + 4 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
+		FAIL_TEST_IF_FALSE(ret2 == ptr);
+
+	REPORT_TEST_PASS();
+}
+
+static void test_seal_mmap_shrink_seal_middle(bool seal)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 12 * page_size;
+	int ret;
+	void *ret2;
+	int prot;
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+
+	if (seal) {
+		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
+		FAIL_TEST_IF_FALSE(!ret);
+	}
+
+	/* use mmap to shrink. */
+	ret2 = mmap(ptr, 7 * page_size, PROT_READ,
+			MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
+	if (seal) {
+		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+
+		size = get_vma_size(ptr + 4 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+
+		size = get_vma_size(ptr + 4 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+		FAIL_TEST_IF_FALSE(prot == 0x4);
+	} else
+		FAIL_TEST_IF_FALSE(ret2 == ptr);
+
+	REPORT_TEST_PASS();
+}
+
+static void test_seal_mmap_reuse_addr(bool seal)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = page_size;
+	int ret;
+	void *ret2;
+	int prot;
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+
+	if (seal) {
+		ret = sys_mseal(ptr, size);
+		FAIL_TEST_IF_FALSE(!ret);
+	}
+
+	/* use mmap to change protection. */
+	ret2 = mmap(ptr, size, PROT_NONE,
+			MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+
+	FAIL_TEST_IF_FALSE(!(ret2 == MAP_FAILED));
+	FAIL_TEST_IF_FALSE(ret2 != ptr);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == page_size);
+	FAIL_TEST_IF_FALSE(prot == 0x4);
+
+	REPORT_TEST_PASS();
+}
+
 int main(int argc, char **argv)
 {
 	bool test_seal = seal_support();
@@ -2243,7 +2359,7 @@ int main(int argc, char **argv)
 	if (!get_vma_size_supported())
 		ksft_exit_skip("get_vma_size not supported\n");
 
-	ksft_set_plan(91);
+	ksft_set_plan(97);
 
 	test_seal_addseal();
 	test_seal_unmapped_start();
@@ -2357,5 +2473,12 @@ int main(int argc, char **argv)
 	test_munmap_free_multiple_ranges(false);
 	test_munmap_free_multiple_ranges(true);
 
+	test_seal_mmap_expand_seal_middle(false);
+	test_seal_mmap_expand_seal_middle(true);
+	test_seal_mmap_shrink_seal_middle(false);
+	test_seal_mmap_shrink_seal_middle(true);
+	test_seal_mmap_reuse_addr(false);
+	test_seal_mmap_reuse_addr(true);
+
 	ksft_finished();
 }
-- 
2.46.0.469.g59c65b2a67-goog



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 4/4] selftests/mm: mseal_test add more tests for mremap
  2024-08-29 21:43 [PATCH v2 0/4] Increase mseal test coverage jeffxu
                   ` (2 preceding siblings ...)
  2024-08-29 21:43 ` [PATCH v2 3/4] selftests/mm: mseal_test add more tests for mmap jeffxu
@ 2024-08-29 21:43 ` jeffxu
  2024-08-30 12:31 ` [PATCH v2 0/4] Increase mseal test coverage Pedro Falcato
  4 siblings, 0 replies; 13+ messages in thread
From: jeffxu @ 2024-08-29 21:43 UTC (permalink / raw)
  To: akpm
  Cc: linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	pedro.falcato, willy, lorenzo.stoakes, broonie, vbabka,
	Liam.Howlett, rientjes, keescook, Jeff Xu

From: Jeff Xu <jeffxu@chromium.org>

Add sealing test to cover mremap for
Expand/shrink/move across vmas.

Signed-off-by: Jeff Xu <jeffxu@chromium.org>
---
 tools/testing/selftests/mm/mseal_test.c | 202 +++++++++++++++++++++++-
 1 file changed, 201 insertions(+), 1 deletion(-)

diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
index d83538039e76..494035129d65 100644
--- a/tools/testing/selftests/mm/mseal_test.c
+++ b/tools/testing/selftests/mm/mseal_test.c
@@ -2338,6 +2338,197 @@ static void test_seal_mmap_reuse_addr(bool seal)
 	REPORT_TEST_PASS();
 }
 
+static void test_seal_mremap_shrink_multiple_vmas(bool seal)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 12 * page_size;
+	int ret;
+	void *ret2;
+	int prot;
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+
+	ret = sys_mprotect(ptr + 4 * page_size, 4 * page_size, PROT_NONE);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	size = get_vma_size(ptr + 4 * page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	if (seal) {
+		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
+		FAIL_TEST_IF_FALSE(!ret);
+	}
+
+	ret2 = sys_mremap(ptr, 12 * page_size, 6 * page_size, 0, 0);
+	if (seal) {
+		FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
+		FAIL_TEST_IF_FALSE(errno == EPERM);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+		size = get_vma_size(ptr + 4 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+	} else {
+		FAIL_TEST_IF_FALSE(ret2 == ptr);
+
+		size = get_vma_size(ptr, &prot);
+		FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+		size = get_vma_size(ptr + 4 * page_size, &prot);
+		FAIL_TEST_IF_FALSE(size == 2 * page_size);
+	}
+
+	REPORT_TEST_PASS();
+}
+
+static void test_seal_mremap_expand_multiple_vmas(bool seal)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 12 * page_size;
+	int ret;
+	void *ret2;
+	int prot;
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+
+	ret = sys_mprotect(ptr + 4 * page_size, 4 * page_size, PROT_NONE);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	/* ummap last 4 pages. */
+	ret = sys_munmap(ptr + 8 * page_size, 4 * page_size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	size = get_vma_size(ptr + 4 * page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	if (seal) {
+		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
+		FAIL_TEST_IF_FALSE(!ret);
+	}
+
+	ret2 = sys_mremap(ptr, 8 * page_size, 12 * page_size, 0, 0);
+	FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	size = get_vma_size(ptr + 4 * page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	REPORT_TEST_PASS();
+}
+
+static void test_seal_mremap_move_expand_multiple_vmas(bool seal)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 12 * page_size;
+	int ret;
+	void *ret2;
+	int prot;
+	void *ptr2;
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+
+	setup_single_address(size, &ptr2);
+	FAIL_TEST_IF_FALSE(ptr2 != (void *)-1);
+
+	ret = sys_munmap(ptr2, 12 * page_size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	ret = sys_mprotect(ptr + 4 * page_size, 4 * page_size, PROT_NONE);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	/* ummap last 4 pages. */
+	ret = sys_munmap(ptr + 8 * page_size, 4 * page_size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	size = get_vma_size(ptr + 4 * page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	if (seal) {
+		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
+		FAIL_TEST_IF_FALSE(!ret);
+	}
+
+	/* move and expand cross VMA boundary will fail */
+	ret2 = sys_mremap(ptr, 8 * page_size, 10 * page_size, MREMAP_FIXED | MREMAP_MAYMOVE, ptr2);
+	FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	size = get_vma_size(ptr + 4 * page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+
+	REPORT_TEST_PASS();
+}
+
+static void test_seal_mremap_move_shrink_multiple_vmas(bool seal)
+{
+	void *ptr;
+	unsigned long page_size = getpagesize();
+	unsigned long size = 12 * page_size;
+	int ret;
+	void *ret2;
+	int prot;
+	void *ptr2;
+
+	setup_single_address(size, &ptr);
+	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
+
+	setup_single_address(size, &ptr2);
+	FAIL_TEST_IF_FALSE(ptr2 != (void *)-1);
+
+	ret = sys_munmap(ptr2, 12 * page_size);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	ret = sys_mprotect(ptr + 4 * page_size, 4 * page_size, PROT_NONE);
+	FAIL_TEST_IF_FALSE(!ret);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+	FAIL_TEST_IF_FALSE(prot == 4);
+
+	size = get_vma_size(ptr + 4 * page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+	FAIL_TEST_IF_FALSE(prot == 0);
+
+	if (seal) {
+		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
+		FAIL_TEST_IF_FALSE(!ret);
+	}
+
+	/* move and shrink cross VMA boundary is NOK */
+	ret2 = sys_mremap(ptr, 12 * page_size, 8 * page_size, MREMAP_FIXED | MREMAP_MAYMOVE, ptr2);
+	FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
+
+	size = get_vma_size(ptr, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+	FAIL_TEST_IF_FALSE(prot == 4);
+
+	size = get_vma_size(ptr + 4 * page_size, &prot);
+	FAIL_TEST_IF_FALSE(size == 4 * page_size);
+	FAIL_TEST_IF_FALSE(prot == 0);
+
+	REPORT_TEST_PASS();
+}
+
 int main(int argc, char **argv)
 {
 	bool test_seal = seal_support();
@@ -2359,7 +2550,7 @@ int main(int argc, char **argv)
 	if (!get_vma_size_supported())
 		ksft_exit_skip("get_vma_size not supported\n");
 
-	ksft_set_plan(97);
+	ksft_set_plan(105);
 
 	test_seal_addseal();
 	test_seal_unmapped_start();
@@ -2480,5 +2671,14 @@ int main(int argc, char **argv)
 	test_seal_mmap_reuse_addr(false);
 	test_seal_mmap_reuse_addr(true);
 
+	test_seal_mremap_shrink_multiple_vmas(false);
+	test_seal_mremap_shrink_multiple_vmas(true);
+	test_seal_mremap_expand_multiple_vmas(false);
+	test_seal_mremap_expand_multiple_vmas(true);
+	test_seal_mremap_move_expand_multiple_vmas(false);
+	test_seal_mremap_move_expand_multiple_vmas(true);
+	test_seal_mremap_move_shrink_multiple_vmas(false);
+	test_seal_mremap_move_shrink_multiple_vmas(true);
+
 	ksft_finished();
 }
-- 
2.46.0.469.g59c65b2a67-goog



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 0/4] Increase mseal test coverage
  2024-08-29 21:43 [PATCH v2 0/4] Increase mseal test coverage jeffxu
                   ` (3 preceding siblings ...)
  2024-08-29 21:43 ` [PATCH v2 4/4] selftests/mm: mseal_test add more tests for mremap jeffxu
@ 2024-08-30 12:31 ` Pedro Falcato
  2024-08-30 15:38   ` Jeff Xu
  4 siblings, 1 reply; 13+ messages in thread
From: Pedro Falcato @ 2024-08-30 12:31 UTC (permalink / raw)
  To: jeffxu
  Cc: akpm, linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	willy, lorenzo.stoakes, broonie, vbabka, Liam.Howlett, rientjes,
	keescook

On Thu, Aug 29, 2024 at 09:43:48PM GMT, jeffxu@chromium.org wrote:
> From: Jeff Xu <jeffxu@chromium.org>
> 
> This series increase the test coverage of mseal_test by:
> 
> Add check for vma_size, prot, and error code for existing tests.
> Add more testcases for madvise, munmap, mmap and mremap to cover
> sealing in different scenarios.
> 
> The increase test coverage hopefully help to prevent future regression.
> It doesn't change any existing mm api's semantics, i.e. it will pass on
> linux main and 6.10 branch.

I do want to be clear that we shouldn't confuse "test coverage" with being unequivocally good
if it has the possibility to paint ourselves into an API corner where details that should be left
unspecified are instead set in stone (e.g do we want to test how mprotect behaves if it finds an msealed
vma midway? no, apart from the property that really matters in this case (that sealed vmas remain untouched)).

> 
> Note: in order to pass this test in mm-unstable, mm-unstable must have
> Liam's fix on mmap [1]
> 
> [1] https://lore.kernel.org/linux-kselftest/vyllxuh5xbqmaoyl2mselebij5ox7cseekjcvl5gmzoxxwd2he@hxi4mpjanxzt/#t
> 
> History:
> V2:
> - remove the mmap fix (Liam R. Howlett will fix it separately)
> - Add cover letter (Lorenzo Stoakes)
> - split the testcase for ease of review (Mark Brown)
> 
> V1:
> - https://lore.kernel.org/linux-kselftest/20240828225522.684774-1-jeffxu@chromium.org/
> 
> Jeff Xu (4):
>   selftests/mm: mseal_test, add vma size check
>   selftests/mm: mseal_test add sealed madvise type
>   selftests/mm: mseal_test add more tests for mmap
>   selftests/mm: mseal_test add more tests for mremap
>

nit: Please follow a more standard commit naming scheme like
	selftests/mm: <change description>
or
	selftests/mseal: <change description>

-- 
Pedro


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 1/4] selftests/mm: mseal_test, add vma size check
  2024-08-29 21:43 ` [PATCH v2 1/4] selftests/mm: mseal_test, add vma size check jeffxu
@ 2024-08-30 12:45   ` Pedro Falcato
  2024-08-30 15:45     ` Jeff Xu
  0 siblings, 1 reply; 13+ messages in thread
From: Pedro Falcato @ 2024-08-30 12:45 UTC (permalink / raw)
  To: jeffxu
  Cc: akpm, linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	willy, lorenzo.stoakes, broonie, vbabka, Liam.Howlett, rientjes,
	keescook

On Thu, Aug 29, 2024 at 09:43:49PM GMT, jeffxu@chromium.org wrote:
> From: Jeff Xu <jeffxu@chromium.org>
> 
> Add check for vma size, prot bits and error return.
> 
> Signed-off-by: Jeff Xu <jeffxu@chromium.org>
> ---
>  tools/testing/selftests/mm/mseal_test.c | 398 ++++++++++++++++++++----
>  1 file changed, 332 insertions(+), 66 deletions(-)
> 
> diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
> index e7991e5fdcf3..adc646cf576c 100644
> --- a/tools/testing/selftests/mm/mseal_test.c
> +++ b/tools/testing/selftests/mm/mseal_test.c
> @@ -170,18 +170,31 @@ static void set_pkey(int pkey, unsigned long pkey_value)
>  static void setup_single_address(int size, void **ptrOut)
>  {
>  	void *ptr;
> +	unsigned long page_size = getpagesize();
>  
> -	ptr = mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> -	*ptrOut = ptr;
> +	*ptrOut = (void *)-1;
> +	ptr = mmap(NULL, size + 2 * page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> +	if (ptr != (void *) -1) {

MAP_FAILED, not (void *) -1

> +		/* add 2 page at the beginning and end to avoid auto-merge of mapping */
> +		sys_mprotect(ptr, page_size, PROT_NONE);
> +		sys_mprotect(ptr + size + page_size, page_size, PROT_NONE);
> +		*ptrOut = ptr + page_size;
> +	}
>  }
>  
>  static void setup_single_address_rw(int size, void **ptrOut)
>  {
>  	void *ptr;
>  	unsigned long mapflags = MAP_ANONYMOUS | MAP_PRIVATE;
> +	unsigned long page_size = getpagesize();
>  
> -	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mapflags, -1, 0);
> -	*ptrOut = ptr;
> +	*ptrOut = (void *)-1;
> +	ptr = mmap(NULL, size + 2 * page_size, PROT_READ | PROT_WRITE, mapflags, -1, 0);
> +	if (ptr != (void *) -1) {

Same here.
> +		sys_mprotect(ptr, page_size, PROT_NONE);
> +		sys_mprotect(ptr + size + page_size, page_size, PROT_NONE);
> +		*ptrOut = ptr + page_size;
> +	}
>  }
>  
>  static int clean_single_address(void *ptr, int size)
> @@ -226,6 +239,21 @@ bool pkey_supported(void)
>  	return false;
>  }
>  
> +bool get_vma_size_supported(void)
> +{
> +	void *ptr;
> +	unsigned long page_size = getpagesize();
> +	unsigned long size = 4 * page_size;
> +	int prot;
> +
> +	setup_single_address(size, &ptr);
> +	size = get_vma_size(ptr, &prot);
> +	if (size == 4 * page_size && prot == 0x4)
> +		return true;
> +
> +	return false;
> +}
> +
>  static void test_seal_addseal(void)
>  {
>  	int ret;
> @@ -419,11 +447,17 @@ static void test_seal_invalid_input(void)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  
> -	setup_single_address(8 * page_size, &ptr);
> +	setup_single_address(9 * page_size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> -	ret = clean_single_address(ptr + 4 * page_size, 4 * page_size);
> +
> +	ret = clean_single_address(ptr, page_size);
>  	FAIL_TEST_IF_FALSE(!ret);
>  
> +	ret = clean_single_address(ptr + 5 * page_size, 4 * page_size);
> +	FAIL_TEST_IF_FALSE(!ret);
> +
> +	ptr = ptr + page_size;
> +
>  	/* invalid flag */
>  	ret = syscall(__NR_mseal, ptr, size, 0x20);
>  	FAIL_TEST_IF_FALSE(ret < 0);
> @@ -523,6 +557,7 @@ static void test_seal_mprotect(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -533,9 +568,14 @@ static void test_seal_mprotect(bool seal)
>  	}
>  
>  	ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
> @@ -547,6 +587,7 @@ static void test_seal_start_mprotect(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -558,9 +599,14 @@ static void test_seal_start_mprotect(bool seal)
>  
>  	/* the first page is sealed. */
>  	ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	/* pages after the first page is not sealed. */
> @@ -577,6 +623,7 @@ static void test_seal_end_mprotect(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -593,9 +640,14 @@ static void test_seal_end_mprotect(bool seal)
>  	/* last 3 page are sealed */
>  	ret = sys_mprotect(ptr + page_size, page_size * 3,
>  			PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr + page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
> @@ -607,6 +659,7 @@ static void test_seal_mprotect_unalign_len(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -618,9 +671,14 @@ static void test_seal_mprotect_unalign_len(bool seal)
>  
>  	/* 2 pages are sealed. */
>  	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	ret = sys_mprotect(ptr + page_size * 2, page_size,
> @@ -636,6 +694,7 @@ static void test_seal_mprotect_unalign_len_variant_2(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -646,9 +705,14 @@ static void test_seal_mprotect_unalign_len_variant_2(bool seal)
>  
>  	/* 3 pages are sealed. */
>  	ret = sys_mprotect(ptr, page_size * 3, PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	ret = sys_mprotect(ptr + page_size * 3, page_size,
> @@ -664,6 +728,7 @@ static void test_seal_mprotect_two_vma(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -678,16 +743,26 @@ static void test_seal_mprotect_two_vma(bool seal)
>  	}
>  
>  	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x6);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	ret = sys_mprotect(ptr + page_size * 2, page_size * 2,
>  			PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr + page_size * 2, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
> @@ -699,6 +774,7 @@ static void test_seal_mprotect_two_vma_with_split(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -719,17 +795,27 @@ static void test_seal_mprotect_two_vma_with_split(bool seal)
>  
>  	/* the second page is sealed. */
>  	ret = sys_mprotect(ptr + page_size, page_size, PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x6);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	/* the third page is sealed. */
>  	ret = sys_mprotect(ptr + 2 * page_size, page_size,
>  			PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr + 2 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	/* the fouth page is not sealed. */
> @@ -746,6 +832,7 @@ static void test_seal_mprotect_partial_mprotect(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -758,9 +845,14 @@ static void test_seal_mprotect_partial_mprotect(bool seal)
>  
>  	/* mprotect first 2 page will fail, since the first page are sealed. */
>  	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
> @@ -783,15 +875,15 @@ static void test_seal_mprotect_partial_mprotect_tail(bool seal)
>  	}
>  
>  	ret = sys_mprotect(ptr, size, PROT_EXEC);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> -		FAIL_TEST_IF_FALSE(!ret);
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
>  
> -	if (seal) {
> -		FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0);
> +		size = get_vma_size(ptr + page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
>  		FAIL_TEST_IF_FALSE(prot == 0x4);
> -	}
> +	} else
> +		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
>  }
> @@ -846,6 +938,7 @@ static void test_seal_mprotect_split(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -862,16 +955,34 @@ static void test_seal_mprotect_split(bool seal)
>  
>  	/* mprotect is sealed. */
>  	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x6);
> +
> +		size = get_vma_size(ptr + page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  
>  	ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x6);
> +
> +		size = get_vma_size(ptr + page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
> @@ -883,6 +994,7 @@ static void test_seal_mprotect_merge(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -899,9 +1011,18 @@ static void test_seal_mprotect_merge(bool seal)
>  
>  	/* 2 pages are sealed. */
>  	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x6);
> +
> +		size = get_vma_size(ptr + page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	/* last 2 pages are not sealed. */
> @@ -917,6 +1038,7 @@ static void test_seal_munmap(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -928,9 +1050,14 @@ static void test_seal_munmap(bool seal)
>  
>  	/* 4 pages are sealed. */
>  	ret = sys_munmap(ptr, size);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
> @@ -948,6 +1075,7 @@ static void test_seal_munmap_two_vma(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -962,15 +1090,33 @@ static void test_seal_munmap_two_vma(bool seal)
>  	}
>  
>  	ret = sys_munmap(ptr, page_size * 2);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x6);
> +
> +		size = get_vma_size(ptr + 2 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	ret = sys_munmap(ptr + page_size, page_size * 2);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x6);
> +
> +		size = get_vma_size(ptr + 2 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
> @@ -1018,33 +1164,75 @@ static void test_seal_munmap_partial_across_vmas(bool seal)
>  {
>  	void *ptr;
>  	unsigned long page_size = getpagesize();
> -	unsigned long size = 2 * page_size;
> +	unsigned long size = 12 * page_size;
>  	int ret;
>  	int prot;
>  
> -	/*
> -	 * Check if a partial mseal (that results in two vmas) works correctly.
> -	 * It might unmap the first, but it'll never unmap the second (msealed) vma.
> -	 */
> -
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
>  
>  	if (seal) {
> -		ret = sys_mseal(ptr + page_size, page_size);
> +		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
>  		FAIL_TEST_IF_FALSE(!ret);
>  	}
>  
> -	ret = sys_munmap(ptr, size);
> -	if (seal)
> +	ret = sys_munmap(ptr, 12 * page_size);
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +		size = get_vma_size(ptr + 4 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +		size = get_vma_size(ptr + 8 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
> +
> +	ret = sys_munmap(ptr, 6 * page_size);
>  	if (seal) {
> -		FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0);
> +		FAIL_TEST_IF_FALSE(ret < 0);
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +		size = get_vma_size(ptr + 4 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
>  		FAIL_TEST_IF_FALSE(prot == 0x4);
> -	}
> +
> +		size = get_vma_size(ptr + 8 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
> +		FAIL_TEST_IF_FALSE(!ret);
> +
> +	ret = sys_munmap(ptr + 6 * page_size, 6 * page_size);
> +	if (seal) {
> +		FAIL_TEST_IF_FALSE(ret < 0);
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +		size = get_vma_size(ptr + 4 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +		size = get_vma_size(ptr + 8 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
> +		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
>  }
> @@ -1074,9 +1262,11 @@ static void test_munmap_start_freed(bool seal)
>  	ret = sys_munmap(ptr, size);
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
>  
>  		size = get_vma_size(ptr + page_size, &prot);
> -		FAIL_TEST_IF_FALSE(size == page_size * 3);
> +		FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else {
>  		/* note: this will be OK, even the first page is */
>  		/* already unmapped. */
> @@ -1095,6 +1285,7 @@ static void test_munmap_end_freed(bool seal)
>  	unsigned long page_size = getpagesize();
>  	unsigned long size = 4 * page_size;
>  	int ret;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1111,9 +1302,14 @@ static void test_munmap_end_freed(bool seal)
>  
>  	/* unmap all pages. */
>  	ret = sys_munmap(ptr, size);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	REPORT_TEST_PASS();
> @@ -1144,12 +1340,15 @@ static void test_munmap_middle_freed(bool seal)
>  	ret = sys_munmap(ptr, size);
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
>  
>  		size = get_vma_size(ptr, &prot);
>  		FAIL_TEST_IF_FALSE(size == page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  
>  		size = get_vma_size(ptr + page_size * 3, &prot);
>  		FAIL_TEST_IF_FALSE(size == page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else {
>  		FAIL_TEST_IF_FALSE(!ret);
>  
> @@ -1170,6 +1369,7 @@ static void test_seal_mremap_shrink(bool seal)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1184,6 +1384,10 @@ static void test_seal_mremap_shrink(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else {
>  		FAIL_TEST_IF_FALSE(ret2 != (void *) MAP_FAILED);
>  
> @@ -1199,6 +1403,7 @@ static void test_seal_mremap_expand(bool seal)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1216,6 +1421,10 @@ static void test_seal_mremap_expand(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else {
>  		FAIL_TEST_IF_FALSE(ret2 == ptr);
>  
> @@ -1231,6 +1440,7 @@ static void test_seal_mremap_move(bool seal)
>  	unsigned long size = page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1249,10 +1459,12 @@ static void test_seal_mremap_move(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> -	} else {
> -		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
>  
> -	}
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size ==  page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
> +		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
>  
>  	REPORT_TEST_PASS();
>  }
> @@ -1264,6 +1476,7 @@ static void test_seal_mmap_overwrite_prot(bool seal)
>  	unsigned long size = page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1279,6 +1492,10 @@ static void test_seal_mmap_overwrite_prot(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else
>  		FAIL_TEST_IF_FALSE(ret2 == ptr);
>  
> @@ -1292,6 +1509,7 @@ static void test_seal_mmap_expand(bool seal)
>  	unsigned long size = 12 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1310,6 +1528,10 @@ static void test_seal_mmap_expand(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 8 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else
>  		FAIL_TEST_IF_FALSE(ret2 == ptr);
>  
> @@ -1323,6 +1545,7 @@ static void test_seal_mmap_shrink(bool seal)
>  	unsigned long size = 12 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1338,6 +1561,10 @@ static void test_seal_mmap_shrink(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 12 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else
>  		FAIL_TEST_IF_FALSE(ret2 == ptr);
>  
> @@ -1352,6 +1579,7 @@ static void test_seal_mremap_shrink_fixed(bool seal)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1369,6 +1597,10 @@ static void test_seal_mremap_shrink_fixed(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else
>  		FAIL_TEST_IF_FALSE(ret2 == newAddr);
>  
> @@ -1383,6 +1615,7 @@ static void test_seal_mremap_expand_fixed(bool seal)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(page_size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1400,6 +1633,10 @@ static void test_seal_mremap_expand_fixed(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(newAddr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else
>  		FAIL_TEST_IF_FALSE(ret2 == newAddr);
>  
> @@ -1414,6 +1651,7 @@ static void test_seal_mremap_move_fixed(bool seal)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1430,6 +1668,10 @@ static void test_seal_mremap_move_fixed(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(newAddr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else
>  		FAIL_TEST_IF_FALSE(ret2 == newAddr);
>  
> @@ -1443,6 +1685,7 @@ static void test_seal_mremap_move_fixed_zero(bool seal)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1460,9 +1703,12 @@ static void test_seal_mremap_move_fixed_zero(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> -	} else {
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
>  		FAIL_TEST_IF_FALSE(ret2 == 0);
> -	}
>  
>  	REPORT_TEST_PASS();
>  }
> @@ -1474,6 +1720,7 @@ static void test_seal_mremap_move_dontunmap(bool seal)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1488,6 +1735,10 @@ static void test_seal_mremap_move_dontunmap(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else {
>  		/* kernel will allocate a new address */
>  		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
> @@ -1503,6 +1754,7 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
>  	unsigned long size = 4 * page_size;
>  	int ret;
>  	void *ret2;
> +	int prot;
>  
>  	setup_single_address(size, &ptr);
>  	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> @@ -1529,6 +1781,10 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
>  	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
>  		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
>  	} else {
>  		/* remap success and return ptr2 */
>  		FAIL_TEST_IF_FALSE(ret2 ==  ptr2);
> @@ -1690,9 +1946,10 @@ static void test_seal_discard_ro_anon_on_pkey(bool seal)
>  	/* sealing will take effect if PKRU deny write. */
>  	set_pkey(pkey, PKEY_DISABLE_WRITE);
>  	ret = sys_madvise(ptr, size, MADV_DONTNEED);
> -	if (seal)
> +	if (seal) {
>  		FAIL_TEST_IF_FALSE(ret < 0);
> -	else
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +	} else
>  		FAIL_TEST_IF_FALSE(!ret);
>  
>  	/* base seal still apply. */

FWIW I can't review any of the above. It's still a hard to review patch with a bunch of unrelated changes
including VMA size, random errno checks, random vma size checks, etc.

Maybe break this down in separate patches.

> @@ -1876,6 +2133,15 @@ int main(int argc, char **argv)
>  	if (!pkey_supported())
>  		ksft_print_msg("PKEY not supported\n");
>  
> +	/*
> +	 * Possible reasons:
> +	 * - unable to read /proc/pid/maps (unlikely)
> +	 * - parsing error when reading /proc/pid/maps,e.g. len is not expected.
> +	 *   Is this "TOPDOWN" mapping or format change in /proc/pid/maps ?

Why do we care? I don't think running selftests without a procfs mount is supported in any way...
Format won't change.

-- 
Pedro


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] selftests/mm: mseal_test add sealed madvise type
  2024-08-29 21:43 ` [PATCH v2 2/4] selftests/mm: mseal_test add sealed madvise type jeffxu
@ 2024-08-30 12:52   ` Pedro Falcato
  2024-08-30 15:46     ` Jeff Xu
  0 siblings, 1 reply; 13+ messages in thread
From: Pedro Falcato @ 2024-08-30 12:52 UTC (permalink / raw)
  To: jeffxu
  Cc: akpm, linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	willy, lorenzo.stoakes, broonie, vbabka, Liam.Howlett, rientjes,
	keescook

On Thu, Aug 29, 2024 at 09:43:50PM GMT, jeffxu@chromium.org wrote:
> From: Jeff Xu <jeffxu@chromium.org>
> 
> Add a testcase to cover all sealed madvise type.
> 
> Signed-off-by: Jeff Xu <jeffxu@chromium.org>
> ---
>  tools/testing/selftests/mm/mseal_test.c | 108 +++++++++++++++++++++++-
>  1 file changed, 107 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
> index adc646cf576c..ae06c354220d 100644
> --- a/tools/testing/selftests/mm/mseal_test.c
> +++ b/tools/testing/selftests/mm/mseal_test.c
> @@ -2121,6 +2121,107 @@ static void test_seal_madvise_nodiscard(bool seal)
>  	REPORT_TEST_PASS();
>  }
>  
> +static void test_seal_discard_madvise_advice(void)
> +{
> +	void *ptr;
> +	unsigned long page_size = getpagesize();
> +	unsigned long size = 4 * page_size;
> +	int ret;
> +	int sealed_advice[] = {MADV_FREE, MADV_DONTNEED,
> +		MADV_DONTNEED_LOCKED, MADV_REMOVE,
> +		MADV_DONTFORK, MADV_WIPEONFORK};
> +	int size_sealed_advice = sizeof(sealed_advice) / sizeof(int);
> +
> +	setup_single_address(size, &ptr);
> +	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> +
> +	ret = seal_single_address(ptr, size);
> +	FAIL_TEST_IF_FALSE(!ret);
> +
> +	for (int i = 0; i < size_sealed_advice; i++) {
> +		ret = sys_madvise(ptr, size, sealed_advice[i]);
> +		FAIL_TEST_IF_FALSE(ret < 0);
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +	}
> +
> +	REPORT_TEST_PASS();
> +}

This can replace some of the other 9 discard tests already there, no?

> +
> +static void test_munmap_free_multiple_ranges(bool seal)
> +{
> +	void *ptr;
> +	unsigned long page_size = getpagesize();
> +	unsigned long size = 8 * page_size;
> +	int ret;
> +	int prot;
> +
> +	setup_single_address(size, &ptr);
> +	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> +
> +	/* unmap one page from beginning. */
> +	ret = sys_munmap(ptr, page_size);
> +	FAIL_TEST_IF_FALSE(!ret);
> +
> +	/* unmap one page from middle. */
> +	ret = sys_munmap(ptr + 4 * page_size, page_size);
> +	FAIL_TEST_IF_FALSE(!ret);
> +
> +	size = get_vma_size(ptr + page_size, &prot);
> +	FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +	FAIL_TEST_IF_FALSE(prot == 4);
> +
> +	size = get_vma_size(ptr +  5 * page_size, &prot);
> +	FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +	FAIL_TEST_IF_FALSE(prot == 4);
> +
> +
> +	/* seal the last page */
> +	if (seal) {
> +		ret = sys_mseal(ptr + 7 * page_size, page_size);
> +		FAIL_TEST_IF_FALSE(!ret);
> +
> +		size = get_vma_size(ptr +  1 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 4);
> +
> +		size = get_vma_size(ptr +  5 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 4);
> +
> +		size = get_vma_size(ptr +  7 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 4);
> +	}
> +
> +	/* munmap all 8  pages from beginning */
> +	ret = sys_munmap(ptr, 8 * page_size);
> +	if (seal) {
> +		FAIL_TEST_IF_FALSE(ret);
> +
> +		/* verify mapping are not changed */
> +		size = get_vma_size(ptr + 1 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 3 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 4);
> +
> +		size = get_vma_size(ptr +  5 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 2 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 4);
> +
> +		size = get_vma_size(ptr +  7 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 1 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 4);
> +	} else {
> +		FAIL_TEST_IF_FALSE(!ret);
> +
> +		for (int i = 0; i < 8; i++) {
> +			size = get_vma_size(ptr, &prot);
> +			FAIL_TEST_IF_FALSE(size == 0);
> +		}
> +	}
> +
> +	REPORT_TEST_PASS();
> +}

Unrelated munmap change.

-- 
Pedro


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/4] selftests/mm: mseal_test add more tests for mmap
  2024-08-29 21:43 ` [PATCH v2 3/4] selftests/mm: mseal_test add more tests for mmap jeffxu
@ 2024-08-30 12:57   ` Pedro Falcato
  2024-08-30 15:52     ` Jeff Xu
  0 siblings, 1 reply; 13+ messages in thread
From: Pedro Falcato @ 2024-08-30 12:57 UTC (permalink / raw)
  To: jeffxu
  Cc: akpm, linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	willy, lorenzo.stoakes, broonie, vbabka, Liam.Howlett, rientjes,
	keescook

On Thu, Aug 29, 2024 at 09:43:51PM GMT, jeffxu@chromium.org wrote:
> From: Jeff Xu <jeffxu@chromium.org>
> 
> Add sealing test to cover mmap for
> Expand/shrink across vmas.
> Reuse the same address in !MAP_FIXED case.
> 
> Signed-off-by: Jeff Xu <jeffxu@chromium.org>
> ---
>  tools/testing/selftests/mm/mseal_test.c | 125 +++++++++++++++++++++++-
>  1 file changed, 124 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
> index ae06c354220d..d83538039e76 100644
> --- a/tools/testing/selftests/mm/mseal_test.c
> +++ b/tools/testing/selftests/mm/mseal_test.c
> @@ -2222,6 +2222,122 @@ static void test_munmap_free_multiple_ranges(bool seal)
>  	REPORT_TEST_PASS();
>  }
>  
> +static void test_seal_mmap_expand_seal_middle(bool seal)
> +{
> +	void *ptr;
> +	unsigned long page_size = getpagesize();
> +	unsigned long size = 12 * page_size;
> +	int ret;
> +	void *ret2;
> +	int prot;
> +
> +	setup_single_address(size, &ptr);
> +	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> +	/* ummap last 4 pages. */
> +	ret = sys_munmap(ptr + 8 * page_size, 4 * page_size);
> +	FAIL_TEST_IF_FALSE(!ret);
> +
> +	size = get_vma_size(ptr, &prot);
> +	FAIL_TEST_IF_FALSE(size == 8 * page_size);
> +	FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +	if (seal) {
> +		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
> +		FAIL_TEST_IF_FALSE(!ret);
> +	}
> +
> +	/* use mmap to expand. */
> +	ret2 = mmap(ptr, 12 * page_size, PROT_READ,
> +			MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);

This is not expansion, but overwriting. Expansion is allowed through an adjacent mmap + mseal (which will merge the two VMAs).

> +	if (seal) {
> +		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +		size = get_vma_size(ptr + 4 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
> +		FAIL_TEST_IF_FALSE(ret2 == ptr);
> +
> +	REPORT_TEST_PASS();
> +}
> +
> +static void test_seal_mmap_shrink_seal_middle(bool seal)
> +{
> +	void *ptr;
> +	unsigned long page_size = getpagesize();
> +	unsigned long size = 12 * page_size;
> +	int ret;
> +	void *ret2;
> +	int prot;
> +
> +	setup_single_address(size, &ptr);
> +	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> +
> +	if (seal) {
> +		ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
> +		FAIL_TEST_IF_FALSE(!ret);
> +	}
> +
> +	/* use mmap to shrink. */
> +	ret2 = mmap(ptr, 7 * page_size, PROT_READ,
> +			MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);

This is also a partial overwrite.

> +	if (seal) {
> +		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> +		FAIL_TEST_IF_FALSE(errno == EPERM);
> +
> +		size = get_vma_size(ptr, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +		size = get_vma_size(ptr + 4 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +
> +		size = get_vma_size(ptr + 4 * page_size, &prot);
> +		FAIL_TEST_IF_FALSE(size == 4 * page_size);
> +		FAIL_TEST_IF_FALSE(prot == 0x4);
> +	} else
> +		FAIL_TEST_IF_FALSE(ret2 == ptr);
> +
> +	REPORT_TEST_PASS();
> +}
> +
> +static void test_seal_mmap_reuse_addr(bool seal)
> +{
> +	void *ptr;
> +	unsigned long page_size = getpagesize();
> +	unsigned long size = page_size;
> +	int ret;
> +	void *ret2;
> +	int prot;
> +
> +	setup_single_address(size, &ptr);
> +	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> +
> +	if (seal) {
> +		ret = sys_mseal(ptr, size);
> +		FAIL_TEST_IF_FALSE(!ret);
> +	}
> +
> +	/* use mmap to change protection. */
> +	ret2 = mmap(ptr, size, PROT_NONE,
> +			MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> +

This is also an overwrite. You're semantically testing the same thing, and testing the same regions of code.
These 3 tests are all kind of the same thing.

-- 
Pedro


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 0/4] Increase mseal test coverage
  2024-08-30 12:31 ` [PATCH v2 0/4] Increase mseal test coverage Pedro Falcato
@ 2024-08-30 15:38   ` Jeff Xu
  0 siblings, 0 replies; 13+ messages in thread
From: Jeff Xu @ 2024-08-30 15:38 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: akpm, linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	willy, lorenzo.stoakes, broonie, vbabka, Liam.Howlett, rientjes,
	keescook

Hi Pedro

On Fri, Aug 30, 2024 at 5:31 AM Pedro Falcato <pedro.falcato@gmail.com> wrote:
>
> On Thu, Aug 29, 2024 at 09:43:48PM GMT, jeffxu@chromium.org wrote:
> > From: Jeff Xu <jeffxu@chromium.org>
> >
> > This series increase the test coverage of mseal_test by:
> >
> > Add check for vma_size, prot, and error code for existing tests.
> > Add more testcases for madvise, munmap, mmap and mremap to cover
> > sealing in different scenarios.
> >
> > The increase test coverage hopefully help to prevent future regression.
> > It doesn't change any existing mm api's semantics, i.e. it will pass on
> > linux main and 6.10 branch.
>
> I do want to be clear that we shouldn't confuse "test coverage" with being unequivocally good
> if it has the possibility to paint ourselves into an API corner where details that should be left
> unspecified are instead set in stone (e.g do we want to test how mprotect behaves if it finds an msealed
> vma midway? no, apart from the property that really matters in this case (that sealed vmas remain untouched)).
>
I do not disagree with this. Let's look through code and comment on
the case directly if there is such a case.

Thanks.
-Jeff

> >
> > Note: in order to pass this test in mm-unstable, mm-unstable must have
> > Liam's fix on mmap [1]
> >
> > [1] https://lore.kernel.org/linux-kselftest/vyllxuh5xbqmaoyl2mselebij5ox7cseekjcvl5gmzoxxwd2he@hxi4mpjanxzt/#t
> >
> > History:
> > V2:
> > - remove the mmap fix (Liam R. Howlett will fix it separately)
> > - Add cover letter (Lorenzo Stoakes)
> > - split the testcase for ease of review (Mark Brown)
> >
> > V1:
> > - https://lore.kernel.org/linux-kselftest/20240828225522.684774-1-jeffxu@chromium.org/
> >
> > Jeff Xu (4):
> >   selftests/mm: mseal_test, add vma size check
> >   selftests/mm: mseal_test add sealed madvise type
> >   selftests/mm: mseal_test add more tests for mmap
> >   selftests/mm: mseal_test add more tests for mremap
> >
>
> nit: Please follow a more standard commit naming scheme like
>         selftests/mm: <change description>
> or
>         selftests/mseal: <change description>
>
> --
> Pedro


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 1/4] selftests/mm: mseal_test, add vma size check
  2024-08-30 12:45   ` Pedro Falcato
@ 2024-08-30 15:45     ` Jeff Xu
  0 siblings, 0 replies; 13+ messages in thread
From: Jeff Xu @ 2024-08-30 15:45 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: akpm, linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	willy, lorenzo.stoakes, broonie, vbabka, Liam.Howlett, rientjes,
	keescook

Hi Pedro

On Fri, Aug 30, 2024 at 5:45 AM Pedro Falcato <pedro.falcato@gmail.com> wrote:
>
> On Thu, Aug 29, 2024 at 09:43:49PM GMT, jeffxu@chromium.org wrote:
> > From: Jeff Xu <jeffxu@chromium.org>
> >
> > Add check for vma size, prot bits and error return.
> >
> > Signed-off-by: Jeff Xu <jeffxu@chromium.org>
> > ---
> >  tools/testing/selftests/mm/mseal_test.c | 398 ++++++++++++++++++++----
> >  1 file changed, 332 insertions(+), 66 deletions(-)
> >
> > diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
> > index e7991e5fdcf3..adc646cf576c 100644
> > --- a/tools/testing/selftests/mm/mseal_test.c
> > +++ b/tools/testing/selftests/mm/mseal_test.c
> > @@ -170,18 +170,31 @@ static void set_pkey(int pkey, unsigned long pkey_value)
> >  static void setup_single_address(int size, void **ptrOut)
> >  {
> >       void *ptr;
> > +     unsigned long page_size = getpagesize();
> >
> > -     ptr = mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> > -     *ptrOut = ptr;
> > +     *ptrOut = (void *)-1;
> > +     ptr = mmap(NULL, size + 2 * page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> > +     if (ptr != (void *) -1) {
>
> MAP_FAILED, not (void *) -1
>
ok.

> > +             /* add 2 page at the beginning and end to avoid auto-merge of mapping */
> > +             sys_mprotect(ptr, page_size, PROT_NONE);
> > +             sys_mprotect(ptr + size + page_size, page_size, PROT_NONE);
> > +             *ptrOut = ptr + page_size;
> > +     }
> >  }
> >
> >  static void setup_single_address_rw(int size, void **ptrOut)
> >  {
> >       void *ptr;
> >       unsigned long mapflags = MAP_ANONYMOUS | MAP_PRIVATE;
> > +     unsigned long page_size = getpagesize();
> >
> > -     ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mapflags, -1, 0);
> > -     *ptrOut = ptr;
> > +     *ptrOut = (void *)-1;
> > +     ptr = mmap(NULL, size + 2 * page_size, PROT_READ | PROT_WRITE, mapflags, -1, 0);
> > +     if (ptr != (void *) -1) {
>
> Same here.
ok.

> > +             sys_mprotect(ptr, page_size, PROT_NONE);
> > +             sys_mprotect(ptr + size + page_size, page_size, PROT_NONE);
> > +             *ptrOut = ptr + page_size;
> > +     }
> >  }
> >
> >  static int clean_single_address(void *ptr, int size)
> > @@ -226,6 +239,21 @@ bool pkey_supported(void)
> >       return false;
> >  }
> >
> > +bool get_vma_size_supported(void)
> > +{
> > +     void *ptr;
> > +     unsigned long page_size = getpagesize();
> > +     unsigned long size = 4 * page_size;
> > +     int prot;
> > +
> > +     setup_single_address(size, &ptr);
> > +     size = get_vma_size(ptr, &prot);
> > +     if (size == 4 * page_size && prot == 0x4)
> > +             return true;
> > +
> > +     return false;
> > +}
> > +
> >  static void test_seal_addseal(void)
> >  {
> >       int ret;
> > @@ -419,11 +447,17 @@ static void test_seal_invalid_input(void)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >
> > -     setup_single_address(8 * page_size, &ptr);
> > +     setup_single_address(9 * page_size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > -     ret = clean_single_address(ptr + 4 * page_size, 4 * page_size);
> > +
> > +     ret = clean_single_address(ptr, page_size);
> >       FAIL_TEST_IF_FALSE(!ret);
> >
> > +     ret = clean_single_address(ptr + 5 * page_size, 4 * page_size);
> > +     FAIL_TEST_IF_FALSE(!ret);
> > +
> > +     ptr = ptr + page_size;
> > +
> >       /* invalid flag */
> >       ret = syscall(__NR_mseal, ptr, size, 0x20);
> >       FAIL_TEST_IF_FALSE(ret < 0);
> > @@ -523,6 +557,7 @@ static void test_seal_mprotect(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -533,9 +568,14 @@ static void test_seal_mprotect(bool seal)
> >       }
> >
> >       ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> > @@ -547,6 +587,7 @@ static void test_seal_start_mprotect(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -558,9 +599,14 @@ static void test_seal_start_mprotect(bool seal)
> >
> >       /* the first page is sealed. */
> >       ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       /* pages after the first page is not sealed. */
> > @@ -577,6 +623,7 @@ static void test_seal_end_mprotect(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -593,9 +640,14 @@ static void test_seal_end_mprotect(bool seal)
> >       /* last 3 page are sealed */
> >       ret = sys_mprotect(ptr + page_size, page_size * 3,
> >                       PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr + page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> > @@ -607,6 +659,7 @@ static void test_seal_mprotect_unalign_len(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -618,9 +671,14 @@ static void test_seal_mprotect_unalign_len(bool seal)
> >
> >       /* 2 pages are sealed. */
> >       ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       ret = sys_mprotect(ptr + page_size * 2, page_size,
> > @@ -636,6 +694,7 @@ static void test_seal_mprotect_unalign_len_variant_2(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -646,9 +705,14 @@ static void test_seal_mprotect_unalign_len_variant_2(bool seal)
> >
> >       /* 3 pages are sealed. */
> >       ret = sys_mprotect(ptr, page_size * 3, PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       ret = sys_mprotect(ptr + page_size * 3, page_size,
> > @@ -664,6 +728,7 @@ static void test_seal_mprotect_two_vma(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -678,16 +743,26 @@ static void test_seal_mprotect_two_vma(bool seal)
> >       }
> >
> >       ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x6);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       ret = sys_mprotect(ptr + page_size * 2, page_size * 2,
> >                       PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr + page_size * 2, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> > @@ -699,6 +774,7 @@ static void test_seal_mprotect_two_vma_with_split(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -719,17 +795,27 @@ static void test_seal_mprotect_two_vma_with_split(bool seal)
> >
> >       /* the second page is sealed. */
> >       ret = sys_mprotect(ptr + page_size, page_size, PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x6);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       /* the third page is sealed. */
> >       ret = sys_mprotect(ptr + 2 * page_size, page_size,
> >                       PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr + 2 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       /* the fouth page is not sealed. */
> > @@ -746,6 +832,7 @@ static void test_seal_mprotect_partial_mprotect(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -758,9 +845,14 @@ static void test_seal_mprotect_partial_mprotect(bool seal)
> >
> >       /* mprotect first 2 page will fail, since the first page are sealed. */
> >       ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> > @@ -783,15 +875,15 @@ static void test_seal_mprotect_partial_mprotect_tail(bool seal)
> >       }
> >
> >       ret = sys_mprotect(ptr, size, PROT_EXEC);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > -             FAIL_TEST_IF_FALSE(!ret);
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> >
> > -     if (seal) {
> > -             FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0);
> > +             size = get_vma_size(ptr + page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> >               FAIL_TEST_IF_FALSE(prot == 0x4);
> > -     }
> > +     } else
> > +             FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> >  }
> > @@ -846,6 +938,7 @@ static void test_seal_mprotect_split(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -862,16 +955,34 @@ static void test_seal_mprotect_split(bool seal)
> >
> >       /* mprotect is sealed. */
> >       ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x6);
> > +
> > +             size = get_vma_size(ptr + page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >
> >       ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x6);
> > +
> > +             size = get_vma_size(ptr + page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> > @@ -883,6 +994,7 @@ static void test_seal_mprotect_merge(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -899,9 +1011,18 @@ static void test_seal_mprotect_merge(bool seal)
> >
> >       /* 2 pages are sealed. */
> >       ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x6);
> > +
> > +             size = get_vma_size(ptr + page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       /* last 2 pages are not sealed. */
> > @@ -917,6 +1038,7 @@ static void test_seal_munmap(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -928,9 +1050,14 @@ static void test_seal_munmap(bool seal)
> >
> >       /* 4 pages are sealed. */
> >       ret = sys_munmap(ptr, size);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> > @@ -948,6 +1075,7 @@ static void test_seal_munmap_two_vma(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -962,15 +1090,33 @@ static void test_seal_munmap_two_vma(bool seal)
> >       }
> >
> >       ret = sys_munmap(ptr, page_size * 2);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x6);
> > +
> > +             size = get_vma_size(ptr + 2 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       ret = sys_munmap(ptr + page_size, page_size * 2);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x6);
> > +
> > +             size = get_vma_size(ptr + 2 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> > @@ -1018,33 +1164,75 @@ static void test_seal_munmap_partial_across_vmas(bool seal)
> >  {
> >       void *ptr;
> >       unsigned long page_size = getpagesize();
> > -     unsigned long size = 2 * page_size;
> > +     unsigned long size = 12 * page_size;
> >       int ret;
> >       int prot;
> >
> > -     /*
> > -      * Check if a partial mseal (that results in two vmas) works correctly.
> > -      * It might unmap the first, but it'll never unmap the second (msealed) vma.
> > -      */
> > -
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> >
> >       if (seal) {
> > -             ret = sys_mseal(ptr + page_size, page_size);
> > +             ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
> >               FAIL_TEST_IF_FALSE(!ret);
> >       }
> >
> > -     ret = sys_munmap(ptr, size);
> > -     if (seal)
> > +     ret = sys_munmap(ptr, 12 * page_size);
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +             size = get_vma_size(ptr + 4 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +             size = get_vma_size(ptr + 8 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> > +
> > +     ret = sys_munmap(ptr, 6 * page_size);
> >       if (seal) {
> > -             FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0);
> > +             FAIL_TEST_IF_FALSE(ret < 0);
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +             size = get_vma_size(ptr + 4 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> >               FAIL_TEST_IF_FALSE(prot == 0x4);
> > -     }
> > +
> > +             size = get_vma_size(ptr + 8 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> > +             FAIL_TEST_IF_FALSE(!ret);
> > +
> > +     ret = sys_munmap(ptr + 6 * page_size, 6 * page_size);
> > +     if (seal) {
> > +             FAIL_TEST_IF_FALSE(ret < 0);
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +             size = get_vma_size(ptr + 4 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +             size = get_vma_size(ptr + 8 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> > +             FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> >  }
> > @@ -1074,9 +1262,11 @@ static void test_munmap_start_freed(bool seal)
> >       ret = sys_munmap(ptr, size);
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> >
> >               size = get_vma_size(ptr + page_size, &prot);
> > -             FAIL_TEST_IF_FALSE(size == page_size * 3);
> > +             FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else {
> >               /* note: this will be OK, even the first page is */
> >               /* already unmapped. */
> > @@ -1095,6 +1285,7 @@ static void test_munmap_end_freed(bool seal)
> >       unsigned long page_size = getpagesize();
> >       unsigned long size = 4 * page_size;
> >       int ret;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1111,9 +1302,14 @@ static void test_munmap_end_freed(bool seal)
> >
> >       /* unmap all pages. */
> >       ret = sys_munmap(ptr, size);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       REPORT_TEST_PASS();
> > @@ -1144,12 +1340,15 @@ static void test_munmap_middle_freed(bool seal)
> >       ret = sys_munmap(ptr, size);
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> >
> >               size = get_vma_size(ptr, &prot);
> >               FAIL_TEST_IF_FALSE(size == page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >
> >               size = get_vma_size(ptr + page_size * 3, &prot);
> >               FAIL_TEST_IF_FALSE(size == page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else {
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> > @@ -1170,6 +1369,7 @@ static void test_seal_mremap_shrink(bool seal)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1184,6 +1384,10 @@ static void test_seal_mremap_shrink(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else {
> >               FAIL_TEST_IF_FALSE(ret2 != (void *) MAP_FAILED);
> >
> > @@ -1199,6 +1403,7 @@ static void test_seal_mremap_expand(bool seal)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1216,6 +1421,10 @@ static void test_seal_mremap_expand(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else {
> >               FAIL_TEST_IF_FALSE(ret2 == ptr);
> >
> > @@ -1231,6 +1440,7 @@ static void test_seal_mremap_move(bool seal)
> >       unsigned long size = page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1249,10 +1459,12 @@ static void test_seal_mremap_move(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > -     } else {
> > -             FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
> >
> > -     }
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size ==  page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> > +             FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
> >
> >       REPORT_TEST_PASS();
> >  }
> > @@ -1264,6 +1476,7 @@ static void test_seal_mmap_overwrite_prot(bool seal)
> >       unsigned long size = page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1279,6 +1492,10 @@ static void test_seal_mmap_overwrite_prot(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else
> >               FAIL_TEST_IF_FALSE(ret2 == ptr);
> >
> > @@ -1292,6 +1509,7 @@ static void test_seal_mmap_expand(bool seal)
> >       unsigned long size = 12 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1310,6 +1528,10 @@ static void test_seal_mmap_expand(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 8 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else
> >               FAIL_TEST_IF_FALSE(ret2 == ptr);
> >
> > @@ -1323,6 +1545,7 @@ static void test_seal_mmap_shrink(bool seal)
> >       unsigned long size = 12 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1338,6 +1561,10 @@ static void test_seal_mmap_shrink(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 12 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else
> >               FAIL_TEST_IF_FALSE(ret2 == ptr);
> >
> > @@ -1352,6 +1579,7 @@ static void test_seal_mremap_shrink_fixed(bool seal)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1369,6 +1597,10 @@ static void test_seal_mremap_shrink_fixed(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else
> >               FAIL_TEST_IF_FALSE(ret2 == newAddr);
> >
> > @@ -1383,6 +1615,7 @@ static void test_seal_mremap_expand_fixed(bool seal)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(page_size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1400,6 +1633,10 @@ static void test_seal_mremap_expand_fixed(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(newAddr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else
> >               FAIL_TEST_IF_FALSE(ret2 == newAddr);
> >
> > @@ -1414,6 +1651,7 @@ static void test_seal_mremap_move_fixed(bool seal)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1430,6 +1668,10 @@ static void test_seal_mremap_move_fixed(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(newAddr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else
> >               FAIL_TEST_IF_FALSE(ret2 == newAddr);
> >
> > @@ -1443,6 +1685,7 @@ static void test_seal_mremap_move_fixed_zero(bool seal)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1460,9 +1703,12 @@ static void test_seal_mremap_move_fixed_zero(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > -     } else {
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> >               FAIL_TEST_IF_FALSE(ret2 == 0);
> > -     }
> >
> >       REPORT_TEST_PASS();
> >  }
> > @@ -1474,6 +1720,7 @@ static void test_seal_mremap_move_dontunmap(bool seal)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1488,6 +1735,10 @@ static void test_seal_mremap_move_dontunmap(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else {
> >               /* kernel will allocate a new address */
> >               FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
> > @@ -1503,6 +1754,7 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
> >       unsigned long size = 4 * page_size;
> >       int ret;
> >       void *ret2;
> > +     int prot;
> >
> >       setup_single_address(size, &ptr);
> >       FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > @@ -1529,6 +1781,10 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
> >       if (seal) {
> >               FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> >               FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> >       } else {
> >               /* remap success and return ptr2 */
> >               FAIL_TEST_IF_FALSE(ret2 ==  ptr2);
> > @@ -1690,9 +1946,10 @@ static void test_seal_discard_ro_anon_on_pkey(bool seal)
> >       /* sealing will take effect if PKRU deny write. */
> >       set_pkey(pkey, PKEY_DISABLE_WRITE);
> >       ret = sys_madvise(ptr, size, MADV_DONTNEED);
> > -     if (seal)
> > +     if (seal) {
> >               FAIL_TEST_IF_FALSE(ret < 0);
> > -     else
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +     } else
> >               FAIL_TEST_IF_FALSE(!ret);
> >
> >       /* base seal still apply. */
>
> FWIW I can't review any of the above. It's still a hard to review patch with a bunch of unrelated changes
> including VMA size, random errno checks, random vma size checks, etc.
>
The EPERM is the standard error code for modifying the sealed memory.
The vma size and prot is to verify the sealed memory isn't changed
after modifying the sealed memory.

Those are all "must-check" parts of verifying the sealing. Now,
previously with out-of-loop checks, there is no need to check any of
those because once EPERM is returned, nothing will be modified. With
in-loop change, this becomes necessary.  I do not think it is
reasonable to split the case further, i.e. go to the exact same
scenario multiple times to check different attributes of sealing.

Thanks
-Jeff


> Maybe break this down in separate patches.
>
> > @@ -1876,6 +2133,15 @@ int main(int argc, char **argv)
> >       if (!pkey_supported())
> >               ksft_print_msg("PKEY not supported\n");
> >
> > +     /*
> > +      * Possible reasons:
> > +      * - unable to read /proc/pid/maps (unlikely)
> > +      * - parsing error when reading /proc/pid/maps,e.g. len is not expected.
> > +      *   Is this "TOPDOWN" mapping or format change in /proc/pid/maps ?
>
> Why do we care? I don't think running selftests without a procfs mount is supported in any way...
> Format won't change.
>
> --
> Pedro


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 2/4] selftests/mm: mseal_test add sealed madvise type
  2024-08-30 12:52   ` Pedro Falcato
@ 2024-08-30 15:46     ` Jeff Xu
  0 siblings, 0 replies; 13+ messages in thread
From: Jeff Xu @ 2024-08-30 15:46 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: akpm, linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	willy, lorenzo.stoakes, broonie, vbabka, Liam.Howlett, rientjes,
	keescook

On Fri, Aug 30, 2024 at 5:52 AM Pedro Falcato <pedro.falcato@gmail.com> wrote:
>
> On Thu, Aug 29, 2024 at 09:43:50PM GMT, jeffxu@chromium.org wrote:
> > From: Jeff Xu <jeffxu@chromium.org>
> >
> > Add a testcase to cover all sealed madvise type.
> >
> > Signed-off-by: Jeff Xu <jeffxu@chromium.org>
> > ---
> >  tools/testing/selftests/mm/mseal_test.c | 108 +++++++++++++++++++++++-
> >  1 file changed, 107 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
> > index adc646cf576c..ae06c354220d 100644
> > --- a/tools/testing/selftests/mm/mseal_test.c
> > +++ b/tools/testing/selftests/mm/mseal_test.c
> > @@ -2121,6 +2121,107 @@ static void test_seal_madvise_nodiscard(bool seal)
> >       REPORT_TEST_PASS();
> >  }
> >
> > +static void test_seal_discard_madvise_advice(void)
> > +{
> > +     void *ptr;
> > +     unsigned long page_size = getpagesize();
> > +     unsigned long size = 4 * page_size;
> > +     int ret;
> > +     int sealed_advice[] = {MADV_FREE, MADV_DONTNEED,
> > +             MADV_DONTNEED_LOCKED, MADV_REMOVE,
> > +             MADV_DONTFORK, MADV_WIPEONFORK};
> > +     int size_sealed_advice = sizeof(sealed_advice) / sizeof(int);
> > +
> > +     setup_single_address(size, &ptr);
> > +     FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > +
> > +     ret = seal_single_address(ptr, size);
> > +     FAIL_TEST_IF_FALSE(!ret);
> > +
> > +     for (int i = 0; i < size_sealed_advice; i++) {
> > +             ret = sys_madvise(ptr, size, sealed_advice[i]);
> > +             FAIL_TEST_IF_FALSE(ret < 0);
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +     }
> > +
> > +     REPORT_TEST_PASS();
> > +}
>
> This can replace some of the other 9 discard tests already there, no?
>
No, this  is focused on enumerating all types.

> > +
> > +static void test_munmap_free_multiple_ranges(bool seal)
> > +{
> > +     void *ptr;
> > +     unsigned long page_size = getpagesize();
> > +     unsigned long size = 8 * page_size;
> > +     int ret;
> > +     int prot;
> > +
> > +     setup_single_address(size, &ptr);
> > +     FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > +
> > +     /* unmap one page from beginning. */
> > +     ret = sys_munmap(ptr, page_size);
> > +     FAIL_TEST_IF_FALSE(!ret);
> > +
> > +     /* unmap one page from middle. */
> > +     ret = sys_munmap(ptr + 4 * page_size, page_size);
> > +     FAIL_TEST_IF_FALSE(!ret);
> > +
> > +     size = get_vma_size(ptr + page_size, &prot);
> > +     FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +     FAIL_TEST_IF_FALSE(prot == 4);
> > +
> > +     size = get_vma_size(ptr +  5 * page_size, &prot);
> > +     FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +     FAIL_TEST_IF_FALSE(prot == 4);
> > +
> > +
> > +     /* seal the last page */
> > +     if (seal) {
> > +             ret = sys_mseal(ptr + 7 * page_size, page_size);
> > +             FAIL_TEST_IF_FALSE(!ret);
> > +
> > +             size = get_vma_size(ptr +  1 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 4);
> > +
> > +             size = get_vma_size(ptr +  5 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 4);
> > +
> > +             size = get_vma_size(ptr +  7 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 4);
> > +     }
> > +
> > +     /* munmap all 8  pages from beginning */
> > +     ret = sys_munmap(ptr, 8 * page_size);
> > +     if (seal) {
> > +             FAIL_TEST_IF_FALSE(ret);
> > +
> > +             /* verify mapping are not changed */
> > +             size = get_vma_size(ptr + 1 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 3 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 4);
> > +
> > +             size = get_vma_size(ptr +  5 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 2 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 4);
> > +
> > +             size = get_vma_size(ptr +  7 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 1 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 4);
> > +     } else {
> > +             FAIL_TEST_IF_FALSE(!ret);
> > +
> > +             for (int i = 0; i < 8; i++) {
> > +                     size = get_vma_size(ptr, &prot);
> > +                     FAIL_TEST_IF_FALSE(size == 0);
> > +             }
> > +     }
> > +
> > +     REPORT_TEST_PASS();
> > +}
>
> Unrelated munmap change.
will move.

>
> --
> Pedro


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 3/4] selftests/mm: mseal_test add more tests for mmap
  2024-08-30 12:57   ` Pedro Falcato
@ 2024-08-30 15:52     ` Jeff Xu
  0 siblings, 0 replies; 13+ messages in thread
From: Jeff Xu @ 2024-08-30 15:52 UTC (permalink / raw)
  To: Pedro Falcato
  Cc: akpm, linux-kselftest, linux-mm, linux-hardening, linux-kernel,
	willy, lorenzo.stoakes, broonie, vbabka, Liam.Howlett, rientjes,
	keescook

Hi Pedro

On Fri, Aug 30, 2024 at 5:57 AM Pedro Falcato <pedro.falcato@gmail.com> wrote:
>
> On Thu, Aug 29, 2024 at 09:43:51PM GMT, jeffxu@chromium.org wrote:
> > From: Jeff Xu <jeffxu@chromium.org>
> >
> > Add sealing test to cover mmap for
> > Expand/shrink across vmas.
> > Reuse the same address in !MAP_FIXED case.
> >
> > Signed-off-by: Jeff Xu <jeffxu@chromium.org>
> > ---
> >  tools/testing/selftests/mm/mseal_test.c | 125 +++++++++++++++++++++++-
> >  1 file changed, 124 insertions(+), 1 deletion(-)
> >
> > diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c
> > index ae06c354220d..d83538039e76 100644
> > --- a/tools/testing/selftests/mm/mseal_test.c
> > +++ b/tools/testing/selftests/mm/mseal_test.c
> > @@ -2222,6 +2222,122 @@ static void test_munmap_free_multiple_ranges(bool seal)
> >       REPORT_TEST_PASS();
> >  }
> >
> > +static void test_seal_mmap_expand_seal_middle(bool seal)
> > +{
> > +     void *ptr;
> > +     unsigned long page_size = getpagesize();
> > +     unsigned long size = 12 * page_size;
> > +     int ret;
> > +     void *ret2;
> > +     int prot;
> > +
> > +     setup_single_address(size, &ptr);
> > +     FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > +     /* ummap last 4 pages. */
> > +     ret = sys_munmap(ptr + 8 * page_size, 4 * page_size);
> > +     FAIL_TEST_IF_FALSE(!ret);
> > +
> > +     size = get_vma_size(ptr, &prot);
> > +     FAIL_TEST_IF_FALSE(size == 8 * page_size);
> > +     FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +     if (seal) {
> > +             ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(!ret);
> > +     }
> > +
> > +     /* use mmap to expand. */
> > +     ret2 = mmap(ptr, 12 * page_size, PROT_READ,
> > +                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
>
> This is not expansion, but overwriting. Expansion is allowed through an adjacent mmap + mseal (which will merge the two VMAs).

The mmap is trying to expand the address range beginning from ptr
(size 8 * page_size) to 12 * page_size. This is overwrite + expansion.

>
> > +     if (seal) {
> > +             FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +             size = get_vma_size(ptr + 4 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> > +             FAIL_TEST_IF_FALSE(ret2 == ptr);
> > +
> > +     REPORT_TEST_PASS();
> > +}
> > +
> > +static void test_seal_mmap_shrink_seal_middle(bool seal)
> > +{
> > +     void *ptr;
> > +     unsigned long page_size = getpagesize();
> > +     unsigned long size = 12 * page_size;
> > +     int ret;
> > +     void *ret2;
> > +     int prot;
> > +
> > +     setup_single_address(size, &ptr);
> > +     FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > +
> > +     if (seal) {
> > +             ret = sys_mseal(ptr + 4 * page_size, 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(!ret);
> > +     }
> > +
> > +     /* use mmap to shrink. */
> > +     ret2 = mmap(ptr, 7 * page_size, PROT_READ,
> > +                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
>
> This is also a partial overwrite.
The mmap is trying to shrink the address range beginning from ptr
(size 12 * page_size) to 8 * page_size. This is overwrite + shrink.

>
> > +     if (seal) {
> > +             FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
> > +             FAIL_TEST_IF_FALSE(errno == EPERM);
> > +
> > +             size = get_vma_size(ptr, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +             size = get_vma_size(ptr + 4 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +
> > +             size = get_vma_size(ptr + 4 * page_size, &prot);
> > +             FAIL_TEST_IF_FALSE(size == 4 * page_size);
> > +             FAIL_TEST_IF_FALSE(prot == 0x4);
> > +     } else
> > +             FAIL_TEST_IF_FALSE(ret2 == ptr);
> > +
> > +     REPORT_TEST_PASS();
> > +}
> > +
> > +static void test_seal_mmap_reuse_addr(bool seal)
> > +{
> > +     void *ptr;
> > +     unsigned long page_size = getpagesize();
> > +     unsigned long size = page_size;
> > +     int ret;
> > +     void *ret2;
> > +     int prot;
> > +
> > +     setup_single_address(size, &ptr);
> > +     FAIL_TEST_IF_FALSE(ptr != (void *)-1);
> > +
> > +     if (seal) {
> > +             ret = sys_mseal(ptr, size);
> > +             FAIL_TEST_IF_FALSE(!ret);
> > +     }
> > +
> > +     /* use mmap to change protection. */
> > +     ret2 = mmap(ptr, size, PROT_NONE,
> > +                     MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> > +
>
> This is also an overwrite. You're semantically testing the same thing, and testing the same regions of code.

This is not overwriting. MAP_FIXED is not used.

-Jeff

> These 3 tests are all kind of the same thing.
>
> --
> Pedro


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-08-30 15:53 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-08-29 21:43 [PATCH v2 0/4] Increase mseal test coverage jeffxu
2024-08-29 21:43 ` [PATCH v2 1/4] selftests/mm: mseal_test, add vma size check jeffxu
2024-08-30 12:45   ` Pedro Falcato
2024-08-30 15:45     ` Jeff Xu
2024-08-29 21:43 ` [PATCH v2 2/4] selftests/mm: mseal_test add sealed madvise type jeffxu
2024-08-30 12:52   ` Pedro Falcato
2024-08-30 15:46     ` Jeff Xu
2024-08-29 21:43 ` [PATCH v2 3/4] selftests/mm: mseal_test add more tests for mmap jeffxu
2024-08-30 12:57   ` Pedro Falcato
2024-08-30 15:52     ` Jeff Xu
2024-08-29 21:43 ` [PATCH v2 4/4] selftests/mm: mseal_test add more tests for mremap jeffxu
2024-08-30 12:31 ` [PATCH v2 0/4] Increase mseal test coverage Pedro Falcato
2024-08-30 15:38   ` Jeff Xu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox