~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/mm/mseal_test.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #define _GNU_SOURCE
  3 #include <linux/mman.h>
  4 #include <sys/mman.h>
  5 #include <stdint.h>
  6 #include <asm-generic/unistd.h>
  7 #include <string.h>
  8 #include <sys/time.h>
  9 #include <sys/resource.h>
 10 #include <stdbool.h>
 11 #include "../kselftest.h"
 12 #include <syscall.h>
 13 #include <errno.h>
 14 #include <stdio.h>
 15 #include <stdlib.h>
 16 #include <fcntl.h>
 17 #include <sys/ioctl.h>
 18 #include <sys/vfs.h>
 19 #include <sys/stat.h>
 20 #include "mseal_helpers.h"
 21 
 22 static unsigned long get_vma_size(void *addr, int *prot)
 23 {
 24         FILE *maps;
 25         char line[256];
 26         int size = 0;
 27         uintptr_t  addr_start, addr_end;
 28         char protstr[5];
 29         *prot = 0;
 30 
 31         maps = fopen("/proc/self/maps", "r");
 32         if (!maps)
 33                 return 0;
 34 
 35         while (fgets(line, sizeof(line), maps)) {
 36                 if (sscanf(line, "%lx-%lx %4s", &addr_start, &addr_end, protstr) == 3) {
 37                         if (addr_start == (uintptr_t) addr) {
 38                                 size = addr_end - addr_start;
 39                                 if (protstr[0] == 'r')
 40                                         *prot |= 0x4;
 41                                 if (protstr[1] == 'w')
 42                                         *prot |= 0x2;
 43                                 if (protstr[2] == 'x')
 44                                         *prot |= 0x1;
 45                                 break;
 46                         }
 47                 }
 48         }
 49         fclose(maps);
 50         return size;
 51 }
 52 
 53 /*
 54  * define sys_xyx to call syscall directly.
 55  */
 56 static int sys_mseal(void *start, size_t len)
 57 {
 58         int sret;
 59 
 60         errno = 0;
 61         sret = syscall(__NR_mseal, start, len, 0);
 62         return sret;
 63 }
 64 
 65 static int sys_mprotect(void *ptr, size_t size, unsigned long prot)
 66 {
 67         int sret;
 68 
 69         errno = 0;
 70         sret = syscall(__NR_mprotect, ptr, size, prot);
 71         return sret;
 72 }
 73 
 74 static int sys_mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
 75                 unsigned long pkey)
 76 {
 77         int sret;
 78 
 79         errno = 0;
 80         sret = syscall(__NR_pkey_mprotect, ptr, size, orig_prot, pkey);
 81         return sret;
 82 }
 83 
 84 static int sys_munmap(void *ptr, size_t size)
 85 {
 86         int sret;
 87 
 88         errno = 0;
 89         sret = syscall(__NR_munmap, ptr, size);
 90         return sret;
 91 }
 92 
 93 static int sys_madvise(void *start, size_t len, int types)
 94 {
 95         int sret;
 96 
 97         errno = 0;
 98         sret = syscall(__NR_madvise, start, len, types);
 99         return sret;
100 }
101 
102 static 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 
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 
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 
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 
146 static unsigned long pkey_bit_position(int pkey)
147 {
148         return pkey * PKEY_BITS_PER_PKEY;
149 }
150 
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 
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 
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 
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 
187 static int clean_single_address(void *ptr, int size)
188 {
189         int ret;
190         ret = munmap(ptr, size);
191         return ret;
192 }
193 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
769 static void test_seal_mprotect_two_vma_with_gap(bool seal)
770 {
771         void *ptr;
772         unsigned long page_size = getpagesize();
773         unsigned long size = 4 * page_size;
774         int ret;
775 
776         setup_single_address(size, &ptr);
777         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
778 
779         /* use mprotect to split. */
780         ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
781         FAIL_TEST_IF_FALSE(!ret);
782 
783         /* use mprotect to split. */
784         ret = sys_mprotect(ptr + 3 * page_size, page_size,
785                         PROT_READ | PROT_WRITE);
786         FAIL_TEST_IF_FALSE(!ret);
787 
788         /* use munmap to free two pages in the middle */
789         ret = sys_munmap(ptr + page_size, 2 * page_size);
790         FAIL_TEST_IF_FALSE(!ret);
791 
792         /* mprotect will fail, because there is a gap in the address. */
793         /* notes, internally mprotect still updated the first page. */
794         ret = sys_mprotect(ptr, 4 * page_size, PROT_READ);
795         FAIL_TEST_IF_FALSE(ret < 0);
796 
797         /* mseal will fail as well. */
798         ret = sys_mseal(ptr, 4 * page_size);
799         FAIL_TEST_IF_FALSE(ret < 0);
800 
801         /* the first page is not sealed. */
802         ret = sys_mprotect(ptr, page_size, PROT_READ);
803         FAIL_TEST_IF_FALSE(ret == 0);
804 
805         /* the last page is not sealed. */
806         ret = sys_mprotect(ptr + 3 * page_size, page_size, PROT_READ);
807         FAIL_TEST_IF_FALSE(ret == 0);
808 
809         REPORT_TEST_PASS();
810 }
811 
812 static void test_seal_mprotect_split(bool seal)
813 {
814         void *ptr;
815         unsigned long page_size = getpagesize();
816         unsigned long size = 4 * page_size;
817         int ret;
818 
819         setup_single_address(size, &ptr);
820         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
821 
822         /* use mprotect to split. */
823         ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
824         FAIL_TEST_IF_FALSE(!ret);
825 
826         /* seal all 4 pages. */
827         if (seal) {
828                 ret = sys_mseal(ptr, 4 * page_size);
829                 FAIL_TEST_IF_FALSE(!ret);
830         }
831 
832         /* mprotect is sealed. */
833         ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
834         if (seal)
835                 FAIL_TEST_IF_FALSE(ret < 0);
836         else
837                 FAIL_TEST_IF_FALSE(!ret);
838 
839 
840         ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ);
841         if (seal)
842                 FAIL_TEST_IF_FALSE(ret < 0);
843         else
844                 FAIL_TEST_IF_FALSE(!ret);
845 
846         REPORT_TEST_PASS();
847 }
848 
849 static void test_seal_mprotect_merge(bool seal)
850 {
851         void *ptr;
852         unsigned long page_size = getpagesize();
853         unsigned long size = 4 * page_size;
854         int ret;
855 
856         setup_single_address(size, &ptr);
857         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
858 
859         /* use mprotect to split one page. */
860         ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE);
861         FAIL_TEST_IF_FALSE(!ret);
862 
863         /* seal first two pages. */
864         if (seal) {
865                 ret = sys_mseal(ptr, 2 * page_size);
866                 FAIL_TEST_IF_FALSE(!ret);
867         }
868 
869         /* 2 pages are sealed. */
870         ret = sys_mprotect(ptr, 2 * page_size, PROT_READ);
871         if (seal)
872                 FAIL_TEST_IF_FALSE(ret < 0);
873         else
874                 FAIL_TEST_IF_FALSE(!ret);
875 
876         /* last 2 pages are not sealed. */
877         ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ);
878         FAIL_TEST_IF_FALSE(ret == 0);
879 
880         REPORT_TEST_PASS();
881 }
882 
883 static void test_seal_munmap(bool seal)
884 {
885         void *ptr;
886         unsigned long page_size = getpagesize();
887         unsigned long size = 4 * page_size;
888         int ret;
889 
890         setup_single_address(size, &ptr);
891         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
892 
893         if (seal) {
894                 ret = sys_mseal(ptr, size);
895                 FAIL_TEST_IF_FALSE(!ret);
896         }
897 
898         /* 4 pages are sealed. */
899         ret = sys_munmap(ptr, size);
900         if (seal)
901                 FAIL_TEST_IF_FALSE(ret < 0);
902         else
903                 FAIL_TEST_IF_FALSE(!ret);
904 
905         REPORT_TEST_PASS();
906 }
907 
908 /*
909  * allocate 4 pages,
910  * use mprotect to split it as two VMAs
911  * seal the whole range
912  * munmap will fail on both
913  */
914 static void test_seal_munmap_two_vma(bool seal)
915 {
916         void *ptr;
917         unsigned long page_size = getpagesize();
918         unsigned long size = 4 * page_size;
919         int ret;
920 
921         setup_single_address(size, &ptr);
922         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
923 
924         /* use mprotect to split */
925         ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE);
926         FAIL_TEST_IF_FALSE(!ret);
927 
928         if (seal) {
929                 ret = sys_mseal(ptr, size);
930                 FAIL_TEST_IF_FALSE(!ret);
931         }
932 
933         ret = sys_munmap(ptr, page_size * 2);
934         if (seal)
935                 FAIL_TEST_IF_FALSE(ret < 0);
936         else
937                 FAIL_TEST_IF_FALSE(!ret);
938 
939         ret = sys_munmap(ptr + page_size, page_size * 2);
940         if (seal)
941                 FAIL_TEST_IF_FALSE(ret < 0);
942         else
943                 FAIL_TEST_IF_FALSE(!ret);
944 
945         REPORT_TEST_PASS();
946 }
947 
948 /*
949  * allocate a VMA with 4 pages.
950  * munmap the middle 2 pages.
951  * seal the whole 4 pages, will fail.
952  * munmap the first page will be OK.
953  * munmap the last page will be OK.
954  */
955 static void test_seal_munmap_vma_with_gap(bool seal)
956 {
957         void *ptr;
958         unsigned long page_size = getpagesize();
959         unsigned long size = 4 * page_size;
960         int ret;
961 
962         setup_single_address(size, &ptr);
963         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
964 
965         ret = sys_munmap(ptr + page_size, page_size * 2);
966         FAIL_TEST_IF_FALSE(!ret);
967 
968         if (seal) {
969                 /* can't have gap in the middle. */
970                 ret = sys_mseal(ptr, size);
971                 FAIL_TEST_IF_FALSE(ret < 0);
972         }
973 
974         ret = sys_munmap(ptr, page_size);
975         FAIL_TEST_IF_FALSE(!ret);
976 
977         ret = sys_munmap(ptr + page_size * 2, page_size);
978         FAIL_TEST_IF_FALSE(!ret);
979 
980         ret = sys_munmap(ptr, size);
981         FAIL_TEST_IF_FALSE(!ret);
982 
983         REPORT_TEST_PASS();
984 }
985 
986 static void test_munmap_start_freed(bool seal)
987 {
988         void *ptr;
989         unsigned long page_size = getpagesize();
990         unsigned long size = 4 * page_size;
991         int ret;
992         int prot;
993 
994         setup_single_address(size, &ptr);
995         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
996 
997         /* unmap the first page. */
998         ret = sys_munmap(ptr, page_size);
999         FAIL_TEST_IF_FALSE(!ret);
1000 
1001         /* seal the last 3 pages. */
1002         if (seal) {
1003                 ret = sys_mseal(ptr + page_size, 3 * page_size);
1004                 FAIL_TEST_IF_FALSE(!ret);
1005         }
1006 
1007         /* unmap from the first page. */
1008         ret = sys_munmap(ptr, size);
1009         if (seal) {
1010                 FAIL_TEST_IF_FALSE(ret < 0);
1011 
1012                 size = get_vma_size(ptr + page_size, &prot);
1013                 FAIL_TEST_IF_FALSE(size == page_size * 3);
1014         } else {
1015                 /* note: this will be OK, even the first page is */
1016                 /* already unmapped. */
1017                 FAIL_TEST_IF_FALSE(!ret);
1018 
1019                 size = get_vma_size(ptr + page_size, &prot);
1020                 FAIL_TEST_IF_FALSE(size == 0);
1021         }
1022 
1023         REPORT_TEST_PASS();
1024 }
1025 
1026 static void test_munmap_end_freed(bool seal)
1027 {
1028         void *ptr;
1029         unsigned long page_size = getpagesize();
1030         unsigned long size = 4 * page_size;
1031         int ret;
1032 
1033         setup_single_address(size, &ptr);
1034         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1035 
1036         /* unmap last page. */
1037         ret = sys_munmap(ptr + page_size * 3, page_size);
1038         FAIL_TEST_IF_FALSE(!ret);
1039 
1040         /* seal the first 3 pages. */
1041         if (seal) {
1042                 ret = sys_mseal(ptr, 3 * page_size);
1043                 FAIL_TEST_IF_FALSE(!ret);
1044         }
1045 
1046         /* unmap all pages. */
1047         ret = sys_munmap(ptr, size);
1048         if (seal)
1049                 FAIL_TEST_IF_FALSE(ret < 0);
1050         else
1051                 FAIL_TEST_IF_FALSE(!ret);
1052 
1053         REPORT_TEST_PASS();
1054 }
1055 
1056 static void test_munmap_middle_freed(bool seal)
1057 {
1058         void *ptr;
1059         unsigned long page_size = getpagesize();
1060         unsigned long size = 4 * page_size;
1061         int ret;
1062         int prot;
1063 
1064         setup_single_address(size, &ptr);
1065         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1066 
1067         /* unmap 2 pages in the middle. */
1068         ret = sys_munmap(ptr + page_size, page_size * 2);
1069         FAIL_TEST_IF_FALSE(!ret);
1070 
1071         /* seal the first page. */
1072         if (seal) {
1073                 ret = sys_mseal(ptr, page_size);
1074                 FAIL_TEST_IF_FALSE(!ret);
1075         }
1076 
1077         /* munmap all 4 pages. */
1078         ret = sys_munmap(ptr, size);
1079         if (seal) {
1080                 FAIL_TEST_IF_FALSE(ret < 0);
1081 
1082                 size = get_vma_size(ptr, &prot);
1083                 FAIL_TEST_IF_FALSE(size == page_size);
1084 
1085                 size = get_vma_size(ptr + page_size * 3, &prot);
1086                 FAIL_TEST_IF_FALSE(size == page_size);
1087         } else {
1088                 FAIL_TEST_IF_FALSE(!ret);
1089 
1090                 size = get_vma_size(ptr, &prot);
1091                 FAIL_TEST_IF_FALSE(size == 0);
1092 
1093                 size = get_vma_size(ptr + page_size * 3, &prot);
1094                 FAIL_TEST_IF_FALSE(size == 0);
1095         }
1096 
1097         REPORT_TEST_PASS();
1098 }
1099 
1100 static void test_seal_mremap_shrink(bool seal)
1101 {
1102         void *ptr;
1103         unsigned long page_size = getpagesize();
1104         unsigned long size = 4 * page_size;
1105         int ret;
1106         void *ret2;
1107 
1108         setup_single_address(size, &ptr);
1109         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1110 
1111         if (seal) {
1112                 ret = sys_mseal(ptr, size);
1113                 FAIL_TEST_IF_FALSE(!ret);
1114         }
1115 
1116         /* shrink from 4 pages to 2 pages. */
1117         ret2 = sys_mremap(ptr, size, 2 * page_size, 0, 0);
1118         if (seal) {
1119                 FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED);
1120                 FAIL_TEST_IF_FALSE(errno == EPERM);
1121         } else {
1122                 FAIL_TEST_IF_FALSE(ret2 != (void *) MAP_FAILED);
1123 
1124         }
1125 
1126         REPORT_TEST_PASS();
1127 }
1128 
1129 static void test_seal_mremap_expand(bool seal)
1130 {
1131         void *ptr;
1132         unsigned long page_size = getpagesize();
1133         unsigned long size = 4 * page_size;
1134         int ret;
1135         void *ret2;
1136 
1137         setup_single_address(size, &ptr);
1138         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1139         /* ummap last 2 pages. */
1140         ret = sys_munmap(ptr + 2 * page_size, 2 * page_size);
1141         FAIL_TEST_IF_FALSE(!ret);
1142 
1143         if (seal) {
1144                 ret = sys_mseal(ptr, 2 * page_size);
1145                 FAIL_TEST_IF_FALSE(!ret);
1146         }
1147 
1148         /* expand from 2 page to 4 pages. */
1149         ret2 = sys_mremap(ptr, 2 * page_size, 4 * page_size, 0, 0);
1150         if (seal) {
1151                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1152                 FAIL_TEST_IF_FALSE(errno == EPERM);
1153         } else {
1154                 FAIL_TEST_IF_FALSE(ret2 == ptr);
1155 
1156         }
1157 
1158         REPORT_TEST_PASS();
1159 }
1160 
1161 static void test_seal_mremap_move(bool seal)
1162 {
1163         void *ptr, *newPtr;
1164         unsigned long page_size = getpagesize();
1165         unsigned long size = page_size;
1166         int ret;
1167         void *ret2;
1168 
1169         setup_single_address(size, &ptr);
1170         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1171         setup_single_address(size, &newPtr);
1172         FAIL_TEST_IF_FALSE(newPtr != (void *)-1);
1173         ret = clean_single_address(newPtr, size);
1174         FAIL_TEST_IF_FALSE(!ret);
1175 
1176         if (seal) {
1177                 ret = sys_mseal(ptr, size);
1178                 FAIL_TEST_IF_FALSE(!ret);
1179         }
1180 
1181         /* move from ptr to fixed address. */
1182         ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newPtr);
1183         if (seal) {
1184                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1185                 FAIL_TEST_IF_FALSE(errno == EPERM);
1186         } else {
1187                 FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
1188 
1189         }
1190 
1191         REPORT_TEST_PASS();
1192 }
1193 
1194 static void test_seal_mmap_overwrite_prot(bool seal)
1195 {
1196         void *ptr;
1197         unsigned long page_size = getpagesize();
1198         unsigned long size = page_size;
1199         int ret;
1200         void *ret2;
1201 
1202         setup_single_address(size, &ptr);
1203         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1204 
1205         if (seal) {
1206                 ret = sys_mseal(ptr, size);
1207                 FAIL_TEST_IF_FALSE(!ret);
1208         }
1209 
1210         /* use mmap to change protection. */
1211         ret2 = mmap(ptr, size, PROT_NONE,
1212                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1213         if (seal) {
1214                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1215                 FAIL_TEST_IF_FALSE(errno == EPERM);
1216         } else
1217                 FAIL_TEST_IF_FALSE(ret2 == ptr);
1218 
1219         REPORT_TEST_PASS();
1220 }
1221 
1222 static void test_seal_mmap_expand(bool seal)
1223 {
1224         void *ptr;
1225         unsigned long page_size = getpagesize();
1226         unsigned long size = 12 * page_size;
1227         int ret;
1228         void *ret2;
1229 
1230         setup_single_address(size, &ptr);
1231         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1232         /* ummap last 4 pages. */
1233         ret = sys_munmap(ptr + 8 * page_size, 4 * page_size);
1234         FAIL_TEST_IF_FALSE(!ret);
1235 
1236         if (seal) {
1237                 ret = sys_mseal(ptr, 8 * page_size);
1238                 FAIL_TEST_IF_FALSE(!ret);
1239         }
1240 
1241         /* use mmap to expand. */
1242         ret2 = mmap(ptr, size, PROT_READ,
1243                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1244         if (seal) {
1245                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1246                 FAIL_TEST_IF_FALSE(errno == EPERM);
1247         } else
1248                 FAIL_TEST_IF_FALSE(ret2 == ptr);
1249 
1250         REPORT_TEST_PASS();
1251 }
1252 
1253 static void test_seal_mmap_shrink(bool seal)
1254 {
1255         void *ptr;
1256         unsigned long page_size = getpagesize();
1257         unsigned long size = 12 * page_size;
1258         int ret;
1259         void *ret2;
1260 
1261         setup_single_address(size, &ptr);
1262         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1263 
1264         if (seal) {
1265                 ret = sys_mseal(ptr, size);
1266                 FAIL_TEST_IF_FALSE(!ret);
1267         }
1268 
1269         /* use mmap to shrink. */
1270         ret2 = mmap(ptr, 8 * page_size, PROT_READ,
1271                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
1272         if (seal) {
1273                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1274                 FAIL_TEST_IF_FALSE(errno == EPERM);
1275         } else
1276                 FAIL_TEST_IF_FALSE(ret2 == ptr);
1277 
1278         REPORT_TEST_PASS();
1279 }
1280 
1281 static void test_seal_mremap_shrink_fixed(bool seal)
1282 {
1283         void *ptr;
1284         void *newAddr;
1285         unsigned long page_size = getpagesize();
1286         unsigned long size = 4 * page_size;
1287         int ret;
1288         void *ret2;
1289 
1290         setup_single_address(size, &ptr);
1291         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1292         setup_single_address(size, &newAddr);
1293         FAIL_TEST_IF_FALSE(newAddr != (void *)-1);
1294 
1295         if (seal) {
1296                 ret = sys_mseal(ptr, size);
1297                 FAIL_TEST_IF_FALSE(!ret);
1298         }
1299 
1300         /* mremap to move and shrink to fixed address */
1301         ret2 = sys_mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED,
1302                         newAddr);
1303         if (seal) {
1304                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1305                 FAIL_TEST_IF_FALSE(errno == EPERM);
1306         } else
1307                 FAIL_TEST_IF_FALSE(ret2 == newAddr);
1308 
1309         REPORT_TEST_PASS();
1310 }
1311 
1312 static void test_seal_mremap_expand_fixed(bool seal)
1313 {
1314         void *ptr;
1315         void *newAddr;
1316         unsigned long page_size = getpagesize();
1317         unsigned long size = 4 * page_size;
1318         int ret;
1319         void *ret2;
1320 
1321         setup_single_address(page_size, &ptr);
1322         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1323         setup_single_address(size, &newAddr);
1324         FAIL_TEST_IF_FALSE(newAddr != (void *)-1);
1325 
1326         if (seal) {
1327                 ret = sys_mseal(newAddr, size);
1328                 FAIL_TEST_IF_FALSE(!ret);
1329         }
1330 
1331         /* mremap to move and expand to fixed address */
1332         ret2 = sys_mremap(ptr, page_size, size, MREMAP_MAYMOVE | MREMAP_FIXED,
1333                         newAddr);
1334         if (seal) {
1335                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1336                 FAIL_TEST_IF_FALSE(errno == EPERM);
1337         } else
1338                 FAIL_TEST_IF_FALSE(ret2 == newAddr);
1339 
1340         REPORT_TEST_PASS();
1341 }
1342 
1343 static void test_seal_mremap_move_fixed(bool seal)
1344 {
1345         void *ptr;
1346         void *newAddr;
1347         unsigned long page_size = getpagesize();
1348         unsigned long size = 4 * page_size;
1349         int ret;
1350         void *ret2;
1351 
1352         setup_single_address(size, &ptr);
1353         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1354         setup_single_address(size, &newAddr);
1355         FAIL_TEST_IF_FALSE(newAddr != (void *)-1);
1356 
1357         if (seal) {
1358                 ret = sys_mseal(newAddr, size);
1359                 FAIL_TEST_IF_FALSE(!ret);
1360         }
1361 
1362         /* mremap to move to fixed address */
1363         ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, newAddr);
1364         if (seal) {
1365                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1366                 FAIL_TEST_IF_FALSE(errno == EPERM);
1367         } else
1368                 FAIL_TEST_IF_FALSE(ret2 == newAddr);
1369 
1370         REPORT_TEST_PASS();
1371 }
1372 
1373 static void test_seal_mremap_move_fixed_zero(bool seal)
1374 {
1375         void *ptr;
1376         unsigned long page_size = getpagesize();
1377         unsigned long size = 4 * page_size;
1378         int ret;
1379         void *ret2;
1380 
1381         setup_single_address(size, &ptr);
1382         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1383 
1384         if (seal) {
1385                 ret = sys_mseal(ptr, size);
1386                 FAIL_TEST_IF_FALSE(!ret);
1387         }
1388 
1389         /*
1390          * MREMAP_FIXED can move the mapping to zero address
1391          */
1392         ret2 = sys_mremap(ptr, size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_FIXED,
1393                         0);
1394         if (seal) {
1395                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1396                 FAIL_TEST_IF_FALSE(errno == EPERM);
1397         } else {
1398                 FAIL_TEST_IF_FALSE(ret2 == 0);
1399         }
1400 
1401         REPORT_TEST_PASS();
1402 }
1403 
1404 static void test_seal_mremap_move_dontunmap(bool seal)
1405 {
1406         void *ptr;
1407         unsigned long page_size = getpagesize();
1408         unsigned long size = 4 * page_size;
1409         int ret;
1410         void *ret2;
1411 
1412         setup_single_address(size, &ptr);
1413         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1414 
1415         if (seal) {
1416                 ret = sys_mseal(ptr, size);
1417                 FAIL_TEST_IF_FALSE(!ret);
1418         }
1419 
1420         /* mremap to move, and don't unmap src addr. */
1421         ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 0);
1422         if (seal) {
1423                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1424                 FAIL_TEST_IF_FALSE(errno == EPERM);
1425         } else {
1426                 /* kernel will allocate a new address */
1427                 FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
1428         }
1429 
1430         REPORT_TEST_PASS();
1431 }
1432 
1433 static void test_seal_mremap_move_dontunmap_anyaddr(bool seal)
1434 {
1435         void *ptr, *ptr2;
1436         unsigned long page_size = getpagesize();
1437         unsigned long size = 4 * page_size;
1438         int ret;
1439         void *ret2;
1440 
1441         setup_single_address(size, &ptr);
1442         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1443 
1444         if (seal) {
1445                 ret = sys_mseal(ptr, size);
1446                 FAIL_TEST_IF_FALSE(!ret);
1447         }
1448 
1449         /*
1450          * The new address is any address that not allocated.
1451          * use allocate/free to similate that.
1452          */
1453         setup_single_address(size, &ptr2);
1454         FAIL_TEST_IF_FALSE(ptr2 != (void *)-1);
1455         ret = sys_munmap(ptr2, size);
1456         FAIL_TEST_IF_FALSE(!ret);
1457 
1458         /*
1459          * remap to any address.
1460          */
1461         ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP,
1462                         (void *) ptr2);
1463         if (seal) {
1464                 FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED);
1465                 FAIL_TEST_IF_FALSE(errno == EPERM);
1466         } else {
1467                 /* remap success and return ptr2 */
1468                 FAIL_TEST_IF_FALSE(ret2 ==  ptr2);
1469         }
1470 
1471         REPORT_TEST_PASS();
1472 }
1473 
1474 static void test_seal_merge_and_split(void)
1475 {
1476         void *ptr;
1477         unsigned long page_size = getpagesize();
1478         unsigned long size;
1479         int ret;
1480         int prot;
1481 
1482         /* (24 RO) */
1483         setup_single_address(24 * page_size, &ptr);
1484         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1485 
1486         /* use mprotect(NONE) to set out boundary */
1487         /* (1 NONE) (22 RO) (1 NONE) */
1488         ret = sys_mprotect(ptr, page_size, PROT_NONE);
1489         FAIL_TEST_IF_FALSE(!ret);
1490         ret = sys_mprotect(ptr + 23 * page_size, page_size, PROT_NONE);
1491         FAIL_TEST_IF_FALSE(!ret);
1492         size = get_vma_size(ptr + page_size, &prot);
1493         FAIL_TEST_IF_FALSE(size == 22 * page_size);
1494         FAIL_TEST_IF_FALSE(prot == 4);
1495 
1496         /* use mseal to split from beginning */
1497         /* (1 NONE) (1 RO_SEAL) (21 RO) (1 NONE) */
1498         ret = sys_mseal(ptr + page_size, page_size);
1499         FAIL_TEST_IF_FALSE(!ret);
1500         size = get_vma_size(ptr + page_size, &prot);
1501         FAIL_TEST_IF_FALSE(size == page_size);
1502         FAIL_TEST_IF_FALSE(prot == 0x4);
1503         size = get_vma_size(ptr + 2 * page_size, &prot);
1504         FAIL_TEST_IF_FALSE(size == 21 * page_size);
1505         FAIL_TEST_IF_FALSE(prot == 0x4);
1506 
1507         /* use mseal to split from the end. */
1508         /* (1 NONE) (1 RO_SEAL) (20 RO) (1 RO_SEAL) (1 NONE) */
1509         ret = sys_mseal(ptr + 22 * page_size, page_size);
1510         FAIL_TEST_IF_FALSE(!ret);
1511         size = get_vma_size(ptr + 22 * page_size, &prot);
1512         FAIL_TEST_IF_FALSE(size == page_size);
1513         FAIL_TEST_IF_FALSE(prot == 0x4);
1514         size = get_vma_size(ptr + 2 * page_size, &prot);
1515         FAIL_TEST_IF_FALSE(size == 20 * page_size);
1516         FAIL_TEST_IF_FALSE(prot == 0x4);
1517 
1518         /* merge with prev. */
1519         /* (1 NONE) (2 RO_SEAL) (19 RO) (1 RO_SEAL) (1 NONE) */
1520         ret = sys_mseal(ptr + 2 * page_size, page_size);
1521         FAIL_TEST_IF_FALSE(!ret);
1522         size = get_vma_size(ptr +  page_size, &prot);
1523         FAIL_TEST_IF_FALSE(size ==  2 * page_size);
1524         FAIL_TEST_IF_FALSE(prot == 0x4);
1525 
1526         /* merge with after. */
1527         /* (1 NONE) (2 RO_SEAL) (18 RO) (2 RO_SEALS) (1 NONE) */
1528         ret = sys_mseal(ptr + 21 * page_size, page_size);
1529         FAIL_TEST_IF_FALSE(!ret);
1530         size = get_vma_size(ptr +  21 * page_size, &prot);
1531         FAIL_TEST_IF_FALSE(size ==  2 * page_size);
1532         FAIL_TEST_IF_FALSE(prot == 0x4);
1533 
1534         /* split and merge from prev */
1535         /* (1 NONE) (3 RO_SEAL) (17 RO) (2 RO_SEALS) (1 NONE) */
1536         ret = sys_mseal(ptr + 2 * page_size, 2 * page_size);
1537         FAIL_TEST_IF_FALSE(!ret);
1538         size = get_vma_size(ptr +  1 * page_size, &prot);
1539         FAIL_TEST_IF_FALSE(size ==  3 * page_size);
1540         FAIL_TEST_IF_FALSE(prot == 0x4);
1541         ret = sys_munmap(ptr + page_size,  page_size);
1542         FAIL_TEST_IF_FALSE(ret < 0);
1543         ret = sys_mprotect(ptr + 2 * page_size, page_size,  PROT_NONE);
1544         FAIL_TEST_IF_FALSE(ret < 0);
1545 
1546         /* split and merge from next */
1547         /* (1 NONE) (3 RO_SEAL) (16 RO) (3 RO_SEALS) (1 NONE) */
1548         ret = sys_mseal(ptr + 20 * page_size, 2 * page_size);
1549         FAIL_TEST_IF_FALSE(!ret);
1550         FAIL_TEST_IF_FALSE(prot == 0x4);
1551         size = get_vma_size(ptr +  20 * page_size, &prot);
1552         FAIL_TEST_IF_FALSE(size ==  3 * page_size);
1553         FAIL_TEST_IF_FALSE(prot == 0x4);
1554 
1555         /* merge from middle of prev and middle of next. */
1556         /* (1 NONE) (22 RO_SEAL) (1 NONE) */
1557         ret = sys_mseal(ptr + 2 * page_size, 20 * page_size);
1558         FAIL_TEST_IF_FALSE(!ret);
1559         size = get_vma_size(ptr +  page_size, &prot);
1560         FAIL_TEST_IF_FALSE(size ==  22 * page_size);
1561         FAIL_TEST_IF_FALSE(prot == 0x4);
1562 
1563         REPORT_TEST_PASS();
1564 }
1565 
1566 static void test_seal_discard_ro_anon_on_rw(bool seal)
1567 {
1568         void *ptr;
1569         unsigned long page_size = getpagesize();
1570         unsigned long size = 4 * page_size;
1571         int ret;
1572 
1573         setup_single_address_rw(size, &ptr);
1574         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1575 
1576         if (seal) {
1577                 ret = sys_mseal(ptr, size);
1578                 FAIL_TEST_IF_FALSE(!ret);
1579         }
1580 
1581         /* sealing doesn't take effect on RW memory. */
1582         ret = sys_madvise(ptr, size, MADV_DONTNEED);
1583         FAIL_TEST_IF_FALSE(!ret);
1584 
1585         /* base seal still apply. */
1586         ret = sys_munmap(ptr, size);
1587         if (seal)
1588                 FAIL_TEST_IF_FALSE(ret < 0);
1589         else
1590                 FAIL_TEST_IF_FALSE(!ret);
1591 
1592         REPORT_TEST_PASS();
1593 }
1594 
1595 static void test_seal_discard_ro_anon_on_pkey(bool seal)
1596 {
1597         void *ptr;
1598         unsigned long page_size = getpagesize();
1599         unsigned long size = 4 * page_size;
1600         int ret;
1601         int pkey;
1602 
1603         SKIP_TEST_IF_FALSE(pkey_supported());
1604 
1605         setup_single_address_rw(size, &ptr);
1606         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1607 
1608         pkey = sys_pkey_alloc(0, 0);
1609         FAIL_TEST_IF_FALSE(pkey > 0);
1610 
1611         ret = sys_mprotect_pkey((void *)ptr, size, PROT_READ | PROT_WRITE, pkey);
1612         FAIL_TEST_IF_FALSE(!ret);
1613 
1614         if (seal) {
1615                 ret = sys_mseal(ptr, size);
1616                 FAIL_TEST_IF_FALSE(!ret);
1617         }
1618 
1619         /* sealing doesn't take effect if PKRU allow write. */
1620         set_pkey(pkey, 0);
1621         ret = sys_madvise(ptr, size, MADV_DONTNEED);
1622         FAIL_TEST_IF_FALSE(!ret);
1623 
1624         /* sealing will take effect if PKRU deny write. */
1625         set_pkey(pkey, PKEY_DISABLE_WRITE);
1626         ret = sys_madvise(ptr, size, MADV_DONTNEED);
1627         if (seal)
1628                 FAIL_TEST_IF_FALSE(ret < 0);
1629         else
1630                 FAIL_TEST_IF_FALSE(!ret);
1631 
1632         /* base seal still apply. */
1633         ret = sys_munmap(ptr, size);
1634         if (seal)
1635                 FAIL_TEST_IF_FALSE(ret < 0);
1636         else
1637                 FAIL_TEST_IF_FALSE(!ret);
1638 
1639         REPORT_TEST_PASS();
1640 }
1641 
1642 static void test_seal_discard_ro_anon_on_filebacked(bool seal)
1643 {
1644         void *ptr;
1645         unsigned long page_size = getpagesize();
1646         unsigned long size = 4 * page_size;
1647         int ret;
1648         int fd;
1649         unsigned long mapflags = MAP_PRIVATE;
1650 
1651         fd = memfd_create("test", 0);
1652         FAIL_TEST_IF_FALSE(fd > 0);
1653 
1654         ret = fallocate(fd, 0, 0, size);
1655         FAIL_TEST_IF_FALSE(!ret);
1656 
1657         ptr = mmap(NULL, size, PROT_READ, mapflags, fd, 0);
1658         FAIL_TEST_IF_FALSE(ptr != MAP_FAILED);
1659 
1660         if (seal) {
1661                 ret = sys_mseal(ptr, size);
1662                 FAIL_TEST_IF_FALSE(!ret);
1663         }
1664 
1665         /* sealing doesn't apply for file backed mapping. */
1666         ret = sys_madvise(ptr, size, MADV_DONTNEED);
1667         FAIL_TEST_IF_FALSE(!ret);
1668 
1669         ret = sys_munmap(ptr, size);
1670         if (seal)
1671                 FAIL_TEST_IF_FALSE(ret < 0);
1672         else
1673                 FAIL_TEST_IF_FALSE(!ret);
1674         close(fd);
1675 
1676         REPORT_TEST_PASS();
1677 }
1678 
1679 static void test_seal_discard_ro_anon_on_shared(bool seal)
1680 {
1681         void *ptr;
1682         unsigned long page_size = getpagesize();
1683         unsigned long size = 4 * page_size;
1684         int ret;
1685         unsigned long mapflags = MAP_ANONYMOUS | MAP_SHARED;
1686 
1687         ptr = mmap(NULL, size, PROT_READ, mapflags, -1, 0);
1688         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1689 
1690         if (seal) {
1691                 ret = sys_mseal(ptr, size);
1692                 FAIL_TEST_IF_FALSE(!ret);
1693         }
1694 
1695         /* sealing doesn't apply for shared mapping. */
1696         ret = sys_madvise(ptr, size, MADV_DONTNEED);
1697         FAIL_TEST_IF_FALSE(!ret);
1698 
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 
1708 static void test_seal_discard_ro_anon(bool seal)
1709 {
1710         void *ptr;
1711         unsigned long page_size = getpagesize();
1712         unsigned long size = 4 * page_size;
1713         int ret;
1714 
1715         setup_single_address(size, &ptr);
1716         FAIL_TEST_IF_FALSE(ptr != (void *)-1);
1717 
1718         if (seal) {
1719                 ret = seal_single_address(ptr, size);
1720                 FAIL_TEST_IF_FALSE(!ret);
1721         }
1722 
1723         ret = sys_madvise(ptr, size, MADV_DONTNEED);
1724         if (seal)
1725                 FAIL_TEST_IF_FALSE(ret < 0);
1726         else
1727                 FAIL_TEST_IF_FALSE(!ret);
1728 
1729         ret = sys_munmap(ptr, size);
1730         if (seal)
1731                 FAIL_TEST_IF_FALSE(ret < 0);
1732         else
1733                 FAIL_TEST_IF_FALSE(!ret);
1734 
1735         REPORT_TEST_PASS();
1736 }
1737 
1738 int main(int argc, char **argv)
1739 {
1740         bool test_seal = seal_support();
1741 
1742         ksft_print_header();
1743 
1744         if (!test_seal)
1745                 ksft_exit_skip("sealing not supported, check CONFIG_64BIT\n");
1746 
1747         if (!pkey_supported())
1748                 ksft_print_msg("PKEY not supported\n");
1749 
1750         ksft_set_plan(80);
1751 
1752         test_seal_addseal();
1753         test_seal_unmapped_start();
1754         test_seal_unmapped_middle();
1755         test_seal_unmapped_end();
1756         test_seal_multiple_vmas();
1757         test_seal_split_start();
1758         test_seal_split_end();
1759         test_seal_invalid_input();
1760         test_seal_zero_length();
1761         test_seal_twice();
1762 
1763         test_seal_mprotect(false);
1764         test_seal_mprotect(true);
1765 
1766         test_seal_start_mprotect(false);
1767         test_seal_start_mprotect(true);
1768 
1769         test_seal_end_mprotect(false);
1770         test_seal_end_mprotect(true);
1771 
1772         test_seal_mprotect_unalign_len(false);
1773         test_seal_mprotect_unalign_len(true);
1774 
1775         test_seal_mprotect_unalign_len_variant_2(false);
1776         test_seal_mprotect_unalign_len_variant_2(true);
1777 
1778         test_seal_mprotect_two_vma(false);
1779         test_seal_mprotect_two_vma(true);
1780 
1781         test_seal_mprotect_two_vma_with_split(false);
1782         test_seal_mprotect_two_vma_with_split(true);
1783 
1784         test_seal_mprotect_partial_mprotect(false);
1785         test_seal_mprotect_partial_mprotect(true);
1786 
1787         test_seal_mprotect_two_vma_with_gap(false);
1788         test_seal_mprotect_two_vma_with_gap(true);
1789 
1790         test_seal_mprotect_merge(false);
1791         test_seal_mprotect_merge(true);
1792 
1793         test_seal_mprotect_split(false);
1794         test_seal_mprotect_split(true);
1795 
1796         test_seal_munmap(false);
1797         test_seal_munmap(true);
1798         test_seal_munmap_two_vma(false);
1799         test_seal_munmap_two_vma(true);
1800         test_seal_munmap_vma_with_gap(false);
1801         test_seal_munmap_vma_with_gap(true);
1802 
1803         test_munmap_start_freed(false);
1804         test_munmap_start_freed(true);
1805         test_munmap_middle_freed(false);
1806         test_munmap_middle_freed(true);
1807         test_munmap_end_freed(false);
1808         test_munmap_end_freed(true);
1809 
1810         test_seal_mremap_shrink(false);
1811         test_seal_mremap_shrink(true);
1812         test_seal_mremap_expand(false);
1813         test_seal_mremap_expand(true);
1814         test_seal_mremap_move(false);
1815         test_seal_mremap_move(true);
1816 
1817         test_seal_mremap_shrink_fixed(false);
1818         test_seal_mremap_shrink_fixed(true);
1819         test_seal_mremap_expand_fixed(false);
1820         test_seal_mremap_expand_fixed(true);
1821         test_seal_mremap_move_fixed(false);
1822         test_seal_mremap_move_fixed(true);
1823         test_seal_mremap_move_dontunmap(false);
1824         test_seal_mremap_move_dontunmap(true);
1825         test_seal_mremap_move_fixed_zero(false);
1826         test_seal_mremap_move_fixed_zero(true);
1827         test_seal_mremap_move_dontunmap_anyaddr(false);
1828         test_seal_mremap_move_dontunmap_anyaddr(true);
1829         test_seal_discard_ro_anon(false);
1830         test_seal_discard_ro_anon(true);
1831         test_seal_discard_ro_anon_on_rw(false);
1832         test_seal_discard_ro_anon_on_rw(true);
1833         test_seal_discard_ro_anon_on_shared(false);
1834         test_seal_discard_ro_anon_on_shared(true);
1835         test_seal_discard_ro_anon_on_filebacked(false);
1836         test_seal_discard_ro_anon_on_filebacked(true);
1837         test_seal_mmap_overwrite_prot(false);
1838         test_seal_mmap_overwrite_prot(true);
1839         test_seal_mmap_expand(false);
1840         test_seal_mmap_expand(true);
1841         test_seal_mmap_shrink(false);
1842         test_seal_mmap_shrink(true);
1843 
1844         test_seal_merge_and_split();
1845         test_seal_zero_address();
1846 
1847         test_seal_discard_ro_anon_on_pkey(false);
1848         test_seal_discard_ro_anon_on_pkey(true);
1849 
1850         ksft_finished();
1851 }
1852 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php