brintos

brintos / linux-shallow public Read only

0
0
Text · 44.6 KiB · 01675c4 Raw
1990 lines · c
1// SPDX-License-Identifier: GPL-2.02#define _GNU_SOURCE3#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 22static 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 */56static 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 65static 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 74static 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 84static 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 93static 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 102static 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 112static 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 119static 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#endif131	return pkey_reg;132}133 134static 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#endif144}145 146static unsigned long pkey_bit_position(int pkey)147{148	return pkey * PKEY_BITS_PER_PKEY;149}150 151static 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 162static 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 170static 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 178static 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 187static int clean_single_address(void *ptr, int size)188{189	int ret;190	ret = munmap(ptr, size);191	return ret;192}193 194static int seal_single_address(void *ptr, int size)195{196	int ret;197	ret = sys_mseal(ptr, size);198	return ret;199}200 201bool 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 218bool 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#endif226	return false;227}228 229static 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 245static 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 273static 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 305static 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 334static 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 365static 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 390static 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 415static 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 450static 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 474static 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 500static 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 520static 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	else539		FAIL_TEST_IF_FALSE(!ret);540 541	REPORT_TEST_PASS();542}543 544static 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	else564		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 574static 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	else599		FAIL_TEST_IF_FALSE(!ret);600 601	REPORT_TEST_PASS();602}603 604static 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	else624		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 633static 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	else652		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 661static 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	else684		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	else691		FAIL_TEST_IF_FALSE(!ret);692 693	REPORT_TEST_PASS();694}695 696static 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	else725		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	else733		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 743static 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	else764		FAIL_TEST_IF_FALSE(!ret);765 766	REPORT_TEST_PASS();767}768 769static 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	else794		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 805static 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 848static 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	else873		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	else880		FAIL_TEST_IF_FALSE(!ret);881 882	REPORT_TEST_PASS();883}884 885static 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	else910		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 919static 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	else939		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 VMAs947 * seal the whole range948 * munmap will fail on both949 */950static 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	else973		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	else979		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 */991static 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 1022static 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	else1042		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 1052static 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 1092static 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	else1117		FAIL_TEST_IF_FALSE(!ret);1118 1119	REPORT_TEST_PASS();1120}1121 1122static 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 1166static 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 1195static 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 1227static 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 1260static 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	} else1283		FAIL_TEST_IF_FALSE(ret2 == ptr);1284 1285	REPORT_TEST_PASS();1286}1287 1288static 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	} else1314		FAIL_TEST_IF_FALSE(ret2 == ptr);1315 1316	REPORT_TEST_PASS();1317}1318 1319static 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	} else1342		FAIL_TEST_IF_FALSE(ret2 == ptr);1343 1344	REPORT_TEST_PASS();1345}1346 1347static 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	} else1373		FAIL_TEST_IF_FALSE(ret2 == newAddr);1374 1375	REPORT_TEST_PASS();1376}1377 1378static 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	} else1404		FAIL_TEST_IF_FALSE(ret2 == newAddr);1405 1406	REPORT_TEST_PASS();1407}1408 1409static 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	} else1434		FAIL_TEST_IF_FALSE(ret2 == newAddr);1435 1436	REPORT_TEST_PASS();1437}1438 1439static 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 address1457	 */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 1470static 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 1499static 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 1540static 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 1632static 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	else1656		FAIL_TEST_IF_FALSE(!ret);1657 1658	REPORT_TEST_PASS();1659}1660 1661static 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	else1696		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	else1703		FAIL_TEST_IF_FALSE(!ret);1704 1705	REPORT_TEST_PASS();1706}1707 1708static 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	else1739		FAIL_TEST_IF_FALSE(!ret);1740	close(fd);1741 1742	REPORT_TEST_PASS();1743}1744 1745static 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	else1769		FAIL_TEST_IF_FALSE(!ret);1770 1771	REPORT_TEST_PASS();1772}1773 1774static 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	else1793		FAIL_TEST_IF_FALSE(!ret);1794 1795	ret = sys_munmap(ptr, size);1796	if (seal)1797		FAIL_TEST_IF_FALSE(ret < 0);1798	else1799		FAIL_TEST_IF_FALSE(!ret);1800 1801	REPORT_TEST_PASS();1802}1803 1804static 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	else1823		FAIL_TEST_IF_FALSE(!ret);1824 1825	ret = sys_munmap(ptr, size);1826	if (seal)1827		FAIL_TEST_IF_FALSE(ret < 0);1828	else1829		FAIL_TEST_IF_FALSE(!ret);1830 1831	REPORT_TEST_PASS();1832}1833 1834 1835static 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 page1852	 * contents (and thus should work for msealed VMAs). RANDOM also happens to1853	 * 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	else1862		FAIL_TEST_IF_FALSE(!ret);1863 1864	REPORT_TEST_PASS();1865}1866 1867int 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