1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/mman.h>
6 #include <asm-generic/unistd.h>
9 #include <sys/resource.h>
11 #include "../kselftest.h"
17 #include <sys/ioctl.h>
20 #include "mseal_helpers.h"
22 static unsigned long get_vma_size(void *addr, int *prot)
27 uintptr_t addr_start, addr_end;
31 maps = fopen("/proc/self/maps", "r");
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')
41 if (protstr[1] == 'w')
43 if (protstr[2] == 'x')
54 * define sys_xyx to call syscall directly.
56 static int sys_mseal(void *start, size_t len)
61 sret = syscall(__NR_mseal, start, len, 0);
65 static int sys_mprotect(void *ptr, size_t size, unsigned long prot)
70 sret = syscall(__NR_mprotect, ptr, size, prot);
74 static int sys_mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
80 sret = syscall(__NR_pkey_mprotect, ptr, size, orig_prot, pkey);
84 static int sys_munmap(void *ptr, size_t size)
89 sret = syscall(__NR_munmap, ptr, size);
93 static int sys_madvise(void *start, size_t len, int types)
98 sret = syscall(__NR_madvise, start, len, types);
102 static void *sys_mremap(void *addr, size_t old_len, size_t new_len,
103 unsigned long flags, void *new_addr)
108 sret = (void *) syscall(__NR_mremap, addr, old_len, new_len, flags, new_addr);
112 static int sys_pkey_alloc(unsigned long flags, unsigned long init_val)
114 int ret = syscall(__NR_pkey_alloc, flags, init_val);
119 static unsigned int __read_pkey_reg(void)
121 unsigned int pkey_reg = 0;
122 #if defined(__i386__) || defined(__x86_64__) /* arch */
123 unsigned int eax, edx;
124 unsigned int ecx = 0;
126 asm volatile(".byte 0x0f,0x01,0xee\n\t"
127 : "=a" (eax), "=d" (edx)
134 static void __write_pkey_reg(u64 pkey_reg)
136 #if defined(__i386__) || defined(__x86_64__) /* arch */
137 unsigned int eax = pkey_reg;
138 unsigned int ecx = 0;
139 unsigned int edx = 0;
141 asm volatile(".byte 0x0f,0x01,0xef\n\t"
142 : : "a" (eax), "c" (ecx), "d" (edx));
146 static unsigned long pkey_bit_position(int pkey)
148 return pkey * PKEY_BITS_PER_PKEY;
151 static u64 set_pkey_bits(u64 reg, int pkey, u64 flags)
153 unsigned long shift = pkey_bit_position(pkey);
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;
162 static void set_pkey(int pkey, unsigned long pkey_value)
166 new_pkey_reg = set_pkey_bits(__read_pkey_reg(), pkey, pkey_value);
167 __write_pkey_reg(new_pkey_reg);
170 static void setup_single_address(int size, void **ptrOut)
174 ptr = mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
178 static void setup_single_address_rw(int size, void **ptrOut)
181 unsigned long mapflags = MAP_ANONYMOUS | MAP_PRIVATE;
183 ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mapflags, -1, 0);
187 static int clean_single_address(void *ptr, int size)
190 ret = munmap(ptr, size);
194 static int seal_single_address(void *ptr, int size)
197 ret = sys_mseal(ptr, size);
201 bool seal_support(void)
205 unsigned long page_size = getpagesize();
207 ptr = mmap(NULL, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
208 if (ptr == (void *) -1)
211 ret = sys_mseal(ptr, page_size);
218 bool pkey_supported(void)
220 #if defined(__i386__) || defined(__x86_64__) /* arch */
221 int pkey = sys_pkey_alloc(0, 0);
229 static void test_seal_addseal(void)
233 unsigned long page_size = getpagesize();
234 unsigned long size = 4 * page_size;
236 setup_single_address(size, &ptr);
237 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
239 ret = sys_mseal(ptr, size);
240 FAIL_TEST_IF_FALSE(!ret);
245 static void test_seal_unmapped_start(void)
249 unsigned long page_size = getpagesize();
250 unsigned long size = 4 * page_size;
252 setup_single_address(size, &ptr);
253 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
255 /* munmap 2 pages from ptr. */
256 ret = sys_munmap(ptr, 2 * page_size);
257 FAIL_TEST_IF_FALSE(!ret);
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);
263 /* mseal will fail because 2 pages from ptr are unmapped. */
264 ret = sys_mseal(ptr, size);
265 FAIL_TEST_IF_FALSE(ret < 0);
267 ret = sys_mseal(ptr + 2 * page_size, 2 * page_size);
268 FAIL_TEST_IF_FALSE(!ret);
273 static void test_seal_unmapped_middle(void)
277 unsigned long page_size = getpagesize();
278 unsigned long size = 4 * page_size;
280 setup_single_address(size, &ptr);
281 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
283 /* munmap 2 pages from ptr + page. */
284 ret = sys_munmap(ptr + page_size, 2 * page_size);
285 FAIL_TEST_IF_FALSE(!ret);
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);
291 /* mseal will fail as well. */
292 ret = sys_mseal(ptr, size);
293 FAIL_TEST_IF_FALSE(ret < 0);
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);
299 ret = sys_mseal(ptr + 3 * page_size, page_size);
300 FAIL_TEST_IF_FALSE(!ret);
305 static void test_seal_unmapped_end(void)
309 unsigned long page_size = getpagesize();
310 unsigned long size = 4 * page_size;
312 setup_single_address(size, &ptr);
313 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
315 /* unmap last 2 pages. */
316 ret = sys_munmap(ptr + 2 * page_size, 2 * page_size);
317 FAIL_TEST_IF_FALSE(!ret);
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);
323 /* mseal will fail as well. */
324 ret = sys_mseal(ptr, size);
325 FAIL_TEST_IF_FALSE(ret < 0);
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);
334 static void test_seal_multiple_vmas(void)
338 unsigned long page_size = getpagesize();
339 unsigned long size = 4 * page_size;
341 setup_single_address(size, &ptr);
342 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
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);
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);
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);
358 /* mseal get applied to all 4 pages - 3 VMAs. */
359 ret = sys_mseal(ptr, size);
360 FAIL_TEST_IF_FALSE(!ret);
365 static void test_seal_split_start(void)
369 unsigned long page_size = getpagesize();
370 unsigned long size = 4 * page_size;
372 setup_single_address(size, &ptr);
373 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
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);
379 /* seal the first page, this will split the VMA */
380 ret = sys_mseal(ptr, page_size);
381 FAIL_TEST_IF_FALSE(!ret);
383 /* add seal to the remain 3 pages */
384 ret = sys_mseal(ptr + page_size, 3 * page_size);
385 FAIL_TEST_IF_FALSE(!ret);
390 static void test_seal_split_end(void)
394 unsigned long page_size = getpagesize();
395 unsigned long size = 4 * page_size;
397 setup_single_address(size, &ptr);
398 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
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);
404 /* seal the last page */
405 ret = sys_mseal(ptr + 3 * page_size, page_size);
406 FAIL_TEST_IF_FALSE(!ret);
408 /* Adding seals to the first 3 pages */
409 ret = sys_mseal(ptr, 3 * page_size);
410 FAIL_TEST_IF_FALSE(!ret);
415 static void test_seal_invalid_input(void)
418 unsigned long page_size = getpagesize();
419 unsigned long size = 4 * page_size;
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);
428 ret = syscall(__NR_mseal, ptr, size, 0x20);
429 FAIL_TEST_IF_FALSE(ret < 0);
431 /* unaligned address */
432 ret = sys_mseal(ptr + 1, 2 * page_size);
433 FAIL_TEST_IF_FALSE(ret < 0);
436 ret = sys_mseal(ptr, 5 * page_size);
437 FAIL_TEST_IF_FALSE(ret < 0);
439 /* length overflow */
440 ret = sys_mseal(ptr, UINT64_MAX/page_size);
441 FAIL_TEST_IF_FALSE(ret < 0);
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);
450 static void test_seal_zero_length(void)
453 unsigned long page_size = getpagesize();
454 unsigned long size = 4 * page_size;
457 setup_single_address(size, &ptr);
458 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
460 ret = sys_mprotect(ptr, 0, PROT_READ | PROT_WRITE);
461 FAIL_TEST_IF_FALSE(!ret);
463 /* seal 0 length will be OK, same as mprotect */
464 ret = sys_mseal(ptr, 0);
465 FAIL_TEST_IF_FALSE(!ret);
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);
474 static void test_seal_zero_address(void)
477 unsigned long page_size = getpagesize();
478 unsigned long size = 4 * page_size;
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);
487 size = get_vma_size(ptr, &prot);
488 FAIL_TEST_IF_FALSE(size == 4 * page_size);
490 ret = sys_mseal(ptr, size);
491 FAIL_TEST_IF_FALSE(!ret);
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);
500 static void test_seal_twice(void)
504 unsigned long page_size = getpagesize();
505 unsigned long size = 4 * page_size;
507 setup_single_address(size, &ptr);
508 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
510 ret = sys_mseal(ptr, size);
511 FAIL_TEST_IF_FALSE(!ret);
513 /* apply the same seal will be OK. idempotent. */
514 ret = sys_mseal(ptr, size);
515 FAIL_TEST_IF_FALSE(!ret);
520 static void test_seal_mprotect(bool seal)
523 unsigned long page_size = getpagesize();
524 unsigned long size = 4 * page_size;
527 setup_single_address(size, &ptr);
528 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
531 ret = seal_single_address(ptr, size);
532 FAIL_TEST_IF_FALSE(!ret);
535 ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE);
537 FAIL_TEST_IF_FALSE(ret < 0);
539 FAIL_TEST_IF_FALSE(!ret);
544 static void test_seal_start_mprotect(bool seal)
547 unsigned long page_size = getpagesize();
548 unsigned long size = 4 * page_size;
551 setup_single_address(size, &ptr);
552 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
555 ret = seal_single_address(ptr, page_size);
556 FAIL_TEST_IF_FALSE(!ret);
559 /* the first page is sealed. */
560 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
562 FAIL_TEST_IF_FALSE(ret < 0);
564 FAIL_TEST_IF_FALSE(!ret);
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);
574 static void test_seal_end_mprotect(bool seal)
577 unsigned long page_size = getpagesize();
578 unsigned long size = 4 * page_size;
581 setup_single_address(size, &ptr);
582 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
585 ret = seal_single_address(ptr + page_size, 3 * page_size);
586 FAIL_TEST_IF_FALSE(!ret);
589 /* first page is not sealed */
590 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
591 FAIL_TEST_IF_FALSE(!ret);
593 /* last 3 page are sealed */
594 ret = sys_mprotect(ptr + page_size, page_size * 3,
595 PROT_READ | PROT_WRITE);
597 FAIL_TEST_IF_FALSE(ret < 0);
599 FAIL_TEST_IF_FALSE(!ret);
604 static void test_seal_mprotect_unalign_len(bool seal)
607 unsigned long page_size = getpagesize();
608 unsigned long size = 4 * page_size;
611 setup_single_address(size, &ptr);
612 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
615 ret = seal_single_address(ptr, page_size * 2 - 1);
616 FAIL_TEST_IF_FALSE(!ret);
619 /* 2 pages are sealed. */
620 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
622 FAIL_TEST_IF_FALSE(ret < 0);
624 FAIL_TEST_IF_FALSE(!ret);
626 ret = sys_mprotect(ptr + page_size * 2, page_size,
627 PROT_READ | PROT_WRITE);
628 FAIL_TEST_IF_FALSE(!ret);
633 static void test_seal_mprotect_unalign_len_variant_2(bool seal)
636 unsigned long page_size = getpagesize();
637 unsigned long size = 4 * page_size;
640 setup_single_address(size, &ptr);
641 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
643 ret = seal_single_address(ptr, page_size * 2 + 1);
644 FAIL_TEST_IF_FALSE(!ret);
647 /* 3 pages are sealed. */
648 ret = sys_mprotect(ptr, page_size * 3, PROT_READ | PROT_WRITE);
650 FAIL_TEST_IF_FALSE(ret < 0);
652 FAIL_TEST_IF_FALSE(!ret);
654 ret = sys_mprotect(ptr + page_size * 3, page_size,
655 PROT_READ | PROT_WRITE);
656 FAIL_TEST_IF_FALSE(!ret);
661 static void test_seal_mprotect_two_vma(bool seal)
664 unsigned long page_size = getpagesize();
665 unsigned long size = 4 * page_size;
668 setup_single_address(size, &ptr);
669 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
671 /* use mprotect to split */
672 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
673 FAIL_TEST_IF_FALSE(!ret);
676 ret = seal_single_address(ptr, page_size * 4);
677 FAIL_TEST_IF_FALSE(!ret);
680 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
682 FAIL_TEST_IF_FALSE(ret < 0);
684 FAIL_TEST_IF_FALSE(!ret);
686 ret = sys_mprotect(ptr + page_size * 2, page_size * 2,
687 PROT_READ | PROT_WRITE);
689 FAIL_TEST_IF_FALSE(ret < 0);
691 FAIL_TEST_IF_FALSE(!ret);
696 static void test_seal_mprotect_two_vma_with_split(bool seal)
699 unsigned long page_size = getpagesize();
700 unsigned long size = 4 * page_size;
703 setup_single_address(size, &ptr);
704 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
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);
710 /* mseal can apply across 2 vma, also split them. */
712 ret = seal_single_address(ptr + page_size, page_size * 2);
713 FAIL_TEST_IF_FALSE(!ret);
716 /* the first page is not sealed. */
717 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
718 FAIL_TEST_IF_FALSE(!ret);
720 /* the second page is sealed. */
721 ret = sys_mprotect(ptr + page_size, page_size, PROT_READ | PROT_WRITE);
723 FAIL_TEST_IF_FALSE(ret < 0);
725 FAIL_TEST_IF_FALSE(!ret);
727 /* the third page is sealed. */
728 ret = sys_mprotect(ptr + 2 * page_size, page_size,
729 PROT_READ | PROT_WRITE);
731 FAIL_TEST_IF_FALSE(ret < 0);
733 FAIL_TEST_IF_FALSE(!ret);
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);
743 static void test_seal_mprotect_partial_mprotect(bool seal)
746 unsigned long page_size = getpagesize();
747 unsigned long size = 4 * page_size;
750 setup_single_address(size, &ptr);
751 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
755 ret = seal_single_address(ptr, page_size);
756 FAIL_TEST_IF_FALSE(!ret);
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);
762 FAIL_TEST_IF_FALSE(ret < 0);
764 FAIL_TEST_IF_FALSE(!ret);
769 static void test_seal_mprotect_partial_mprotect_tail(bool seal)
772 unsigned long page_size = getpagesize();
773 unsigned long size = 2 * page_size;
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.
782 setup_single_address(size, &ptr);
783 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
786 ret = sys_mseal(ptr + page_size, page_size);
787 FAIL_TEST_IF_FALSE(!ret);
790 ret = sys_mprotect(ptr, size, PROT_EXEC);
792 FAIL_TEST_IF_FALSE(ret < 0);
794 FAIL_TEST_IF_FALSE(!ret);
797 FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0);
798 FAIL_TEST_IF_FALSE(prot == 0x4);
805 static void test_seal_mprotect_two_vma_with_gap(bool seal)
808 unsigned long page_size = getpagesize();
809 unsigned long size = 4 * page_size;
812 setup_single_address(size, &ptr);
813 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
815 /* use mprotect to split. */
816 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
817 FAIL_TEST_IF_FALSE(!ret);
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);
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);
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);
833 /* mseal will fail as well. */
834 ret = sys_mseal(ptr, 4 * page_size);
835 FAIL_TEST_IF_FALSE(ret < 0);
837 /* the first page is not sealed. */
838 ret = sys_mprotect(ptr, page_size, PROT_READ);
839 FAIL_TEST_IF_FALSE(ret == 0);
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);
848 static void test_seal_mprotect_split(bool seal)
851 unsigned long page_size = getpagesize();
852 unsigned long size = 4 * page_size;
855 setup_single_address(size, &ptr);
856 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
858 /* use mprotect to split. */
859 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
860 FAIL_TEST_IF_FALSE(!ret);
862 /* seal all 4 pages. */
864 ret = sys_mseal(ptr, 4 * page_size);
865 FAIL_TEST_IF_FALSE(!ret);
868 /* mprotect is sealed. */
869 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
871 FAIL_TEST_IF_FALSE(ret < 0);
873 FAIL_TEST_IF_FALSE(!ret);
876 ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ);
878 FAIL_TEST_IF_FALSE(ret < 0);
880 FAIL_TEST_IF_FALSE(!ret);
885 static void test_seal_mprotect_merge(bool seal)
888 unsigned long page_size = getpagesize();
889 unsigned long size = 4 * page_size;
892 setup_single_address(size, &ptr);
893 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
895 /* use mprotect to split one page. */
896 ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
897 FAIL_TEST_IF_FALSE(!ret);
899 /* seal first two pages. */
901 ret = sys_mseal(ptr, 2 * page_size);
902 FAIL_TEST_IF_FALSE(!ret);
905 /* 2 pages are sealed. */
906 ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
908 FAIL_TEST_IF_FALSE(ret < 0);
910 FAIL_TEST_IF_FALSE(!ret);
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);
919 static void test_seal_munmap(bool seal)
922 unsigned long page_size = getpagesize();
923 unsigned long size = 4 * page_size;
926 setup_single_address(size, &ptr);
927 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
930 ret = sys_mseal(ptr, size);
931 FAIL_TEST_IF_FALSE(!ret);
934 /* 4 pages are sealed. */
935 ret = sys_munmap(ptr, size);
937 FAIL_TEST_IF_FALSE(ret < 0);
939 FAIL_TEST_IF_FALSE(!ret);
946 * use mprotect to split it as two VMAs
947 * seal the whole range
948 * munmap will fail on both
950 static void test_seal_munmap_two_vma(bool seal)
953 unsigned long page_size = getpagesize();
954 unsigned long size = 4 * page_size;
957 setup_single_address(size, &ptr);
958 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
960 /* use mprotect to split */
961 ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
962 FAIL_TEST_IF_FALSE(!ret);
965 ret = sys_mseal(ptr, size);
966 FAIL_TEST_IF_FALSE(!ret);
969 ret = sys_munmap(ptr, page_size * 2);
971 FAIL_TEST_IF_FALSE(ret < 0);
973 FAIL_TEST_IF_FALSE(!ret);
975 ret = sys_munmap(ptr + page_size, page_size * 2);
977 FAIL_TEST_IF_FALSE(ret < 0);
979 FAIL_TEST_IF_FALSE(!ret);
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.
991 static void test_seal_munmap_vma_with_gap(bool seal)
994 unsigned long page_size = getpagesize();
995 unsigned long size = 4 * page_size;
998 setup_single_address(size, &ptr);
999 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1001 ret = sys_munmap(ptr + page_size, page_size * 2);
1002 FAIL_TEST_IF_FALSE(!ret);
1005 /* can't have gap in the middle. */
1006 ret = sys_mseal(ptr, size);
1007 FAIL_TEST_IF_FALSE(ret < 0);
1010 ret = sys_munmap(ptr, page_size);
1011 FAIL_TEST_IF_FALSE(!ret);
1013 ret = sys_munmap(ptr + page_size * 2, page_size);
1014 FAIL_TEST_IF_FALSE(!ret);
1016 ret = sys_munmap(ptr, size);
1017 FAIL_TEST_IF_FALSE(!ret);
1022 static void test_seal_munmap_partial_across_vmas(bool seal)
1025 unsigned long page_size = getpagesize();
1026 unsigned long size = 2 * page_size;
1030 setup_single_address(size, &ptr);
1031 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1034 ret = sys_mseal(ptr + page_size, page_size);
1035 FAIL_TEST_IF_FALSE(!ret);
1038 ret = sys_munmap(ptr, size);
1040 FAIL_TEST_IF_FALSE(ret < 0);
1042 FAIL_TEST_IF_FALSE(!ret);
1045 FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0);
1046 FAIL_TEST_IF_FALSE(prot == 0x4);
1052 static void test_munmap_start_freed(bool seal)
1055 unsigned long page_size = getpagesize();
1056 unsigned long size = 4 * page_size;
1060 setup_single_address(size, &ptr);
1061 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1063 /* unmap the first page. */
1064 ret = sys_munmap(ptr, page_size);
1065 FAIL_TEST_IF_FALSE(!ret);
1067 /* seal the last 3 pages. */
1069 ret = sys_mseal(ptr + page_size, 3 * page_size);
1070 FAIL_TEST_IF_FALSE(!ret);
1073 /* unmap from the first page. */
1074 ret = sys_munmap(ptr, size);
1076 FAIL_TEST_IF_FALSE(ret < 0);
1078 size = get_vma_size(ptr + page_size, &prot);
1079 FAIL_TEST_IF_FALSE(size == page_size * 3);
1081 /* note: this will be OK, even the first page is */
1082 /* already unmapped. */
1083 FAIL_TEST_IF_FALSE(!ret);
1085 size = get_vma_size(ptr + page_size, &prot);
1086 FAIL_TEST_IF_FALSE(size == 0);
1092 static void test_munmap_end_freed(bool seal)
1095 unsigned long page_size = getpagesize();
1096 unsigned long size = 4 * page_size;
1099 setup_single_address(size, &ptr);
1100 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1102 /* unmap last page. */
1103 ret = sys_munmap(ptr + page_size * 3, page_size);
1104 FAIL_TEST_IF_FALSE(!ret);
1106 /* seal the first 3 pages. */
1108 ret = sys_mseal(ptr, 3 * page_size);
1109 FAIL_TEST_IF_FALSE(!ret);
1112 /* unmap all pages. */
1113 ret = sys_munmap(ptr, size);
1115 FAIL_TEST_IF_FALSE(ret < 0);
1117 FAIL_TEST_IF_FALSE(!ret);
1122 static void test_munmap_middle_freed(bool seal)
1125 unsigned long page_size = getpagesize();
1126 unsigned long size = 4 * page_size;
1130 setup_single_address(size, &ptr);
1131 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1133 /* unmap 2 pages in the middle. */
1134 ret = sys_munmap(ptr + page_size, page_size * 2);
1135 FAIL_TEST_IF_FALSE(!ret);
1137 /* seal the first page. */
1139 ret = sys_mseal(ptr, page_size);
1140 FAIL_TEST_IF_FALSE(!ret);
1143 /* munmap all 4 pages. */
1144 ret = sys_munmap(ptr, size);
1146 FAIL_TEST_IF_FALSE(ret < 0);
1148 size = get_vma_size(ptr, &prot);
1149 FAIL_TEST_IF_FALSE(size == page_size);
1151 size = get_vma_size(ptr + page_size * 3, &prot);
1152 FAIL_TEST_IF_FALSE(size == page_size);
1154 FAIL_TEST_IF_FALSE(!ret);
1156 size = get_vma_size(ptr, &prot);
1157 FAIL_TEST_IF_FALSE(size == 0);
1159 size = get_vma_size(ptr + page_size * 3, &prot);
1160 FAIL_TEST_IF_FALSE(size == 0);
1166 static void test_seal_mremap_shrink(bool seal)
1169 unsigned long page_size = getpagesize();
1170 unsigned long size = 4 * page_size;
1174 setup_single_address(size, &ptr);
1175 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1178 ret = sys_mseal(ptr, size);
1179 FAIL_TEST_IF_FALSE(!ret);
1182 /* shrink from 4 pages to 2 pages. */
1183 ret2 = sys_mremap(ptr, size, 2 * page_size, 0, 0);
1185 FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
1186 FAIL_TEST_IF_FALSE(errno == EPERM);
1188 FAIL_TEST_IF_FALSE(ret2 != (void *) MAP_FAILED);
1195 static void test_seal_mremap_expand(bool seal)
1198 unsigned long page_size = getpagesize();
1199 unsigned long size = 4 * page_size;
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);
1210 ret = sys_mseal(ptr, 2 * page_size);
1211 FAIL_TEST_IF_FALSE(!ret);
1214 /* expand from 2 page to 4 pages. */
1215 ret2 = sys_mremap(ptr, 2 * page_size, 4 * page_size, 0, 0);
1217 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1218 FAIL_TEST_IF_FALSE(errno == EPERM);
1220 FAIL_TEST_IF_FALSE(ret2 == ptr);
1227 static void test_seal_mremap_move(bool seal)
1230 unsigned long page_size = getpagesize();
1231 unsigned long size = page_size;
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);
1243 ret = sys_mseal(ptr, size);
1244 FAIL_TEST_IF_FALSE(!ret);
1247 /* move from ptr to fixed address. */
1248 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newPtr);
1250 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1251 FAIL_TEST_IF_FALSE(errno == EPERM);
1253 FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
1260 static void test_seal_mmap_overwrite_prot(bool seal)
1263 unsigned long page_size = getpagesize();
1264 unsigned long size = page_size;
1268 setup_single_address(size, &ptr);
1269 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1272 ret = sys_mseal(ptr, size);
1273 FAIL_TEST_IF_FALSE(!ret);
1276 /* use mmap to change protection. */
1277 ret2 = mmap(ptr, size, PROT_NONE,
1278 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1280 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1281 FAIL_TEST_IF_FALSE(errno == EPERM);
1283 FAIL_TEST_IF_FALSE(ret2 == ptr);
1288 static void test_seal_mmap_expand(bool seal)
1291 unsigned long page_size = getpagesize();
1292 unsigned long size = 12 * page_size;
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);
1303 ret = sys_mseal(ptr, 8 * page_size);
1304 FAIL_TEST_IF_FALSE(!ret);
1307 /* use mmap to expand. */
1308 ret2 = mmap(ptr, size, PROT_READ,
1309 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1311 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1312 FAIL_TEST_IF_FALSE(errno == EPERM);
1314 FAIL_TEST_IF_FALSE(ret2 == ptr);
1319 static void test_seal_mmap_shrink(bool seal)
1322 unsigned long page_size = getpagesize();
1323 unsigned long size = 12 * page_size;
1327 setup_single_address(size, &ptr);
1328 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1331 ret = sys_mseal(ptr, size);
1332 FAIL_TEST_IF_FALSE(!ret);
1335 /* use mmap to shrink. */
1336 ret2 = mmap(ptr, 8 * page_size, PROT_READ,
1337 MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1339 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1340 FAIL_TEST_IF_FALSE(errno == EPERM);
1342 FAIL_TEST_IF_FALSE(ret2 == ptr);
1347 static void test_seal_mremap_shrink_fixed(bool seal)
1351 unsigned long page_size = getpagesize();
1352 unsigned long size = 4 * page_size;
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);
1362 ret = sys_mseal(ptr, size);
1363 FAIL_TEST_IF_FALSE(!ret);
1366 /* mremap to move and shrink to fixed address */
1367 ret2 = sys_mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED,
1370 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1371 FAIL_TEST_IF_FALSE(errno == EPERM);
1373 FAIL_TEST_IF_FALSE(ret2 == newAddr);
1378 static void test_seal_mremap_expand_fixed(bool seal)
1382 unsigned long page_size = getpagesize();
1383 unsigned long size = 4 * page_size;
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);
1393 ret = sys_mseal(newAddr, size);
1394 FAIL_TEST_IF_FALSE(!ret);
1397 /* mremap to move and expand to fixed address */
1398 ret2 = sys_mremap(ptr, page_size, size, MREMAP_MAYMOVE | MREMAP_FIXED,
1401 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1402 FAIL_TEST_IF_FALSE(errno == EPERM);
1404 FAIL_TEST_IF_FALSE(ret2 == newAddr);
1409 static void test_seal_mremap_move_fixed(bool seal)
1413 unsigned long page_size = getpagesize();
1414 unsigned long size = 4 * page_size;
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);
1424 ret = sys_mseal(newAddr, size);
1425 FAIL_TEST_IF_FALSE(!ret);
1428 /* mremap to move to fixed address */
1429 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newAddr);
1431 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1432 FAIL_TEST_IF_FALSE(errno == EPERM);
1434 FAIL_TEST_IF_FALSE(ret2 == newAddr);
1439 static void test_seal_mremap_move_fixed_zero(bool seal)
1442 unsigned long page_size = getpagesize();
1443 unsigned long size = 4 * page_size;
1447 setup_single_address(size, &ptr);
1448 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1451 ret = sys_mseal(ptr, size);
1452 FAIL_TEST_IF_FALSE(!ret);
1456 * MREMAP_FIXED can move the mapping to zero address
1458 ret2 = sys_mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED,
1461 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1462 FAIL_TEST_IF_FALSE(errno == EPERM);
1464 FAIL_TEST_IF_FALSE(ret2 == 0);
1470 static void test_seal_mremap_move_dontunmap(bool seal)
1473 unsigned long page_size = getpagesize();
1474 unsigned long size = 4 * page_size;
1478 setup_single_address(size, &ptr);
1479 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1482 ret = sys_mseal(ptr, size);
1483 FAIL_TEST_IF_FALSE(!ret);
1486 /* mremap to move, and don't unmap src addr. */
1487 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 0);
1489 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1490 FAIL_TEST_IF_FALSE(errno == EPERM);
1492 /* kernel will allocate a new address */
1493 FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
1499 static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
1502 unsigned long page_size = getpagesize();
1503 unsigned long size = 4 * page_size;
1507 setup_single_address(size, &ptr);
1508 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1511 ret = sys_mseal(ptr, size);
1512 FAIL_TEST_IF_FALSE(!ret);
1516 * The new address is any address that not allocated.
1517 * use allocate/free to similate that.
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);
1525 * remap to any address.
1527 ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP,
1530 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1531 FAIL_TEST_IF_FALSE(errno == EPERM);
1533 /* remap success and return ptr2 */
1534 FAIL_TEST_IF_FALSE(ret2 == ptr2);
1540 static void test_seal_merge_and_split(void)
1543 unsigned long page_size = getpagesize();
1549 setup_single_address(24 * page_size, &ptr);
1550 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
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);
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);
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);
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);
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);
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);
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);
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);
1632 static void test_seal_discard_ro_anon_on_rw(bool seal)
1635 unsigned long page_size = getpagesize();
1636 unsigned long size = 4 * page_size;
1639 setup_single_address_rw(size, &ptr);
1640 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1643 ret = sys_mseal(ptr, size);
1644 FAIL_TEST_IF_FALSE(!ret);
1647 /* sealing doesn't take effect on RW memory. */
1648 ret = sys_madvise(ptr, size, MADV_DONTNEED);
1649 FAIL_TEST_IF_FALSE(!ret);
1651 /* base seal still apply. */
1652 ret = sys_munmap(ptr, size);
1654 FAIL_TEST_IF_FALSE(ret < 0);
1656 FAIL_TEST_IF_FALSE(!ret);
1661 static void test_seal_discard_ro_anon_on_pkey(bool seal)
1664 unsigned long page_size = getpagesize();
1665 unsigned long size = 4 * page_size;
1669 SKIP_TEST_IF_FALSE(pkey_supported());
1671 setup_single_address_rw(size, &ptr);
1672 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1674 pkey = sys_pkey_alloc(0, 0);
1675 FAIL_TEST_IF_FALSE(pkey > 0);
1677 ret = sys_mprotect_pkey((void *)ptr, size, PROT_READ | PROT_WRITE, pkey);
1678 FAIL_TEST_IF_FALSE(!ret);
1681 ret = sys_mseal(ptr, size);
1682 FAIL_TEST_IF_FALSE(!ret);
1685 /* sealing doesn't take effect if PKRU allow write. */
1687 ret = sys_madvise(ptr, size, MADV_DONTNEED);
1688 FAIL_TEST_IF_FALSE(!ret);
1690 /* sealing will take effect if PKRU deny write. */
1691 set_pkey(pkey, PKEY_DISABLE_WRITE);
1692 ret = sys_madvise(ptr, size, MADV_DONTNEED);
1694 FAIL_TEST_IF_FALSE(ret < 0);
1696 FAIL_TEST_IF_FALSE(!ret);
1698 /* base seal still apply. */
1699 ret = sys_munmap(ptr, size);
1701 FAIL_TEST_IF_FALSE(ret < 0);
1703 FAIL_TEST_IF_FALSE(!ret);
1708 static void test_seal_discard_ro_anon_on_filebacked(bool seal)
1711 unsigned long page_size = getpagesize();
1712 unsigned long size = 4 * page_size;
1715 unsigned long mapflags = MAP_PRIVATE;
1717 fd = memfd_create("test", 0);
1718 FAIL_TEST_IF_FALSE(fd > 0);
1720 ret = fallocate(fd, 0, 0, size);
1721 FAIL_TEST_IF_FALSE(!ret);
1723 ptr = mmap(NULL, size, PROT_READ, mapflags, fd, 0);
1724 FAIL_TEST_IF_FALSE(ptr != MAP_FAILED);
1727 ret = sys_mseal(ptr, size);
1728 FAIL_TEST_IF_FALSE(!ret);
1731 /* sealing doesn't apply for file backed mapping. */
1732 ret = sys_madvise(ptr, size, MADV_DONTNEED);
1733 FAIL_TEST_IF_FALSE(!ret);
1735 ret = sys_munmap(ptr, size);
1737 FAIL_TEST_IF_FALSE(ret < 0);
1739 FAIL_TEST_IF_FALSE(!ret);
1745 static void test_seal_discard_ro_anon_on_shared(bool seal)
1748 unsigned long page_size = getpagesize();
1749 unsigned long size = 4 * page_size;
1751 unsigned long mapflags = MAP_ANONYMOUS | MAP_SHARED;
1753 ptr = mmap(NULL, size, PROT_READ, mapflags, -1, 0);
1754 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1757 ret = sys_mseal(ptr, size);
1758 FAIL_TEST_IF_FALSE(!ret);
1761 /* sealing doesn't apply for shared mapping. */
1762 ret = sys_madvise(ptr, size, MADV_DONTNEED);
1763 FAIL_TEST_IF_FALSE(!ret);
1765 ret = sys_munmap(ptr, size);
1767 FAIL_TEST_IF_FALSE(ret < 0);
1769 FAIL_TEST_IF_FALSE(!ret);
1774 static void test_seal_discard_ro_anon(bool seal)
1777 unsigned long page_size = getpagesize();
1778 unsigned long size = 4 * page_size;
1781 setup_single_address(size, &ptr);
1782 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1785 ret = seal_single_address(ptr, size);
1786 FAIL_TEST_IF_FALSE(!ret);
1789 ret = sys_madvise(ptr, size, MADV_DONTNEED);
1791 FAIL_TEST_IF_FALSE(ret < 0);
1793 FAIL_TEST_IF_FALSE(!ret);
1795 ret = sys_munmap(ptr, size);
1797 FAIL_TEST_IF_FALSE(ret < 0);
1799 FAIL_TEST_IF_FALSE(!ret);
1804 static void test_seal_discard_across_vmas(bool seal)
1807 unsigned long page_size = getpagesize();
1808 unsigned long size = 2 * page_size;
1811 setup_single_address(size, &ptr);
1812 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1815 ret = seal_single_address(ptr + page_size, page_size);
1816 FAIL_TEST_IF_FALSE(!ret);
1819 ret = sys_madvise(ptr, size, MADV_DONTNEED);
1821 FAIL_TEST_IF_FALSE(ret < 0);
1823 FAIL_TEST_IF_FALSE(!ret);
1825 ret = sys_munmap(ptr, size);
1827 FAIL_TEST_IF_FALSE(ret < 0);
1829 FAIL_TEST_IF_FALSE(!ret);
1835 static void test_seal_madvise_nodiscard(bool seal)
1838 unsigned long page_size = getpagesize();
1839 unsigned long size = 4 * page_size;
1842 setup_single_address(size, &ptr);
1843 FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1846 ret = seal_single_address(ptr, size);
1847 FAIL_TEST_IF_FALSE(!ret);
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.
1855 ret = sys_madvise(ptr, size, MADV_RANDOM);
1856 FAIL_TEST_IF_FALSE(!ret);
1858 ret = sys_munmap(ptr, size);
1860 FAIL_TEST_IF_FALSE(ret < 0);
1862 FAIL_TEST_IF_FALSE(!ret);
1867 int main(int argc, char **argv)
1869 bool test_seal = seal_support();
1871 ksft_print_header();
1874 ksft_exit_skip("sealing not supported, check CONFIG_64BIT\n");
1876 if (!pkey_supported())
1877 ksft_print_msg("PKEY not supported\n");
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();
1892 test_seal_mprotect(false);
1893 test_seal_mprotect(true);
1895 test_seal_start_mprotect(false);
1896 test_seal_start_mprotect(true);
1898 test_seal_end_mprotect(false);
1899 test_seal_end_mprotect(true);
1901 test_seal_mprotect_unalign_len(false);
1902 test_seal_mprotect_unalign_len(true);
1904 test_seal_mprotect_unalign_len_variant_2(false);
1905 test_seal_mprotect_unalign_len_variant_2(true);
1907 test_seal_mprotect_two_vma(false);
1908 test_seal_mprotect_two_vma(true);
1910 test_seal_mprotect_two_vma_with_split(false);
1911 test_seal_mprotect_two_vma_with_split(true);
1913 test_seal_mprotect_partial_mprotect(false);
1914 test_seal_mprotect_partial_mprotect(true);
1916 test_seal_mprotect_two_vma_with_gap(false);
1917 test_seal_mprotect_two_vma_with_gap(true);
1919 test_seal_mprotect_merge(false);
1920 test_seal_mprotect_merge(true);
1922 test_seal_mprotect_split(false);
1923 test_seal_mprotect_split(true);
1925 test_seal_mprotect_partial_mprotect_tail(false);
1926 test_seal_mprotect_partial_mprotect_tail(true);
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);
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);
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);
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);
1982 test_seal_merge_and_split();
1983 test_seal_zero_address();
1985 test_seal_discard_ro_anon_on_pkey(false);
1986 test_seal_discard_ro_anon_on_pkey(true);