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