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