xref: /linux/tools/testing/selftests/mm/mseal_test.c (revision ea04ef19ebdcd22e8a21054a19c2c8fefae011ce)
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 #include <linux/mman.h>
4 #include <sys/mman.h>
5 #include <stdint.h>
6 #include <unistd.h>
7 #include <string.h>
8 #include <sys/time.h>
9 #include <sys/resource.h>
10 #include <stdbool.h>
11 #include "../kselftest.h"
12 #include <syscall.h>
13 #include <errno.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <fcntl.h>
17 #include <sys/ioctl.h>
18 #include <sys/vfs.h>
19 #include <sys/stat.h>
20 
21 /*
22  * need those definition for manually build using gcc.
23  * gcc -I ../../../../usr/include   -DDEBUG -O3  -DDEBUG -O3 mseal_test.c -o mseal_test
24  */
25 #ifndef PKEY_DISABLE_ACCESS
26 # define PKEY_DISABLE_ACCESS    0x1
27 #endif
28 
29 #ifndef PKEY_DISABLE_WRITE
30 # define PKEY_DISABLE_WRITE     0x2
31 #endif
32 
33 #ifndef PKEY_BITS_PER_PKEY
34 #define PKEY_BITS_PER_PKEY      2
35 #endif
36 
37 #ifndef PKEY_MASK
38 #define PKEY_MASK       (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE)
39 #endif
40 
41 #define FAIL_TEST_IF_FALSE(c) do {\
42 		if (!(c)) {\
43 			ksft_test_result_fail("%s, line:%d\n", __func__, __LINE__);\
44 			goto test_end;\
45 		} \
46 	} \
47 	while (0)
48 
49 #define SKIP_TEST_IF_FALSE(c) do {\
50 		if (!(c)) {\
51 			ksft_test_result_skip("%s, line:%d\n", __func__, __LINE__);\
52 			goto test_end;\
53 		} \
54 	} \
55 	while (0)
56 
57 
58 #define TEST_END_CHECK() {\
59 		ksft_test_result_pass("%s\n", __func__);\
60 		return;\
61 test_end:\
62 		return;\
63 }
64 
65 #ifndef u64
66 #define u64 unsigned long long
67 #endif
68 
69 static unsigned long get_vma_size(void *addr, int *prot)
70 {
71 	FILE *maps;
72 	char line[256];
73 	int size = 0;
74 	uintptr_t  addr_start, addr_end;
75 	char protstr[5];
76 	*prot = 0;
77 
78 	maps = fopen("/proc/self/maps", "r");
79 	if (!maps)
80 		return 0;
81 
82 	while (fgets(line, sizeof(line), maps)) {
83 		if (sscanf(line, "%lx-%lx %4s", &addr_start, &addr_end, protstr) == 3) {
84 			if (addr_start == (uintptr_t) addr) {
85 				size = addr_end - addr_start;
86 				if (protstr[0] == 'r')
87 					*prot |= 0x4;
88 				if (protstr[1] == 'w')
89 					*prot |= 0x2;
90 				if (protstr[2] == 'x')
91 					*prot |= 0x1;
92 				break;
93 			}
94 		}
95 	}
96 	fclose(maps);
97 	return size;
98 }
99 
100 /*
101  * define sys_xyx to call syscall directly.
102  */
103 static int sys_mseal(void *start, size_t len)
104 {
105 	int sret;
106 
107 	errno = 0;
108 	sret = syscall(__NR_mseal, start, len, 0);
109 	return sret;
110 }
111 
112 static int sys_mprotect(void *ptr, size_t size, unsigned long prot)
113 {
114 	int sret;
115 
116 	errno = 0;
117 	sret = syscall(__NR_mprotect, ptr, size, prot);
118 	return sret;
119 }
120 
121 static int sys_mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
122 		unsigned long pkey)
123 {
124 	int sret;
125 
126 	errno = 0;
127 	sret = syscall(__NR_pkey_mprotect, ptr, size, orig_prot, pkey);
128 	return sret;
129 }
130 
131 static void *sys_mmap(void *addr, unsigned long len, unsigned long prot,
132 	unsigned long flags, unsigned long fd, unsigned long offset)
133 {
134 	void *sret;
135 
136 	errno = 0;
137 	sret = (void *) syscall(__NR_mmap, addr, len, prot,
138 		flags, fd, offset);
139 	return sret;
140 }
141 
142 static int sys_munmap(void *ptr, size_t size)
143 {
144 	int sret;
145 
146 	errno = 0;
147 	sret = syscall(__NR_munmap, ptr, size);
148 	return sret;
149 }
150 
151 static int sys_madvise(void *start, size_t len, int types)
152 {
153 	int sret;
154 
155 	errno = 0;
156 	sret = syscall(__NR_madvise, start, len, types);
157 	return sret;
158 }
159 
160 static int sys_pkey_alloc(unsigned long flags, unsigned long init_val)
161 {
162 	int ret = syscall(__NR_pkey_alloc, flags, init_val);
163 
164 	return ret;
165 }
166 
167 static unsigned int __read_pkey_reg(void)
168 {
169 	unsigned int pkey_reg = 0;
170 #if defined(__i386__) || defined(__x86_64__) /* arch */
171 	unsigned int eax, edx;
172 	unsigned int ecx = 0;
173 
174 	asm volatile(".byte 0x0f,0x01,0xee\n\t"
175 			: "=a" (eax), "=d" (edx)
176 			: "c" (ecx));
177 	pkey_reg = eax;
178 #endif
179 	return pkey_reg;
180 }
181 
182 static void __write_pkey_reg(u64 pkey_reg)
183 {
184 #if defined(__i386__) || defined(__x86_64__) /* arch */
185 	unsigned int eax = pkey_reg;
186 	unsigned int ecx = 0;
187 	unsigned int edx = 0;
188 
189 	asm volatile(".byte 0x0f,0x01,0xef\n\t"
190 			: : "a" (eax), "c" (ecx), "d" (edx));
191 #endif
192 }
193 
194 static unsigned long pkey_bit_position(int pkey)
195 {
196 	return pkey * PKEY_BITS_PER_PKEY;
197 }
198 
199 static u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
200 {
201 	unsigned long shift = pkey_bit_position(pkey);
202 
203 	/* mask out bits from pkey in old value */
204 	reg &= ~((u64)PKEY_MASK << shift);
205 	/* OR in new bits for pkey */
206 	reg |= (flags & PKEY_MASK) << shift;
207 	return reg;
208 }
209 
210 static void set_pkey(int pkey, unsigned long pkey_value)
211 {
212 	u64 new_pkey_reg;
213 
214 	new_pkey_reg = set_pkey_bits(__read_pkey_reg(), pkey, pkey_value);
215 	__write_pkey_reg(new_pkey_reg);
216 }
217 
218 static void setup_single_address(int size, void **ptrOut)
219 {
220 	void *ptr;
221 
222 	ptr = sys_mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
223 	*ptrOut = ptr;
224 }
225 
226 static void setup_single_address_rw(int size, void **ptrOut)
227 {
228 	void *ptr;
229 	unsigned long mapflags = MAP_ANONYMOUS | MAP_PRIVATE;
230 
231 	ptr = sys_mmap(NULL, size, PROT_READ | PROT_WRITE, mapflags, -1, 0);
232 	*ptrOut = ptr;
233 }
234 
235 static int clean_single_address(void *ptr, int size)
236 {
237 	int ret;
238 	ret = munmap(ptr, size);
239 	return ret;
240 }
241 
242 static int seal_single_address(void *ptr, int size)
243 {
244 	int ret;
245 	ret = sys_mseal(ptr, size);
246 	return ret;
247 }
248 
249 bool seal_support(void)
250 {
251 	int ret;
252 	void *ptr;
253 	unsigned long page_size = getpagesize();
254 
255 	ptr = sys_mmap(NULL, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
256 	if (ptr == (void *) -1)
257 		return false;
258 
259 	ret = sys_mseal(ptr, page_size);
260 	if (ret < 0)
261 		return false;
262 
263 	return true;
264 }
265 
266 bool pkey_supported(void)
267 {
268 #if defined(__i386__) || defined(__x86_64__) /* arch */
269 	int pkey = sys_pkey_alloc(0, 0);
270 
271 	if (pkey > 0)
272 		return true;
273 #endif
274 	return false;
275 }
276 
277 static void test_seal_addseal(void)
278 {
279 	int ret;
280 	void *ptr;
281 	unsigned long page_size = getpagesize();
282 	unsigned long size = 4 * page_size;
283 
284 	setup_single_address(size, &ptr);
285 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
286 
287 	ret = sys_mseal(ptr, size);
288 	FAIL_TEST_IF_FALSE(!ret);
289 
290 	TEST_END_CHECK();
291 }
292 
293 static void test_seal_unmapped_start(void)
294 {
295 	int ret;
296 	void *ptr;
297 	unsigned long page_size = getpagesize();
298 	unsigned long size = 4 * page_size;
299 
300 	setup_single_address(size, &ptr);
301 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
302 
303 	/* munmap 2 pages from ptr. */
304 	ret = sys_munmap(ptr, 2 * page_size);
305 	FAIL_TEST_IF_FALSE(!ret);
306 
307 	/* mprotect will fail because 2 pages from ptr are unmapped. */
308 	ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
309 	FAIL_TEST_IF_FALSE(ret < 0);
310 
311 	/* mseal will fail because 2 pages from ptr are unmapped. */
312 	ret = sys_mseal(ptr, size);
313 	FAIL_TEST_IF_FALSE(ret < 0);
314 
315 	ret = sys_mseal(ptr + 2 * page_size, 2 * page_size);
316 	FAIL_TEST_IF_FALSE(!ret);
317 
318 	TEST_END_CHECK();
319 }
320 
321 static void test_seal_unmapped_middle(void)
322 {
323 	int ret;
324 	void *ptr;
325 	unsigned long page_size = getpagesize();
326 	unsigned long size = 4 * page_size;
327 
328 	setup_single_address(size, &ptr);
329 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
330 
331 	/* munmap 2 pages from ptr + page. */
332 	ret = sys_munmap(ptr + page_size, 2 * page_size);
333 	FAIL_TEST_IF_FALSE(!ret);
334 
335 	/* mprotect will fail, since middle 2 pages are unmapped. */
336 	ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
337 	FAIL_TEST_IF_FALSE(ret < 0);
338 
339 	/* mseal will fail as well. */
340 	ret = sys_mseal(ptr, size);
341 	FAIL_TEST_IF_FALSE(ret < 0);
342 
343 	/* we still can add seal to the first page and last page*/
344 	ret = sys_mseal(ptr, page_size);
345 	FAIL_TEST_IF_FALSE(!ret);
346 
347 	ret = sys_mseal(ptr + 3 * page_size, page_size);
348 	FAIL_TEST_IF_FALSE(!ret);
349 
350 	TEST_END_CHECK();
351 }
352 
353 static void test_seal_unmapped_end(void)
354 {
355 	int ret;
356 	void *ptr;
357 	unsigned long page_size = getpagesize();
358 	unsigned long size = 4 * page_size;
359 
360 	setup_single_address(size, &ptr);
361 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
362 
363 	/* unmap last 2 pages. */
364 	ret = sys_munmap(ptr + 2 * page_size, 2 * page_size);
365 	FAIL_TEST_IF_FALSE(!ret);
366 
367 	/* mprotect will fail since last 2 pages are unmapped. */
368 	ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
369 	FAIL_TEST_IF_FALSE(ret < 0);
370 
371 	/* mseal will fail as well. */
372 	ret = sys_mseal(ptr, size);
373 	FAIL_TEST_IF_FALSE(ret < 0);
374 
375 	/* The first 2 pages is not sealed, and can add seals */
376 	ret = sys_mseal(ptr, 2 * page_size);
377 	FAIL_TEST_IF_FALSE(!ret);
378 
379 	TEST_END_CHECK();
380 }
381 
382 static void test_seal_multiple_vmas(void)
383 {
384 	int ret;
385 	void *ptr;
386 	unsigned long page_size = getpagesize();
387 	unsigned long size = 4 * page_size;
388 
389 	setup_single_address(size, &ptr);
390 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
391 
392 	/* use mprotect to split the vma into 3. */
393 	ret = sys_mprotect(ptr + page_size, 2 * page_size,
394 			PROT_READ | PROT_WRITE);
395 	FAIL_TEST_IF_FALSE(!ret);
396 
397 	/* mprotect will get applied to all 4 pages - 3 VMAs. */
398 	ret = sys_mprotect(ptr, size, PROT_READ);
399 	FAIL_TEST_IF_FALSE(!ret);
400 
401 	/* use mprotect to split the vma into 3. */
402 	ret = sys_mprotect(ptr + page_size, 2 * page_size,
403 			PROT_READ | PROT_WRITE);
404 	FAIL_TEST_IF_FALSE(!ret);
405 
406 	/* mseal get applied to all 4 pages - 3 VMAs. */
407 	ret = sys_mseal(ptr, size);
408 	FAIL_TEST_IF_FALSE(!ret);
409 
410 	TEST_END_CHECK();
411 }
412 
413 static void test_seal_split_start(void)
414 {
415 	int ret;
416 	void *ptr;
417 	unsigned long page_size = getpagesize();
418 	unsigned long size = 4 * page_size;
419 
420 	setup_single_address(size, &ptr);
421 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
422 
423 	/* use mprotect to split at middle */
424 	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE);
425 	FAIL_TEST_IF_FALSE(!ret);
426 
427 	/* seal the first page, this will split the VMA */
428 	ret = sys_mseal(ptr, page_size);
429 	FAIL_TEST_IF_FALSE(!ret);
430 
431 	/* add seal to the remain 3 pages */
432 	ret = sys_mseal(ptr + page_size, 3 * page_size);
433 	FAIL_TEST_IF_FALSE(!ret);
434 
435 	TEST_END_CHECK();
436 }
437 
438 static void test_seal_split_end(void)
439 {
440 	int ret;
441 	void *ptr;
442 	unsigned long page_size = getpagesize();
443 	unsigned long size = 4 * page_size;
444 
445 	setup_single_address(size, &ptr);
446 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
447 
448 	/* use mprotect to split at middle */
449 	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE);
450 	FAIL_TEST_IF_FALSE(!ret);
451 
452 	/* seal the last page */
453 	ret = sys_mseal(ptr + 3 * page_size, page_size);
454 	FAIL_TEST_IF_FALSE(!ret);
455 
456 	/* Adding seals to the first 3 pages */
457 	ret = sys_mseal(ptr, 3 * page_size);
458 	FAIL_TEST_IF_FALSE(!ret);
459 
460 	TEST_END_CHECK();
461 }
462 
463 static void test_seal_invalid_input(void)
464 {
465 	void *ptr;
466 	unsigned long page_size = getpagesize();
467 	unsigned long size = 4 * page_size;
468 	int ret;
469 
470 	setup_single_address(8 * page_size, &ptr);
471 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
472 	ret = clean_single_address(ptr + 4 * page_size, 4 * page_size);
473 	FAIL_TEST_IF_FALSE(!ret);
474 
475 	/* invalid flag */
476 	ret = syscall(__NR_mseal, ptr, size, 0x20);
477 	FAIL_TEST_IF_FALSE(ret < 0);
478 
479 	/* unaligned address */
480 	ret = sys_mseal(ptr + 1, 2 * page_size);
481 	FAIL_TEST_IF_FALSE(ret < 0);
482 
483 	/* length too big */
484 	ret = sys_mseal(ptr, 5 * page_size);
485 	FAIL_TEST_IF_FALSE(ret < 0);
486 
487 	/* length overflow */
488 	ret = sys_mseal(ptr, UINT64_MAX/page_size);
489 	FAIL_TEST_IF_FALSE(ret < 0);
490 
491 	/* start is not in a valid VMA */
492 	ret = sys_mseal(ptr - page_size, 5 * page_size);
493 	FAIL_TEST_IF_FALSE(ret < 0);
494 
495 	TEST_END_CHECK();
496 }
497 
498 static void test_seal_zero_length(void)
499 {
500 	void *ptr;
501 	unsigned long page_size = getpagesize();
502 	unsigned long size = 4 * page_size;
503 	int ret;
504 
505 	setup_single_address(size, &ptr);
506 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
507 
508 	ret = sys_mprotect(ptr, 0, PROT_READ | PROT_WRITE);
509 	FAIL_TEST_IF_FALSE(!ret);
510 
511 	/* seal 0 length will be OK, same as mprotect */
512 	ret = sys_mseal(ptr, 0);
513 	FAIL_TEST_IF_FALSE(!ret);
514 
515 	/* verify the 4 pages are not sealed by previous call. */
516 	ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
517 	FAIL_TEST_IF_FALSE(!ret);
518 
519 	TEST_END_CHECK();
520 }
521 
522 static void test_seal_zero_address(void)
523 {
524 	void *ptr;
525 	unsigned long page_size = getpagesize();
526 	unsigned long size = 4 * page_size;
527 	int ret;
528 	int prot;
529 
530 	/* use mmap to change protection. */
531 	ptr = sys_mmap(0, size, PROT_NONE,
532 			MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
533 	FAIL_TEST_IF_FALSE(ptr == 0);
534 
535 	size = get_vma_size(ptr, &prot);
536 	FAIL_TEST_IF_FALSE(size == 4 * page_size);
537 
538 	ret = sys_mseal(ptr, size);
539 	FAIL_TEST_IF_FALSE(!ret);
540 
541 	/* verify the 4 pages are sealed by previous call. */
542 	ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
543 	FAIL_TEST_IF_FALSE(ret);
544 
545 	TEST_END_CHECK();
546 }
547 
548 static void test_seal_twice(void)
549 {
550 	int ret;
551 	void *ptr;
552 	unsigned long page_size = getpagesize();
553 	unsigned long size = 4 * page_size;
554 
555 	setup_single_address(size, &ptr);
556 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
557 
558 	ret = sys_mseal(ptr, size);
559 	FAIL_TEST_IF_FALSE(!ret);
560 
561 	/* apply the same seal will be OK. idempotent. */
562 	ret = sys_mseal(ptr, size);
563 	FAIL_TEST_IF_FALSE(!ret);
564 
565 	TEST_END_CHECK();
566 }
567 
568 static void test_seal_mprotect(bool seal)
569 {
570 	void *ptr;
571 	unsigned long page_size = getpagesize();
572 	unsigned long size = 4 * page_size;
573 	int ret;
574 
575 	setup_single_address(size, &ptr);
576 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
577 
578 	if (seal) {
579 		ret = seal_single_address(ptr, size);
580 		FAIL_TEST_IF_FALSE(!ret);
581 	}
582 
583 	ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
584 	if (seal)
585 		FAIL_TEST_IF_FALSE(ret < 0);
586 	else
587 		FAIL_TEST_IF_FALSE(!ret);
588 
589 	TEST_END_CHECK();
590 }
591 
592 static void test_seal_start_mprotect(bool seal)
593 {
594 	void *ptr;
595 	unsigned long page_size = getpagesize();
596 	unsigned long size = 4 * page_size;
597 	int ret;
598 
599 	setup_single_address(size, &ptr);
600 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
601 
602 	if (seal) {
603 		ret = seal_single_address(ptr, page_size);
604 		FAIL_TEST_IF_FALSE(!ret);
605 	}
606 
607 	/* the first page is sealed. */
608 	ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
609 	if (seal)
610 		FAIL_TEST_IF_FALSE(ret < 0);
611 	else
612 		FAIL_TEST_IF_FALSE(!ret);
613 
614 	/* pages after the first page is not sealed. */
615 	ret = sys_mprotect(ptr + page_size, page_size * 3,
616 			PROT_READ | PROT_WRITE);
617 	FAIL_TEST_IF_FALSE(!ret);
618 
619 	TEST_END_CHECK();
620 }
621 
622 static void test_seal_end_mprotect(bool seal)
623 {
624 	void *ptr;
625 	unsigned long page_size = getpagesize();
626 	unsigned long size = 4 * page_size;
627 	int ret;
628 
629 	setup_single_address(size, &ptr);
630 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
631 
632 	if (seal) {
633 		ret = seal_single_address(ptr + page_size, 3 * page_size);
634 		FAIL_TEST_IF_FALSE(!ret);
635 	}
636 
637 	/* first page is not sealed */
638 	ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
639 	FAIL_TEST_IF_FALSE(!ret);
640 
641 	/* last 3 page are sealed */
642 	ret = sys_mprotect(ptr + page_size, page_size * 3,
643 			PROT_READ | PROT_WRITE);
644 	if (seal)
645 		FAIL_TEST_IF_FALSE(ret < 0);
646 	else
647 		FAIL_TEST_IF_FALSE(!ret);
648 
649 	TEST_END_CHECK();
650 }
651 
652 static void test_seal_mprotect_unalign_len(bool seal)
653 {
654 	void *ptr;
655 	unsigned long page_size = getpagesize();
656 	unsigned long size = 4 * page_size;
657 	int ret;
658 
659 	setup_single_address(size, &ptr);
660 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
661 
662 	if (seal) {
663 		ret = seal_single_address(ptr, page_size * 2 - 1);
664 		FAIL_TEST_IF_FALSE(!ret);
665 	}
666 
667 	/* 2 pages are sealed. */
668 	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
669 	if (seal)
670 		FAIL_TEST_IF_FALSE(ret < 0);
671 	else
672 		FAIL_TEST_IF_FALSE(!ret);
673 
674 	ret = sys_mprotect(ptr + page_size * 2, page_size,
675 			PROT_READ | PROT_WRITE);
676 	FAIL_TEST_IF_FALSE(!ret);
677 
678 	TEST_END_CHECK();
679 }
680 
681 static void test_seal_mprotect_unalign_len_variant_2(bool seal)
682 {
683 	void *ptr;
684 	unsigned long page_size = getpagesize();
685 	unsigned long size = 4 * page_size;
686 	int ret;
687 
688 	setup_single_address(size, &ptr);
689 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
690 	if (seal) {
691 		ret =  seal_single_address(ptr, page_size * 2 + 1);
692 		FAIL_TEST_IF_FALSE(!ret);
693 	}
694 
695 	/* 3 pages are sealed. */
696 	ret = sys_mprotect(ptr, page_size * 3, PROT_READ | PROT_WRITE);
697 	if (seal)
698 		FAIL_TEST_IF_FALSE(ret < 0);
699 	else
700 		FAIL_TEST_IF_FALSE(!ret);
701 
702 	ret = sys_mprotect(ptr + page_size * 3, page_size,
703 			PROT_READ | PROT_WRITE);
704 	FAIL_TEST_IF_FALSE(!ret);
705 
706 	TEST_END_CHECK();
707 }
708 
709 static void test_seal_mprotect_two_vma(bool seal)
710 {
711 	void *ptr;
712 	unsigned long page_size = getpagesize();
713 	unsigned long size = 4 * page_size;
714 	int ret;
715 
716 	setup_single_address(size, &ptr);
717 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
718 
719 	/* use mprotect to split */
720 	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
721 	FAIL_TEST_IF_FALSE(!ret);
722 
723 	if (seal) {
724 		ret = seal_single_address(ptr, page_size * 4);
725 		FAIL_TEST_IF_FALSE(!ret);
726 	}
727 
728 	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
729 	if (seal)
730 		FAIL_TEST_IF_FALSE(ret < 0);
731 	else
732 		FAIL_TEST_IF_FALSE(!ret);
733 
734 	ret = sys_mprotect(ptr + page_size * 2, page_size * 2,
735 			PROT_READ | PROT_WRITE);
736 	if (seal)
737 		FAIL_TEST_IF_FALSE(ret < 0);
738 	else
739 		FAIL_TEST_IF_FALSE(!ret);
740 
741 	TEST_END_CHECK();
742 }
743 
744 static void test_seal_mprotect_two_vma_with_split(bool seal)
745 {
746 	void *ptr;
747 	unsigned long page_size = getpagesize();
748 	unsigned long size = 4 * page_size;
749 	int ret;
750 
751 	setup_single_address(size, &ptr);
752 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
753 
754 	/* use mprotect to split as two vma. */
755 	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
756 	FAIL_TEST_IF_FALSE(!ret);
757 
758 	/* mseal can apply across 2 vma, also split them. */
759 	if (seal) {
760 		ret = seal_single_address(ptr + page_size, page_size * 2);
761 		FAIL_TEST_IF_FALSE(!ret);
762 	}
763 
764 	/* the first page is not sealed. */
765 	ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
766 	FAIL_TEST_IF_FALSE(!ret);
767 
768 	/* the second page is sealed. */
769 	ret = sys_mprotect(ptr + page_size, page_size, PROT_READ | PROT_WRITE);
770 	if (seal)
771 		FAIL_TEST_IF_FALSE(ret < 0);
772 	else
773 		FAIL_TEST_IF_FALSE(!ret);
774 
775 	/* the third page is sealed. */
776 	ret = sys_mprotect(ptr + 2 * page_size, page_size,
777 			PROT_READ | PROT_WRITE);
778 	if (seal)
779 		FAIL_TEST_IF_FALSE(ret < 0);
780 	else
781 		FAIL_TEST_IF_FALSE(!ret);
782 
783 	/* the fouth page is not sealed. */
784 	ret = sys_mprotect(ptr + 3 * page_size, page_size,
785 			PROT_READ | PROT_WRITE);
786 	FAIL_TEST_IF_FALSE(!ret);
787 
788 	TEST_END_CHECK();
789 }
790 
791 static void test_seal_mprotect_partial_mprotect(bool seal)
792 {
793 	void *ptr;
794 	unsigned long page_size = getpagesize();
795 	unsigned long size = 4 * page_size;
796 	int ret;
797 
798 	setup_single_address(size, &ptr);
799 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
800 
801 	/* seal one page. */
802 	if (seal) {
803 		ret = seal_single_address(ptr, page_size);
804 		FAIL_TEST_IF_FALSE(!ret);
805 	}
806 
807 	/* mprotect first 2 page will fail, since the first page are sealed. */
808 	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE);
809 	if (seal)
810 		FAIL_TEST_IF_FALSE(ret < 0);
811 	else
812 		FAIL_TEST_IF_FALSE(!ret);
813 
814 	TEST_END_CHECK();
815 }
816 
817 static void test_seal_mprotect_two_vma_with_gap(bool seal)
818 {
819 	void *ptr;
820 	unsigned long page_size = getpagesize();
821 	unsigned long size = 4 * page_size;
822 	int ret;
823 
824 	setup_single_address(size, &ptr);
825 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
826 
827 	/* use mprotect to split. */
828 	ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
829 	FAIL_TEST_IF_FALSE(!ret);
830 
831 	/* use mprotect to split. */
832 	ret = sys_mprotect(ptr + 3 * page_size, page_size,
833 			PROT_READ | PROT_WRITE);
834 	FAIL_TEST_IF_FALSE(!ret);
835 
836 	/* use munmap to free two pages in the middle */
837 	ret = sys_munmap(ptr + page_size, 2 * page_size);
838 	FAIL_TEST_IF_FALSE(!ret);
839 
840 	/* mprotect will fail, because there is a gap in the address. */
841 	/* notes, internally mprotect still updated the first page. */
842 	ret = sys_mprotect(ptr, 4 * page_size, PROT_READ);
843 	FAIL_TEST_IF_FALSE(ret < 0);
844 
845 	/* mseal will fail as well. */
846 	ret = sys_mseal(ptr, 4 * page_size);
847 	FAIL_TEST_IF_FALSE(ret < 0);
848 
849 	/* the first page is not sealed. */
850 	ret = sys_mprotect(ptr, page_size, PROT_READ);
851 	FAIL_TEST_IF_FALSE(ret == 0);
852 
853 	/* the last page is not sealed. */
854 	ret = sys_mprotect(ptr + 3 * page_size, page_size, PROT_READ);
855 	FAIL_TEST_IF_FALSE(ret == 0);
856 
857 	TEST_END_CHECK();
858 }
859 
860 static void test_seal_mprotect_split(bool seal)
861 {
862 	void *ptr;
863 	unsigned long page_size = getpagesize();
864 	unsigned long size = 4 * page_size;
865 	int ret;
866 
867 	setup_single_address(size, &ptr);
868 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
869 
870 	/* use mprotect to split. */
871 	ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
872 	FAIL_TEST_IF_FALSE(!ret);
873 
874 	/* seal all 4 pages. */
875 	if (seal) {
876 		ret = sys_mseal(ptr, 4 * page_size);
877 		FAIL_TEST_IF_FALSE(!ret);
878 	}
879 
880 	/* mprotect is sealed. */
881 	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
882 	if (seal)
883 		FAIL_TEST_IF_FALSE(ret < 0);
884 	else
885 		FAIL_TEST_IF_FALSE(!ret);
886 
887 
888 	ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ);
889 	if (seal)
890 		FAIL_TEST_IF_FALSE(ret < 0);
891 	else
892 		FAIL_TEST_IF_FALSE(!ret);
893 
894 	TEST_END_CHECK();
895 }
896 
897 static void test_seal_mprotect_merge(bool seal)
898 {
899 	void *ptr;
900 	unsigned long page_size = getpagesize();
901 	unsigned long size = 4 * page_size;
902 	int ret;
903 
904 	setup_single_address(size, &ptr);
905 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
906 
907 	/* use mprotect to split one page. */
908 	ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
909 	FAIL_TEST_IF_FALSE(!ret);
910 
911 	/* seal first two pages. */
912 	if (seal) {
913 		ret = sys_mseal(ptr, 2 * page_size);
914 		FAIL_TEST_IF_FALSE(!ret);
915 	}
916 
917 	/* 2 pages are sealed. */
918 	ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
919 	if (seal)
920 		FAIL_TEST_IF_FALSE(ret < 0);
921 	else
922 		FAIL_TEST_IF_FALSE(!ret);
923 
924 	/* last 2 pages are not sealed. */
925 	ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ);
926 	FAIL_TEST_IF_FALSE(ret == 0);
927 
928 	TEST_END_CHECK();
929 }
930 
931 static void test_seal_munmap(bool seal)
932 {
933 	void *ptr;
934 	unsigned long page_size = getpagesize();
935 	unsigned long size = 4 * page_size;
936 	int ret;
937 
938 	setup_single_address(size, &ptr);
939 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
940 
941 	if (seal) {
942 		ret = sys_mseal(ptr, size);
943 		FAIL_TEST_IF_FALSE(!ret);
944 	}
945 
946 	/* 4 pages are sealed. */
947 	ret = sys_munmap(ptr, size);
948 	if (seal)
949 		FAIL_TEST_IF_FALSE(ret < 0);
950 	else
951 		FAIL_TEST_IF_FALSE(!ret);
952 
953 	TEST_END_CHECK();
954 }
955 
956 /*
957  * allocate 4 pages,
958  * use mprotect to split it as two VMAs
959  * seal the whole range
960  * munmap will fail on both
961  */
962 static void test_seal_munmap_two_vma(bool seal)
963 {
964 	void *ptr;
965 	unsigned long page_size = getpagesize();
966 	unsigned long size = 4 * page_size;
967 	int ret;
968 
969 	setup_single_address(size, &ptr);
970 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
971 
972 	/* use mprotect to split */
973 	ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
974 	FAIL_TEST_IF_FALSE(!ret);
975 
976 	if (seal) {
977 		ret = sys_mseal(ptr, size);
978 		FAIL_TEST_IF_FALSE(!ret);
979 	}
980 
981 	ret = sys_munmap(ptr, page_size * 2);
982 	if (seal)
983 		FAIL_TEST_IF_FALSE(ret < 0);
984 	else
985 		FAIL_TEST_IF_FALSE(!ret);
986 
987 	ret = sys_munmap(ptr + page_size, page_size * 2);
988 	if (seal)
989 		FAIL_TEST_IF_FALSE(ret < 0);
990 	else
991 		FAIL_TEST_IF_FALSE(!ret);
992 
993 	TEST_END_CHECK();
994 }
995 
996 /*
997  * allocate a VMA with 4 pages.
998  * munmap the middle 2 pages.
999  * seal the whole 4 pages, will fail.
1000  * munmap the first page will be OK.
1001  * munmap the last page will be OK.
1002  */
1003 static void test_seal_munmap_vma_with_gap(bool seal)
1004 {
1005 	void *ptr;
1006 	unsigned long page_size = getpagesize();
1007 	unsigned long size = 4 * page_size;
1008 	int ret;
1009 
1010 	setup_single_address(size, &ptr);
1011 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1012 
1013 	ret = sys_munmap(ptr + page_size, page_size * 2);
1014 	FAIL_TEST_IF_FALSE(!ret);
1015 
1016 	if (seal) {
1017 		/* can't have gap in the middle. */
1018 		ret = sys_mseal(ptr, size);
1019 		FAIL_TEST_IF_FALSE(ret < 0);
1020 	}
1021 
1022 	ret = sys_munmap(ptr, page_size);
1023 	FAIL_TEST_IF_FALSE(!ret);
1024 
1025 	ret = sys_munmap(ptr + page_size * 2, page_size);
1026 	FAIL_TEST_IF_FALSE(!ret);
1027 
1028 	ret = sys_munmap(ptr, size);
1029 	FAIL_TEST_IF_FALSE(!ret);
1030 
1031 	TEST_END_CHECK();
1032 }
1033 
1034 static void test_munmap_start_freed(bool seal)
1035 {
1036 	void *ptr;
1037 	unsigned long page_size = getpagesize();
1038 	unsigned long size = 4 * page_size;
1039 	int ret;
1040 	int prot;
1041 
1042 	setup_single_address(size, &ptr);
1043 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1044 
1045 	/* unmap the first page. */
1046 	ret = sys_munmap(ptr, page_size);
1047 	FAIL_TEST_IF_FALSE(!ret);
1048 
1049 	/* seal the last 3 pages. */
1050 	if (seal) {
1051 		ret = sys_mseal(ptr + page_size, 3 * page_size);
1052 		FAIL_TEST_IF_FALSE(!ret);
1053 	}
1054 
1055 	/* unmap from the first page. */
1056 	ret = sys_munmap(ptr, size);
1057 	if (seal) {
1058 		FAIL_TEST_IF_FALSE(ret < 0);
1059 
1060 		size = get_vma_size(ptr + page_size, &prot);
1061 		FAIL_TEST_IF_FALSE(size == page_size * 3);
1062 	} else {
1063 		/* note: this will be OK, even the first page is */
1064 		/* already unmapped. */
1065 		FAIL_TEST_IF_FALSE(!ret);
1066 
1067 		size = get_vma_size(ptr + page_size, &prot);
1068 		FAIL_TEST_IF_FALSE(size == 0);
1069 	}
1070 
1071 	TEST_END_CHECK();
1072 }
1073 
1074 static void test_munmap_end_freed(bool seal)
1075 {
1076 	void *ptr;
1077 	unsigned long page_size = getpagesize();
1078 	unsigned long size = 4 * page_size;
1079 	int ret;
1080 
1081 	setup_single_address(size, &ptr);
1082 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1083 
1084 	/* unmap last page. */
1085 	ret = sys_munmap(ptr + page_size * 3, page_size);
1086 	FAIL_TEST_IF_FALSE(!ret);
1087 
1088 	/* seal the first 3 pages. */
1089 	if (seal) {
1090 		ret = sys_mseal(ptr, 3 * page_size);
1091 		FAIL_TEST_IF_FALSE(!ret);
1092 	}
1093 
1094 	/* unmap all pages. */
1095 	ret = sys_munmap(ptr, size);
1096 	if (seal)
1097 		FAIL_TEST_IF_FALSE(ret < 0);
1098 	else
1099 		FAIL_TEST_IF_FALSE(!ret);
1100 
1101 	TEST_END_CHECK();
1102 }
1103 
1104 static void test_munmap_middle_freed(bool seal)
1105 {
1106 	void *ptr;
1107 	unsigned long page_size = getpagesize();
1108 	unsigned long size = 4 * page_size;
1109 	int ret;
1110 	int prot;
1111 
1112 	setup_single_address(size, &ptr);
1113 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1114 
1115 	/* unmap 2 pages in the middle. */
1116 	ret = sys_munmap(ptr + page_size, page_size * 2);
1117 	FAIL_TEST_IF_FALSE(!ret);
1118 
1119 	/* seal the first page. */
1120 	if (seal) {
1121 		ret = sys_mseal(ptr, page_size);
1122 		FAIL_TEST_IF_FALSE(!ret);
1123 	}
1124 
1125 	/* munmap all 4 pages. */
1126 	ret = sys_munmap(ptr, size);
1127 	if (seal) {
1128 		FAIL_TEST_IF_FALSE(ret < 0);
1129 
1130 		size = get_vma_size(ptr, &prot);
1131 		FAIL_TEST_IF_FALSE(size == page_size);
1132 
1133 		size = get_vma_size(ptr + page_size * 3, &prot);
1134 		FAIL_TEST_IF_FALSE(size == page_size);
1135 	} else {
1136 		FAIL_TEST_IF_FALSE(!ret);
1137 
1138 		size = get_vma_size(ptr, &prot);
1139 		FAIL_TEST_IF_FALSE(size == 0);
1140 
1141 		size = get_vma_size(ptr + page_size * 3, &prot);
1142 		FAIL_TEST_IF_FALSE(size == 0);
1143 	}
1144 
1145 	TEST_END_CHECK();
1146 }
1147 
1148 static void test_seal_mremap_shrink(bool seal)
1149 {
1150 	void *ptr;
1151 	unsigned long page_size = getpagesize();
1152 	unsigned long size = 4 * page_size;
1153 	int ret;
1154 	void *ret2;
1155 
1156 	setup_single_address(size, &ptr);
1157 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1158 
1159 	if (seal) {
1160 		ret = sys_mseal(ptr, size);
1161 		FAIL_TEST_IF_FALSE(!ret);
1162 	}
1163 
1164 	/* shrink from 4 pages to 2 pages. */
1165 	ret2 = mremap(ptr, size, 2 * page_size, 0, 0);
1166 	if (seal) {
1167 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1168 		FAIL_TEST_IF_FALSE(errno == EPERM);
1169 	} else {
1170 		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
1171 
1172 	}
1173 
1174 	TEST_END_CHECK();
1175 }
1176 
1177 static void test_seal_mremap_expand(bool seal)
1178 {
1179 	void *ptr;
1180 	unsigned long page_size = getpagesize();
1181 	unsigned long size = 4 * page_size;
1182 	int ret;
1183 	void *ret2;
1184 
1185 	setup_single_address(size, &ptr);
1186 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1187 	/* ummap last 2 pages. */
1188 	ret = sys_munmap(ptr + 2 * page_size, 2 * page_size);
1189 	FAIL_TEST_IF_FALSE(!ret);
1190 
1191 	if (seal) {
1192 		ret = sys_mseal(ptr, 2 * page_size);
1193 		FAIL_TEST_IF_FALSE(!ret);
1194 	}
1195 
1196 	/* expand from 2 page to 4 pages. */
1197 	ret2 = mremap(ptr, 2 * page_size, 4 * page_size, 0, 0);
1198 	if (seal) {
1199 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1200 		FAIL_TEST_IF_FALSE(errno == EPERM);
1201 	} else {
1202 		FAIL_TEST_IF_FALSE(ret2 == ptr);
1203 
1204 	}
1205 
1206 	TEST_END_CHECK();
1207 }
1208 
1209 static void test_seal_mremap_move(bool seal)
1210 {
1211 	void *ptr, *newPtr;
1212 	unsigned long page_size = getpagesize();
1213 	unsigned long size = page_size;
1214 	int ret;
1215 	void *ret2;
1216 
1217 	setup_single_address(size, &ptr);
1218 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1219 	setup_single_address(size, &newPtr);
1220 	FAIL_TEST_IF_FALSE(newPtr != (void *)-1);
1221 	ret = clean_single_address(newPtr, size);
1222 	FAIL_TEST_IF_FALSE(!ret);
1223 
1224 	if (seal) {
1225 		ret = sys_mseal(ptr, size);
1226 		FAIL_TEST_IF_FALSE(!ret);
1227 	}
1228 
1229 	/* move from ptr to fixed address. */
1230 	ret2 = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newPtr);
1231 	if (seal) {
1232 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1233 		FAIL_TEST_IF_FALSE(errno == EPERM);
1234 	} else {
1235 		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
1236 
1237 	}
1238 
1239 	TEST_END_CHECK();
1240 }
1241 
1242 static void test_seal_mmap_overwrite_prot(bool seal)
1243 {
1244 	void *ptr;
1245 	unsigned long page_size = getpagesize();
1246 	unsigned long size = page_size;
1247 	int ret;
1248 	void *ret2;
1249 
1250 	setup_single_address(size, &ptr);
1251 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1252 
1253 	if (seal) {
1254 		ret = sys_mseal(ptr, size);
1255 		FAIL_TEST_IF_FALSE(!ret);
1256 	}
1257 
1258 	/* use mmap to change protection. */
1259 	ret2 = sys_mmap(ptr, size, PROT_NONE,
1260 			MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1261 	if (seal) {
1262 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1263 		FAIL_TEST_IF_FALSE(errno == EPERM);
1264 	} else
1265 		FAIL_TEST_IF_FALSE(ret2 == ptr);
1266 
1267 	TEST_END_CHECK();
1268 }
1269 
1270 static void test_seal_mmap_expand(bool seal)
1271 {
1272 	void *ptr;
1273 	unsigned long page_size = getpagesize();
1274 	unsigned long size = 12 * page_size;
1275 	int ret;
1276 	void *ret2;
1277 
1278 	setup_single_address(size, &ptr);
1279 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1280 	/* ummap last 4 pages. */
1281 	ret = sys_munmap(ptr + 8 * page_size, 4 * page_size);
1282 	FAIL_TEST_IF_FALSE(!ret);
1283 
1284 	if (seal) {
1285 		ret = sys_mseal(ptr, 8 * page_size);
1286 		FAIL_TEST_IF_FALSE(!ret);
1287 	}
1288 
1289 	/* use mmap to expand. */
1290 	ret2 = sys_mmap(ptr, size, PROT_READ,
1291 			MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1292 	if (seal) {
1293 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1294 		FAIL_TEST_IF_FALSE(errno == EPERM);
1295 	} else
1296 		FAIL_TEST_IF_FALSE(ret2 == ptr);
1297 
1298 	TEST_END_CHECK();
1299 }
1300 
1301 static void test_seal_mmap_shrink(bool seal)
1302 {
1303 	void *ptr;
1304 	unsigned long page_size = getpagesize();
1305 	unsigned long size = 12 * page_size;
1306 	int ret;
1307 	void *ret2;
1308 
1309 	setup_single_address(size, &ptr);
1310 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1311 
1312 	if (seal) {
1313 		ret = sys_mseal(ptr, size);
1314 		FAIL_TEST_IF_FALSE(!ret);
1315 	}
1316 
1317 	/* use mmap to shrink. */
1318 	ret2 = sys_mmap(ptr, 8 * page_size, PROT_READ,
1319 			MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1320 	if (seal) {
1321 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1322 		FAIL_TEST_IF_FALSE(errno == EPERM);
1323 	} else
1324 		FAIL_TEST_IF_FALSE(ret2 == ptr);
1325 
1326 	TEST_END_CHECK();
1327 }
1328 
1329 static void test_seal_mremap_shrink_fixed(bool seal)
1330 {
1331 	void *ptr;
1332 	void *newAddr;
1333 	unsigned long page_size = getpagesize();
1334 	unsigned long size = 4 * page_size;
1335 	int ret;
1336 	void *ret2;
1337 
1338 	setup_single_address(size, &ptr);
1339 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1340 	setup_single_address(size, &newAddr);
1341 	FAIL_TEST_IF_FALSE(newAddr != (void *)-1);
1342 
1343 	if (seal) {
1344 		ret = sys_mseal(ptr, size);
1345 		FAIL_TEST_IF_FALSE(!ret);
1346 	}
1347 
1348 	/* mremap to move and shrink to fixed address */
1349 	ret2 = mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED,
1350 			newAddr);
1351 	if (seal) {
1352 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1353 		FAIL_TEST_IF_FALSE(errno == EPERM);
1354 	} else
1355 		FAIL_TEST_IF_FALSE(ret2 == newAddr);
1356 
1357 	TEST_END_CHECK();
1358 }
1359 
1360 static void test_seal_mremap_expand_fixed(bool seal)
1361 {
1362 	void *ptr;
1363 	void *newAddr;
1364 	unsigned long page_size = getpagesize();
1365 	unsigned long size = 4 * page_size;
1366 	int ret;
1367 	void *ret2;
1368 
1369 	setup_single_address(page_size, &ptr);
1370 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1371 	setup_single_address(size, &newAddr);
1372 	FAIL_TEST_IF_FALSE(newAddr != (void *)-1);
1373 
1374 	if (seal) {
1375 		ret = sys_mseal(newAddr, size);
1376 		FAIL_TEST_IF_FALSE(!ret);
1377 	}
1378 
1379 	/* mremap to move and expand to fixed address */
1380 	ret2 = mremap(ptr, page_size, size, MREMAP_MAYMOVE | MREMAP_FIXED,
1381 			newAddr);
1382 	if (seal) {
1383 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1384 		FAIL_TEST_IF_FALSE(errno == EPERM);
1385 	} else
1386 		FAIL_TEST_IF_FALSE(ret2 == newAddr);
1387 
1388 	TEST_END_CHECK();
1389 }
1390 
1391 static void test_seal_mremap_move_fixed(bool seal)
1392 {
1393 	void *ptr;
1394 	void *newAddr;
1395 	unsigned long page_size = getpagesize();
1396 	unsigned long size = 4 * page_size;
1397 	int ret;
1398 	void *ret2;
1399 
1400 	setup_single_address(size, &ptr);
1401 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1402 	setup_single_address(size, &newAddr);
1403 	FAIL_TEST_IF_FALSE(newAddr != (void *)-1);
1404 
1405 	if (seal) {
1406 		ret = sys_mseal(newAddr, size);
1407 		FAIL_TEST_IF_FALSE(!ret);
1408 	}
1409 
1410 	/* mremap to move to fixed address */
1411 	ret2 = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newAddr);
1412 	if (seal) {
1413 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1414 		FAIL_TEST_IF_FALSE(errno == EPERM);
1415 	} else
1416 		FAIL_TEST_IF_FALSE(ret2 == newAddr);
1417 
1418 	TEST_END_CHECK();
1419 }
1420 
1421 static void test_seal_mremap_move_fixed_zero(bool seal)
1422 {
1423 	void *ptr;
1424 	unsigned long page_size = getpagesize();
1425 	unsigned long size = 4 * page_size;
1426 	int ret;
1427 	void *ret2;
1428 
1429 	setup_single_address(size, &ptr);
1430 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1431 
1432 	if (seal) {
1433 		ret = sys_mseal(ptr, size);
1434 		FAIL_TEST_IF_FALSE(!ret);
1435 	}
1436 
1437 	/*
1438 	 * MREMAP_FIXED can move the mapping to zero address
1439 	 */
1440 	ret2 = mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED,
1441 			0);
1442 	if (seal) {
1443 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1444 		FAIL_TEST_IF_FALSE(errno == EPERM);
1445 	} else {
1446 		FAIL_TEST_IF_FALSE(ret2 == 0);
1447 
1448 	}
1449 
1450 	TEST_END_CHECK();
1451 }
1452 
1453 static void test_seal_mremap_move_dontunmap(bool seal)
1454 {
1455 	void *ptr;
1456 	unsigned long page_size = getpagesize();
1457 	unsigned long size = 4 * page_size;
1458 	int ret;
1459 	void *ret2;
1460 
1461 	setup_single_address(size, &ptr);
1462 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1463 
1464 	if (seal) {
1465 		ret = sys_mseal(ptr, size);
1466 		FAIL_TEST_IF_FALSE(!ret);
1467 	}
1468 
1469 	/* mremap to move, and don't unmap src addr. */
1470 	ret2 = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 0);
1471 	if (seal) {
1472 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1473 		FAIL_TEST_IF_FALSE(errno == EPERM);
1474 	} else {
1475 		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
1476 
1477 	}
1478 
1479 	TEST_END_CHECK();
1480 }
1481 
1482 static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
1483 {
1484 	void *ptr;
1485 	unsigned long page_size = getpagesize();
1486 	unsigned long size = 4 * page_size;
1487 	int ret;
1488 	void *ret2;
1489 
1490 	setup_single_address(size, &ptr);
1491 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1492 
1493 	if (seal) {
1494 		ret = sys_mseal(ptr, size);
1495 		FAIL_TEST_IF_FALSE(!ret);
1496 	}
1497 
1498 	/*
1499 	 * The 0xdeaddead should not have effect on dest addr
1500 	 * when MREMAP_DONTUNMAP is set.
1501 	 */
1502 	ret2 = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP,
1503 			0xdeaddead);
1504 	if (seal) {
1505 		FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1506 		FAIL_TEST_IF_FALSE(errno == EPERM);
1507 	} else {
1508 		FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
1509 		FAIL_TEST_IF_FALSE((long)ret2 != 0xdeaddead);
1510 
1511 	}
1512 
1513 	TEST_END_CHECK();
1514 }
1515 
1516 
1517 static void test_seal_merge_and_split(void)
1518 {
1519 	void *ptr;
1520 	unsigned long page_size = getpagesize();
1521 	unsigned long size;
1522 	int ret;
1523 	int prot;
1524 
1525 	/* (24 RO) */
1526 	setup_single_address(24 * page_size, &ptr);
1527 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1528 
1529 	/* use mprotect(NONE) to set out boundary */
1530 	/* (1 NONE) (22 RO) (1 NONE) */
1531 	ret = sys_mprotect(ptr, page_size, PROT_NONE);
1532 	FAIL_TEST_IF_FALSE(!ret);
1533 	ret = sys_mprotect(ptr + 23 * page_size, page_size, PROT_NONE);
1534 	FAIL_TEST_IF_FALSE(!ret);
1535 	size = get_vma_size(ptr + page_size, &prot);
1536 	FAIL_TEST_IF_FALSE(size == 22 * page_size);
1537 	FAIL_TEST_IF_FALSE(prot == 4);
1538 
1539 	/* use mseal to split from beginning */
1540 	/* (1 NONE) (1 RO_SEAL) (21 RO) (1 NONE) */
1541 	ret = sys_mseal(ptr + page_size, page_size);
1542 	FAIL_TEST_IF_FALSE(!ret);
1543 	size = get_vma_size(ptr + page_size, &prot);
1544 	FAIL_TEST_IF_FALSE(size == page_size);
1545 	FAIL_TEST_IF_FALSE(prot == 0x4);
1546 	size = get_vma_size(ptr + 2 * page_size, &prot);
1547 	FAIL_TEST_IF_FALSE(size == 21 * page_size);
1548 	FAIL_TEST_IF_FALSE(prot == 0x4);
1549 
1550 	/* use mseal to split from the end. */
1551 	/* (1 NONE) (1 RO_SEAL) (20 RO) (1 RO_SEAL) (1 NONE) */
1552 	ret = sys_mseal(ptr + 22 * page_size, page_size);
1553 	FAIL_TEST_IF_FALSE(!ret);
1554 	size = get_vma_size(ptr + 22 * page_size, &prot);
1555 	FAIL_TEST_IF_FALSE(size == page_size);
1556 	FAIL_TEST_IF_FALSE(prot == 0x4);
1557 	size = get_vma_size(ptr + 2 * page_size, &prot);
1558 	FAIL_TEST_IF_FALSE(size == 20 * page_size);
1559 	FAIL_TEST_IF_FALSE(prot == 0x4);
1560 
1561 	/* merge with prev. */
1562 	/* (1 NONE) (2 RO_SEAL) (19 RO) (1 RO_SEAL) (1 NONE) */
1563 	ret = sys_mseal(ptr + 2 * page_size, page_size);
1564 	FAIL_TEST_IF_FALSE(!ret);
1565 	size = get_vma_size(ptr +  page_size, &prot);
1566 	FAIL_TEST_IF_FALSE(size ==  2 * page_size);
1567 	FAIL_TEST_IF_FALSE(prot == 0x4);
1568 
1569 	/* merge with after. */
1570 	/* (1 NONE) (2 RO_SEAL) (18 RO) (2 RO_SEALS) (1 NONE) */
1571 	ret = sys_mseal(ptr + 21 * page_size, page_size);
1572 	FAIL_TEST_IF_FALSE(!ret);
1573 	size = get_vma_size(ptr +  21 * page_size, &prot);
1574 	FAIL_TEST_IF_FALSE(size ==  2 * page_size);
1575 	FAIL_TEST_IF_FALSE(prot == 0x4);
1576 
1577 	/* split and merge from prev */
1578 	/* (1 NONE) (3 RO_SEAL) (17 RO) (2 RO_SEALS) (1 NONE) */
1579 	ret = sys_mseal(ptr + 2 * page_size, 2 * page_size);
1580 	FAIL_TEST_IF_FALSE(!ret);
1581 	size = get_vma_size(ptr +  1 * page_size, &prot);
1582 	FAIL_TEST_IF_FALSE(size ==  3 * page_size);
1583 	FAIL_TEST_IF_FALSE(prot == 0x4);
1584 	ret = sys_munmap(ptr + page_size,  page_size);
1585 	FAIL_TEST_IF_FALSE(ret < 0);
1586 	ret = sys_mprotect(ptr + 2 * page_size, page_size,  PROT_NONE);
1587 	FAIL_TEST_IF_FALSE(ret < 0);
1588 
1589 	/* split and merge from next */
1590 	/* (1 NONE) (3 RO_SEAL) (16 RO) (3 RO_SEALS) (1 NONE) */
1591 	ret = sys_mseal(ptr + 20 * page_size, 2 * page_size);
1592 	FAIL_TEST_IF_FALSE(!ret);
1593 	FAIL_TEST_IF_FALSE(prot == 0x4);
1594 	size = get_vma_size(ptr +  20 * page_size, &prot);
1595 	FAIL_TEST_IF_FALSE(size ==  3 * page_size);
1596 	FAIL_TEST_IF_FALSE(prot == 0x4);
1597 
1598 	/* merge from middle of prev and middle of next. */
1599 	/* (1 NONE) (22 RO_SEAL) (1 NONE) */
1600 	ret = sys_mseal(ptr + 2 * page_size, 20 * page_size);
1601 	FAIL_TEST_IF_FALSE(!ret);
1602 	size = get_vma_size(ptr +  page_size, &prot);
1603 	FAIL_TEST_IF_FALSE(size ==  22 * page_size);
1604 	FAIL_TEST_IF_FALSE(prot == 0x4);
1605 
1606 	TEST_END_CHECK();
1607 }
1608 
1609 static void test_seal_discard_ro_anon_on_rw(bool seal)
1610 {
1611 	void *ptr;
1612 	unsigned long page_size = getpagesize();
1613 	unsigned long size = 4 * page_size;
1614 	int ret;
1615 
1616 	setup_single_address_rw(size, &ptr);
1617 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1618 
1619 	if (seal) {
1620 		ret = sys_mseal(ptr, size);
1621 		FAIL_TEST_IF_FALSE(!ret);
1622 	}
1623 
1624 	/* sealing doesn't take effect on RW memory. */
1625 	ret = sys_madvise(ptr, size, MADV_DONTNEED);
1626 	FAIL_TEST_IF_FALSE(!ret);
1627 
1628 	/* base seal still apply. */
1629 	ret = sys_munmap(ptr, size);
1630 	if (seal)
1631 		FAIL_TEST_IF_FALSE(ret < 0);
1632 	else
1633 		FAIL_TEST_IF_FALSE(!ret);
1634 
1635 	TEST_END_CHECK();
1636 }
1637 
1638 static void test_seal_discard_ro_anon_on_pkey(bool seal)
1639 {
1640 	void *ptr;
1641 	unsigned long page_size = getpagesize();
1642 	unsigned long size = 4 * page_size;
1643 	int ret;
1644 	int pkey;
1645 
1646 	SKIP_TEST_IF_FALSE(pkey_supported());
1647 
1648 	setup_single_address_rw(size, &ptr);
1649 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1650 
1651 	pkey = sys_pkey_alloc(0, 0);
1652 	FAIL_TEST_IF_FALSE(pkey > 0);
1653 
1654 	ret = sys_mprotect_pkey((void *)ptr, size, PROT_READ | PROT_WRITE, pkey);
1655 	FAIL_TEST_IF_FALSE(!ret);
1656 
1657 	if (seal) {
1658 		ret = sys_mseal(ptr, size);
1659 		FAIL_TEST_IF_FALSE(!ret);
1660 	}
1661 
1662 	/* sealing doesn't take effect if PKRU allow write. */
1663 	set_pkey(pkey, 0);
1664 	ret = sys_madvise(ptr, size, MADV_DONTNEED);
1665 	FAIL_TEST_IF_FALSE(!ret);
1666 
1667 	/* sealing will take effect if PKRU deny write. */
1668 	set_pkey(pkey, PKEY_DISABLE_WRITE);
1669 	ret = sys_madvise(ptr, size, MADV_DONTNEED);
1670 	if (seal)
1671 		FAIL_TEST_IF_FALSE(ret < 0);
1672 	else
1673 		FAIL_TEST_IF_FALSE(!ret);
1674 
1675 	/* base seal still apply. */
1676 	ret = sys_munmap(ptr, size);
1677 	if (seal)
1678 		FAIL_TEST_IF_FALSE(ret < 0);
1679 	else
1680 		FAIL_TEST_IF_FALSE(!ret);
1681 
1682 	TEST_END_CHECK();
1683 }
1684 
1685 static void test_seal_discard_ro_anon_on_filebacked(bool seal)
1686 {
1687 	void *ptr;
1688 	unsigned long page_size = getpagesize();
1689 	unsigned long size = 4 * page_size;
1690 	int ret;
1691 	int fd;
1692 	unsigned long mapflags = MAP_PRIVATE;
1693 
1694 	fd = memfd_create("test", 0);
1695 	FAIL_TEST_IF_FALSE(fd > 0);
1696 
1697 	ret = fallocate(fd, 0, 0, size);
1698 	FAIL_TEST_IF_FALSE(!ret);
1699 
1700 	ptr = sys_mmap(NULL, size, PROT_READ, mapflags, fd, 0);
1701 	FAIL_TEST_IF_FALSE(ptr != MAP_FAILED);
1702 
1703 	if (seal) {
1704 		ret = sys_mseal(ptr, size);
1705 		FAIL_TEST_IF_FALSE(!ret);
1706 	}
1707 
1708 	/* sealing doesn't apply for file backed mapping. */
1709 	ret = sys_madvise(ptr, size, MADV_DONTNEED);
1710 	FAIL_TEST_IF_FALSE(!ret);
1711 
1712 	ret = sys_munmap(ptr, size);
1713 	if (seal)
1714 		FAIL_TEST_IF_FALSE(ret < 0);
1715 	else
1716 		FAIL_TEST_IF_FALSE(!ret);
1717 	close(fd);
1718 
1719 	TEST_END_CHECK();
1720 }
1721 
1722 static void test_seal_discard_ro_anon_on_shared(bool seal)
1723 {
1724 	void *ptr;
1725 	unsigned long page_size = getpagesize();
1726 	unsigned long size = 4 * page_size;
1727 	int ret;
1728 	unsigned long mapflags = MAP_ANONYMOUS | MAP_SHARED;
1729 
1730 	ptr = sys_mmap(NULL, size, PROT_READ, mapflags, -1, 0);
1731 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1732 
1733 	if (seal) {
1734 		ret = sys_mseal(ptr, size);
1735 		FAIL_TEST_IF_FALSE(!ret);
1736 	}
1737 
1738 	/* sealing doesn't apply for shared mapping. */
1739 	ret = sys_madvise(ptr, size, MADV_DONTNEED);
1740 	FAIL_TEST_IF_FALSE(!ret);
1741 
1742 	ret = sys_munmap(ptr, size);
1743 	if (seal)
1744 		FAIL_TEST_IF_FALSE(ret < 0);
1745 	else
1746 		FAIL_TEST_IF_FALSE(!ret);
1747 
1748 	TEST_END_CHECK();
1749 }
1750 
1751 static void test_seal_discard_ro_anon(bool seal)
1752 {
1753 	void *ptr;
1754 	unsigned long page_size = getpagesize();
1755 	unsigned long size = 4 * page_size;
1756 	int ret;
1757 
1758 	setup_single_address(size, &ptr);
1759 	FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1760 
1761 	if (seal) {
1762 		ret = seal_single_address(ptr, size);
1763 		FAIL_TEST_IF_FALSE(!ret);
1764 	}
1765 
1766 	ret = sys_madvise(ptr, size, MADV_DONTNEED);
1767 	if (seal)
1768 		FAIL_TEST_IF_FALSE(ret < 0);
1769 	else
1770 		FAIL_TEST_IF_FALSE(!ret);
1771 
1772 	ret = sys_munmap(ptr, size);
1773 	if (seal)
1774 		FAIL_TEST_IF_FALSE(ret < 0);
1775 	else
1776 		FAIL_TEST_IF_FALSE(!ret);
1777 
1778 	TEST_END_CHECK();
1779 }
1780 
1781 int main(int argc, char **argv)
1782 {
1783 	bool test_seal = seal_support();
1784 
1785 	ksft_print_header();
1786 
1787 	if (!test_seal)
1788 		ksft_exit_skip("sealing not supported, check CONFIG_64BIT\n");
1789 
1790 	if (!pkey_supported())
1791 		ksft_print_msg("PKEY not supported\n");
1792 
1793 	ksft_set_plan(80);
1794 
1795 	test_seal_addseal();
1796 	test_seal_unmapped_start();
1797 	test_seal_unmapped_middle();
1798 	test_seal_unmapped_end();
1799 	test_seal_multiple_vmas();
1800 	test_seal_split_start();
1801 	test_seal_split_end();
1802 	test_seal_invalid_input();
1803 	test_seal_zero_length();
1804 	test_seal_twice();
1805 
1806 	test_seal_mprotect(false);
1807 	test_seal_mprotect(true);
1808 
1809 	test_seal_start_mprotect(false);
1810 	test_seal_start_mprotect(true);
1811 
1812 	test_seal_end_mprotect(false);
1813 	test_seal_end_mprotect(true);
1814 
1815 	test_seal_mprotect_unalign_len(false);
1816 	test_seal_mprotect_unalign_len(true);
1817 
1818 	test_seal_mprotect_unalign_len_variant_2(false);
1819 	test_seal_mprotect_unalign_len_variant_2(true);
1820 
1821 	test_seal_mprotect_two_vma(false);
1822 	test_seal_mprotect_two_vma(true);
1823 
1824 	test_seal_mprotect_two_vma_with_split(false);
1825 	test_seal_mprotect_two_vma_with_split(true);
1826 
1827 	test_seal_mprotect_partial_mprotect(false);
1828 	test_seal_mprotect_partial_mprotect(true);
1829 
1830 	test_seal_mprotect_two_vma_with_gap(false);
1831 	test_seal_mprotect_two_vma_with_gap(true);
1832 
1833 	test_seal_mprotect_merge(false);
1834 	test_seal_mprotect_merge(true);
1835 
1836 	test_seal_mprotect_split(false);
1837 	test_seal_mprotect_split(true);
1838 
1839 	test_seal_munmap(false);
1840 	test_seal_munmap(true);
1841 	test_seal_munmap_two_vma(false);
1842 	test_seal_munmap_two_vma(true);
1843 	test_seal_munmap_vma_with_gap(false);
1844 	test_seal_munmap_vma_with_gap(true);
1845 
1846 	test_munmap_start_freed(false);
1847 	test_munmap_start_freed(true);
1848 	test_munmap_middle_freed(false);
1849 	test_munmap_middle_freed(true);
1850 	test_munmap_end_freed(false);
1851 	test_munmap_end_freed(true);
1852 
1853 	test_seal_mremap_shrink(false);
1854 	test_seal_mremap_shrink(true);
1855 	test_seal_mremap_expand(false);
1856 	test_seal_mremap_expand(true);
1857 	test_seal_mremap_move(false);
1858 	test_seal_mremap_move(true);
1859 
1860 	test_seal_mremap_shrink_fixed(false);
1861 	test_seal_mremap_shrink_fixed(true);
1862 	test_seal_mremap_expand_fixed(false);
1863 	test_seal_mremap_expand_fixed(true);
1864 	test_seal_mremap_move_fixed(false);
1865 	test_seal_mremap_move_fixed(true);
1866 	test_seal_mremap_move_dontunmap(false);
1867 	test_seal_mremap_move_dontunmap(true);
1868 	test_seal_mremap_move_fixed_zero(false);
1869 	test_seal_mremap_move_fixed_zero(true);
1870 	test_seal_mremap_move_dontunmap_anyaddr(false);
1871 	test_seal_mremap_move_dontunmap_anyaddr(true);
1872 	test_seal_discard_ro_anon(false);
1873 	test_seal_discard_ro_anon(true);
1874 	test_seal_discard_ro_anon_on_rw(false);
1875 	test_seal_discard_ro_anon_on_rw(true);
1876 	test_seal_discard_ro_anon_on_shared(false);
1877 	test_seal_discard_ro_anon_on_shared(true);
1878 	test_seal_discard_ro_anon_on_filebacked(false);
1879 	test_seal_discard_ro_anon_on_filebacked(true);
1880 	test_seal_mmap_overwrite_prot(false);
1881 	test_seal_mmap_overwrite_prot(true);
1882 	test_seal_mmap_expand(false);
1883 	test_seal_mmap_expand(true);
1884 	test_seal_mmap_shrink(false);
1885 	test_seal_mmap_shrink(true);
1886 
1887 	test_seal_merge_and_split();
1888 	test_seal_zero_address();
1889 
1890 	test_seal_discard_ro_anon_on_pkey(false);
1891 	test_seal_discard_ro_anon_on_pkey(true);
1892 
1893 	ksft_finished();
1894 }
1895