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