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