Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.10.11.
   1// SPDX-License-Identifier: GPL-2.0
   2/*  Copyright(c) 2016-20 Intel Corporation. */
   3
   4#include <cpuid.h>
   5#include <elf.h>
   6#include <errno.h>
   7#include <fcntl.h>
   8#include <stdbool.h>
   9#include <stdio.h>
  10#include <stdint.h>
  11#include <stdlib.h>
  12#include <string.h>
  13#include <unistd.h>
  14#include <sys/ioctl.h>
  15#include <sys/mman.h>
  16#include <sys/stat.h>
  17#include <sys/time.h>
  18#include <sys/types.h>
  19#include <sys/auxv.h>
  20#include "defines.h"
  21#include "../kselftest_harness.h"
  22#include "main.h"
  23
  24static const uint64_t MAGIC = 0x1122334455667788ULL;
  25static const uint64_t MAGIC2 = 0x8877665544332211ULL;
  26vdso_sgx_enter_enclave_t vdso_sgx_enter_enclave;
  27
  28/*
  29 * Security Information (SECINFO) data structure needed by a few SGX
  30 * instructions (eg. ENCLU[EACCEPT] and ENCLU[EMODPE]) holds meta-data
  31 * about an enclave page. &enum sgx_secinfo_page_state specifies the
  32 * secinfo flags used for page state.
  33 */
  34enum sgx_secinfo_page_state {
  35	SGX_SECINFO_PENDING = (1 << 3),
  36	SGX_SECINFO_MODIFIED = (1 << 4),
  37	SGX_SECINFO_PR = (1 << 5),
  38};
  39
  40struct vdso_symtab {
  41	Elf64_Sym *elf_symtab;
  42	const char *elf_symstrtab;
  43	Elf64_Word *elf_hashtab;
  44};
  45
  46static Elf64_Dyn *vdso_get_dyntab(void *addr)
  47{
  48	Elf64_Ehdr *ehdr = addr;
  49	Elf64_Phdr *phdrtab = addr + ehdr->e_phoff;
  50	int i;
  51
  52	for (i = 0; i < ehdr->e_phnum; i++)
  53		if (phdrtab[i].p_type == PT_DYNAMIC)
  54			return addr + phdrtab[i].p_offset;
  55
  56	return NULL;
  57}
  58
  59static void *vdso_get_dyn(void *addr, Elf64_Dyn *dyntab, Elf64_Sxword tag)
  60{
  61	int i;
  62
  63	for (i = 0; dyntab[i].d_tag != DT_NULL; i++)
  64		if (dyntab[i].d_tag == tag)
  65			return addr + dyntab[i].d_un.d_ptr;
  66
  67	return NULL;
  68}
  69
  70static bool vdso_get_symtab(void *addr, struct vdso_symtab *symtab)
  71{
  72	Elf64_Dyn *dyntab = vdso_get_dyntab(addr);
  73
  74	symtab->elf_symtab = vdso_get_dyn(addr, dyntab, DT_SYMTAB);
  75	if (!symtab->elf_symtab)
  76		return false;
  77
  78	symtab->elf_symstrtab = vdso_get_dyn(addr, dyntab, DT_STRTAB);
  79	if (!symtab->elf_symstrtab)
  80		return false;
  81
  82	symtab->elf_hashtab = vdso_get_dyn(addr, dyntab, DT_HASH);
  83	if (!symtab->elf_hashtab)
  84		return false;
  85
  86	return true;
  87}
  88
  89static inline int sgx2_supported(void)
  90{
  91	unsigned int eax, ebx, ecx, edx;
  92
  93	__cpuid_count(SGX_CPUID, 0x0, eax, ebx, ecx, edx);
  94
  95	return eax & 0x2;
  96}
  97
  98static unsigned long elf_sym_hash(const char *name)
  99{
 100	unsigned long h = 0, high;
 101
 102	while (*name) {
 103		h = (h << 4) + *name++;
 104		high = h & 0xf0000000;
 105
 106		if (high)
 107			h ^= high >> 24;
 108
 109		h &= ~high;
 110	}
 111
 112	return h;
 113}
 114
 115static Elf64_Sym *vdso_symtab_get(struct vdso_symtab *symtab, const char *name)
 116{
 117	Elf64_Word bucketnum = symtab->elf_hashtab[0];
 118	Elf64_Word *buckettab = &symtab->elf_hashtab[2];
 119	Elf64_Word *chaintab = &symtab->elf_hashtab[2 + bucketnum];
 120	Elf64_Sym *sym;
 121	Elf64_Word i;
 122
 123	for (i = buckettab[elf_sym_hash(name) % bucketnum]; i != STN_UNDEF;
 124	     i = chaintab[i]) {
 125		sym = &symtab->elf_symtab[i];
 126		if (!strcmp(name, &symtab->elf_symstrtab[sym->st_name]))
 127			return sym;
 128	}
 129
 130	return NULL;
 131}
 132
 133/*
 134 * Return the offset in the enclave where the TCS segment can be found.
 135 * The first RW segment loaded is the TCS.
 136 */
 137static off_t encl_get_tcs_offset(struct encl *encl)
 138{
 139	int i;
 140
 141	for (i = 0; i < encl->nr_segments; i++) {
 142		struct encl_segment *seg = &encl->segment_tbl[i];
 143
 144		if (i == 0 && seg->prot == (PROT_READ | PROT_WRITE))
 145			return seg->offset;
 146	}
 147
 148	return -1;
 149}
 150
 151/*
 152 * Return the offset in the enclave where the data segment can be found.
 153 * The first RW segment loaded is the TCS, skip that to get info on the
 154 * data segment.
 155 */
 156static off_t encl_get_data_offset(struct encl *encl)
 157{
 158	int i;
 159
 160	for (i = 1; i < encl->nr_segments; i++) {
 161		struct encl_segment *seg = &encl->segment_tbl[i];
 162
 163		if (seg->prot == (PROT_READ | PROT_WRITE))
 164			return seg->offset;
 165	}
 166
 167	return -1;
 168}
 169
 170FIXTURE(enclave) {
 171	struct encl encl;
 172	struct sgx_enclave_run run;
 173};
 174
 175static bool setup_test_encl(unsigned long heap_size, struct encl *encl,
 176			    struct __test_metadata *_metadata)
 177{
 178	Elf64_Sym *sgx_enter_enclave_sym = NULL;
 179	struct vdso_symtab symtab;
 180	struct encl_segment *seg;
 181	char maps_line[256];
 182	FILE *maps_file;
 183	unsigned int i;
 184	void *addr;
 185
 186	if (!encl_load("test_encl.elf", encl, heap_size)) {
 187		encl_delete(encl);
 188		TH_LOG("Failed to load the test enclave.");
 189		return false;
 190	}
 191
 192	if (!encl_measure(encl))
 193		goto err;
 194
 195	if (!encl_build(encl))
 196		goto err;
 197
 198	/*
 199	 * An enclave consumer only must do this.
 200	 */
 201	for (i = 0; i < encl->nr_segments; i++) {
 202		struct encl_segment *seg = &encl->segment_tbl[i];
 203
 204		addr = mmap((void *)encl->encl_base + seg->offset, seg->size,
 205			    seg->prot, MAP_SHARED | MAP_FIXED, encl->fd, 0);
 206		EXPECT_NE(addr, MAP_FAILED);
 207		if (addr == MAP_FAILED)
 208			goto err;
 209	}
 210
 211	/* Get vDSO base address */
 212	addr = (void *)getauxval(AT_SYSINFO_EHDR);
 213	if (!addr)
 214		goto err;
 215
 216	if (!vdso_get_symtab(addr, &symtab))
 217		goto err;
 218
 219	sgx_enter_enclave_sym = vdso_symtab_get(&symtab, "__vdso_sgx_enter_enclave");
 220	if (!sgx_enter_enclave_sym)
 221		goto err;
 222
 223	vdso_sgx_enter_enclave = addr + sgx_enter_enclave_sym->st_value;
 224
 225	return true;
 226
 227err:
 228	for (i = 0; i < encl->nr_segments; i++) {
 229		seg = &encl->segment_tbl[i];
 230
 231		TH_LOG("0x%016lx 0x%016lx 0x%02x", seg->offset, seg->size, seg->prot);
 232	}
 233
 234	maps_file = fopen("/proc/self/maps", "r");
 235	if (maps_file != NULL)  {
 236		while (fgets(maps_line, sizeof(maps_line), maps_file) != NULL) {
 237			maps_line[strlen(maps_line) - 1] = '\0';
 238
 239			if (strstr(maps_line, "/dev/sgx_enclave"))
 240				TH_LOG("%s", maps_line);
 241		}
 242
 243		fclose(maps_file);
 244	}
 245
 246	TH_LOG("Failed to initialize the test enclave.");
 247
 248	encl_delete(encl);
 249
 250	return false;
 251}
 252
 253FIXTURE_SETUP(enclave)
 254{
 255}
 256
 257FIXTURE_TEARDOWN(enclave)
 258{
 259	encl_delete(&self->encl);
 260}
 261
 262#define ENCL_CALL(op, run, clobbered) \
 263	({ \
 264		int ret; \
 265		if ((clobbered)) \
 266			ret = vdso_sgx_enter_enclave((unsigned long)(op), 0, 0, \
 267						     EENTER, 0, 0, (run)); \
 268		else \
 269			ret = sgx_enter_enclave((void *)(op), NULL, 0, EENTER, NULL, NULL, \
 270						(run)); \
 271		ret; \
 272	})
 273
 274#define EXPECT_EEXIT(run) \
 275	do { \
 276		EXPECT_EQ((run)->function, EEXIT); \
 277		if ((run)->function != EEXIT) \
 278			TH_LOG("0x%02x 0x%02x 0x%016llx", (run)->exception_vector, \
 279			       (run)->exception_error_code, (run)->exception_addr); \
 280	} while (0)
 281
 282TEST_F(enclave, unclobbered_vdso)
 283{
 284	struct encl_op_get_from_buf get_op;
 285	struct encl_op_put_to_buf put_op;
 286
 287	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
 288
 289	memset(&self->run, 0, sizeof(self->run));
 290	self->run.tcs = self->encl.encl_base;
 291
 292	put_op.header.type = ENCL_OP_PUT_TO_BUFFER;
 293	put_op.value = MAGIC;
 294
 295	EXPECT_EQ(ENCL_CALL(&put_op, &self->run, false), 0);
 296
 297	EXPECT_EEXIT(&self->run);
 298	EXPECT_EQ(self->run.user_data, 0);
 299
 300	get_op.header.type = ENCL_OP_GET_FROM_BUFFER;
 301	get_op.value = 0;
 302
 303	EXPECT_EQ(ENCL_CALL(&get_op, &self->run, false), 0);
 304
 305	EXPECT_EQ(get_op.value, MAGIC);
 306	EXPECT_EEXIT(&self->run);
 307	EXPECT_EQ(self->run.user_data, 0);
 308}
 309
 310/*
 311 * A section metric is concatenated in a way that @low bits 12-31 define the
 312 * bits 12-31 of the metric and @high bits 0-19 define the bits 32-51 of the
 313 * metric.
 314 */
 315static unsigned long sgx_calc_section_metric(unsigned int low,
 316					     unsigned int high)
 317{
 318	return (low & GENMASK_ULL(31, 12)) +
 319	       ((high & GENMASK_ULL(19, 0)) << 32);
 320}
 321
 322/*
 323 * Sum total available physical SGX memory across all EPC sections
 324 *
 325 * Return: total available physical SGX memory available on system
 326 */
 327static unsigned long get_total_epc_mem(void)
 328{
 329	unsigned int eax, ebx, ecx, edx;
 330	unsigned long total_size = 0;
 331	unsigned int type;
 332	int section = 0;
 333
 334	while (true) {
 335		__cpuid_count(SGX_CPUID, section + SGX_CPUID_EPC, eax, ebx, ecx, edx);
 336
 337		type = eax & SGX_CPUID_EPC_MASK;
 338		if (type == SGX_CPUID_EPC_INVALID)
 339			break;
 340
 341		if (type != SGX_CPUID_EPC_SECTION)
 342			break;
 343
 344		total_size += sgx_calc_section_metric(ecx, edx);
 345
 346		section++;
 347	}
 348
 349	return total_size;
 350}
 351
 352TEST_F(enclave, unclobbered_vdso_oversubscribed)
 353{
 354	struct encl_op_get_from_buf get_op;
 355	struct encl_op_put_to_buf put_op;
 356	unsigned long total_mem;
 357
 358	total_mem = get_total_epc_mem();
 359	ASSERT_NE(total_mem, 0);
 360	ASSERT_TRUE(setup_test_encl(total_mem, &self->encl, _metadata));
 361
 362	memset(&self->run, 0, sizeof(self->run));
 363	self->run.tcs = self->encl.encl_base;
 364
 365	put_op.header.type = ENCL_OP_PUT_TO_BUFFER;
 366	put_op.value = MAGIC;
 367
 368	EXPECT_EQ(ENCL_CALL(&put_op, &self->run, false), 0);
 369
 370	EXPECT_EEXIT(&self->run);
 371	EXPECT_EQ(self->run.user_data, 0);
 372
 373	get_op.header.type = ENCL_OP_GET_FROM_BUFFER;
 374	get_op.value = 0;
 375
 376	EXPECT_EQ(ENCL_CALL(&get_op, &self->run, false), 0);
 377
 378	EXPECT_EQ(get_op.value, MAGIC);
 379	EXPECT_EEXIT(&self->run);
 380	EXPECT_EQ(self->run.user_data, 0);
 381}
 382
 383TEST_F_TIMEOUT(enclave, unclobbered_vdso_oversubscribed_remove, 900)
 384{
 385	struct sgx_enclave_remove_pages remove_ioc;
 386	struct sgx_enclave_modify_types modt_ioc;
 387	struct encl_op_get_from_buf get_op;
 388	struct encl_op_eaccept eaccept_op;
 389	struct encl_op_put_to_buf put_op;
 390	struct encl_segment *heap;
 391	unsigned long total_mem;
 392	int ret, errno_save;
 393	unsigned long addr;
 394	unsigned long i;
 395
 396	/*
 397	 * Create enclave with additional heap that is as big as all
 398	 * available physical SGX memory.
 399	 */
 400	total_mem = get_total_epc_mem();
 401	ASSERT_NE(total_mem, 0);
 402	TH_LOG("Creating an enclave with %lu bytes heap may take a while ...",
 403	       total_mem);
 404	ASSERT_TRUE(setup_test_encl(total_mem, &self->encl, _metadata));
 405
 406	/*
 407	 * Hardware (SGX2) and kernel support is needed for this test. Start
 408	 * with check that test has a chance of succeeding.
 409	 */
 410	memset(&modt_ioc, 0, sizeof(modt_ioc));
 411	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
 412
 413	if (ret == -1) {
 414		if (errno == ENOTTY)
 415			SKIP(return,
 416			     "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()");
 417		else if (errno == ENODEV)
 418			SKIP(return, "System does not support SGX2");
 419	}
 420
 421	/*
 422	 * Invalid parameters were provided during sanity check,
 423	 * expect command to fail.
 424	 */
 425	EXPECT_EQ(ret, -1);
 426
 427	/* SGX2 is supported by kernel and hardware, test can proceed. */
 428	memset(&self->run, 0, sizeof(self->run));
 429	self->run.tcs = self->encl.encl_base;
 430
 431	heap = &self->encl.segment_tbl[self->encl.nr_segments - 1];
 432
 433	put_op.header.type = ENCL_OP_PUT_TO_BUFFER;
 434	put_op.value = MAGIC;
 435
 436	EXPECT_EQ(ENCL_CALL(&put_op, &self->run, false), 0);
 437
 438	EXPECT_EEXIT(&self->run);
 439	EXPECT_EQ(self->run.user_data, 0);
 440
 441	get_op.header.type = ENCL_OP_GET_FROM_BUFFER;
 442	get_op.value = 0;
 443
 444	EXPECT_EQ(ENCL_CALL(&get_op, &self->run, false), 0);
 445
 446	EXPECT_EQ(get_op.value, MAGIC);
 447	EXPECT_EEXIT(&self->run);
 448	EXPECT_EQ(self->run.user_data, 0);
 449
 450	/* Trim entire heap. */
 451	memset(&modt_ioc, 0, sizeof(modt_ioc));
 452
 453	modt_ioc.offset = heap->offset;
 454	modt_ioc.length = heap->size;
 455	modt_ioc.page_type = SGX_PAGE_TYPE_TRIM;
 456
 457	TH_LOG("Changing type of %zd bytes to trimmed may take a while ...",
 458	       heap->size);
 459	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
 460	errno_save = ret == -1 ? errno : 0;
 461
 462	EXPECT_EQ(ret, 0);
 463	EXPECT_EQ(errno_save, 0);
 464	EXPECT_EQ(modt_ioc.result, 0);
 465	EXPECT_EQ(modt_ioc.count, heap->size);
 466
 467	/* EACCEPT all removed pages. */
 468	addr = self->encl.encl_base + heap->offset;
 469
 470	eaccept_op.flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED;
 471	eaccept_op.header.type = ENCL_OP_EACCEPT;
 472
 473	TH_LOG("Entering enclave to run EACCEPT for each page of %zd bytes may take a while ...",
 474	       heap->size);
 475	for (i = 0; i < heap->size; i += 4096) {
 476		eaccept_op.epc_addr = addr + i;
 477		eaccept_op.ret = 0;
 478
 479		EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
 480
 481		EXPECT_EQ(self->run.exception_vector, 0);
 482		EXPECT_EQ(self->run.exception_error_code, 0);
 483		EXPECT_EQ(self->run.exception_addr, 0);
 484		ASSERT_EQ(eaccept_op.ret, 0);
 485		ASSERT_EQ(self->run.function, EEXIT);
 486	}
 487
 488	/* Complete page removal. */
 489	memset(&remove_ioc, 0, sizeof(remove_ioc));
 490
 491	remove_ioc.offset = heap->offset;
 492	remove_ioc.length = heap->size;
 493
 494	TH_LOG("Removing %zd bytes from enclave may take a while ...",
 495	       heap->size);
 496	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &remove_ioc);
 497	errno_save = ret == -1 ? errno : 0;
 498
 499	EXPECT_EQ(ret, 0);
 500	EXPECT_EQ(errno_save, 0);
 501	EXPECT_EQ(remove_ioc.count, heap->size);
 502}
 503
 504TEST_F(enclave, clobbered_vdso)
 505{
 506	struct encl_op_get_from_buf get_op;
 507	struct encl_op_put_to_buf put_op;
 508
 509	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
 510
 511	memset(&self->run, 0, sizeof(self->run));
 512	self->run.tcs = self->encl.encl_base;
 513
 514	put_op.header.type = ENCL_OP_PUT_TO_BUFFER;
 515	put_op.value = MAGIC;
 516
 517	EXPECT_EQ(ENCL_CALL(&put_op, &self->run, true), 0);
 518
 519	EXPECT_EEXIT(&self->run);
 520	EXPECT_EQ(self->run.user_data, 0);
 521
 522	get_op.header.type = ENCL_OP_GET_FROM_BUFFER;
 523	get_op.value = 0;
 524
 525	EXPECT_EQ(ENCL_CALL(&get_op, &self->run, true), 0);
 526
 527	EXPECT_EQ(get_op.value, MAGIC);
 528	EXPECT_EEXIT(&self->run);
 529	EXPECT_EQ(self->run.user_data, 0);
 530}
 531
 532static int test_handler(long rdi, long rsi, long rdx, long ursp, long r8, long r9,
 533			struct sgx_enclave_run *run)
 534{
 535	run->user_data = 0;
 536
 537	return 0;
 538}
 539
 540TEST_F(enclave, clobbered_vdso_and_user_function)
 541{
 542	struct encl_op_get_from_buf get_op;
 543	struct encl_op_put_to_buf put_op;
 544
 545	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
 546
 547	memset(&self->run, 0, sizeof(self->run));
 548	self->run.tcs = self->encl.encl_base;
 549
 550	self->run.user_handler = (__u64)test_handler;
 551	self->run.user_data = 0xdeadbeef;
 552
 553	put_op.header.type = ENCL_OP_PUT_TO_BUFFER;
 554	put_op.value = MAGIC;
 555
 556	EXPECT_EQ(ENCL_CALL(&put_op, &self->run, true), 0);
 557
 558	EXPECT_EEXIT(&self->run);
 559	EXPECT_EQ(self->run.user_data, 0);
 560
 561	get_op.header.type = ENCL_OP_GET_FROM_BUFFER;
 562	get_op.value = 0;
 563
 564	EXPECT_EQ(ENCL_CALL(&get_op, &self->run, true), 0);
 565
 566	EXPECT_EQ(get_op.value, MAGIC);
 567	EXPECT_EEXIT(&self->run);
 568	EXPECT_EQ(self->run.user_data, 0);
 569}
 570
 571/*
 572 * Sanity check that it is possible to enter either of the two hardcoded TCS
 573 */
 574TEST_F(enclave, tcs_entry)
 575{
 576	struct encl_op_header op;
 577
 578	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
 579
 580	memset(&self->run, 0, sizeof(self->run));
 581	self->run.tcs = self->encl.encl_base;
 582
 583	op.type = ENCL_OP_NOP;
 584
 585	EXPECT_EQ(ENCL_CALL(&op, &self->run, true), 0);
 586
 587	EXPECT_EEXIT(&self->run);
 588	EXPECT_EQ(self->run.exception_vector, 0);
 589	EXPECT_EQ(self->run.exception_error_code, 0);
 590	EXPECT_EQ(self->run.exception_addr, 0);
 591
 592	/* Move to the next TCS. */
 593	self->run.tcs = self->encl.encl_base + PAGE_SIZE;
 594
 595	EXPECT_EQ(ENCL_CALL(&op, &self->run, true), 0);
 596
 597	EXPECT_EEXIT(&self->run);
 598	EXPECT_EQ(self->run.exception_vector, 0);
 599	EXPECT_EQ(self->run.exception_error_code, 0);
 600	EXPECT_EQ(self->run.exception_addr, 0);
 601}
 602
 603/*
 604 * Second page of .data segment is used to test changing PTE permissions.
 605 * This spans the local encl_buffer within the test enclave.
 606 *
 607 * 1) Start with a sanity check: a value is written to the target page within
 608 *    the enclave and read back to ensure target page can be written to.
 609 * 2) Change PTE permissions (RW -> RO) of target page within enclave.
 610 * 3) Repeat (1) - this time expecting a regular #PF communicated via the
 611 *    vDSO.
 612 * 4) Change PTE permissions of target page within enclave back to be RW.
 613 * 5) Repeat (1) by resuming enclave, now expected to be possible to write to
 614 *    and read from target page within enclave.
 615 */
 616TEST_F(enclave, pte_permissions)
 617{
 618	struct encl_op_get_from_addr get_addr_op;
 619	struct encl_op_put_to_addr put_addr_op;
 620	unsigned long data_start;
 621	int ret;
 622
 623	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
 624
 625	memset(&self->run, 0, sizeof(self->run));
 626	self->run.tcs = self->encl.encl_base;
 627
 628	data_start = self->encl.encl_base +
 629		     encl_get_data_offset(&self->encl) +
 630		     PAGE_SIZE;
 631
 632	/*
 633	 * Sanity check to ensure it is possible to write to page that will
 634	 * have its permissions manipulated.
 635	 */
 636
 637	/* Write MAGIC to page */
 638	put_addr_op.value = MAGIC;
 639	put_addr_op.addr = data_start;
 640	put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS;
 641
 642	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
 643
 644	EXPECT_EEXIT(&self->run);
 645	EXPECT_EQ(self->run.exception_vector, 0);
 646	EXPECT_EQ(self->run.exception_error_code, 0);
 647	EXPECT_EQ(self->run.exception_addr, 0);
 648
 649	/*
 650	 * Read memory that was just written to, confirming that it is the
 651	 * value previously written (MAGIC).
 652	 */
 653	get_addr_op.value = 0;
 654	get_addr_op.addr = data_start;
 655	get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS;
 656
 657	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
 658
 659	EXPECT_EQ(get_addr_op.value, MAGIC);
 660	EXPECT_EEXIT(&self->run);
 661	EXPECT_EQ(self->run.exception_vector, 0);
 662	EXPECT_EQ(self->run.exception_error_code, 0);
 663	EXPECT_EQ(self->run.exception_addr, 0);
 664
 665	/* Change PTE permissions of target page within the enclave */
 666	ret = mprotect((void *)data_start, PAGE_SIZE, PROT_READ);
 667	if (ret)
 668		perror("mprotect");
 669
 670	/*
 671	 * PTE permissions of target page changed to read-only, EPCM
 672	 * permissions unchanged (EPCM permissions are RW), attempt to
 673	 * write to the page, expecting a regular #PF.
 674	 */
 675
 676	put_addr_op.value = MAGIC2;
 677
 678	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
 679
 680	EXPECT_EQ(self->run.exception_vector, 14);
 681	EXPECT_EQ(self->run.exception_error_code, 0x7);
 682	EXPECT_EQ(self->run.exception_addr, data_start);
 683
 684	self->run.exception_vector = 0;
 685	self->run.exception_error_code = 0;
 686	self->run.exception_addr = 0;
 687
 688	/*
 689	 * Change PTE permissions back to enable enclave to write to the
 690	 * target page and resume enclave - do not expect any exceptions this
 691	 * time.
 692	 */
 693	ret = mprotect((void *)data_start, PAGE_SIZE, PROT_READ | PROT_WRITE);
 694	if (ret)
 695		perror("mprotect");
 696
 697	EXPECT_EQ(vdso_sgx_enter_enclave((unsigned long)&put_addr_op, 0,
 698					 0, ERESUME, 0, 0, &self->run),
 699		 0);
 700
 701	EXPECT_EEXIT(&self->run);
 702	EXPECT_EQ(self->run.exception_vector, 0);
 703	EXPECT_EQ(self->run.exception_error_code, 0);
 704	EXPECT_EQ(self->run.exception_addr, 0);
 705
 706	get_addr_op.value = 0;
 707
 708	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
 709
 710	EXPECT_EQ(get_addr_op.value, MAGIC2);
 711	EXPECT_EEXIT(&self->run);
 712	EXPECT_EQ(self->run.exception_vector, 0);
 713	EXPECT_EQ(self->run.exception_error_code, 0);
 714	EXPECT_EQ(self->run.exception_addr, 0);
 715}
 716
 717/*
 718 * Modifying permissions of TCS page should not be possible.
 719 */
 720TEST_F(enclave, tcs_permissions)
 721{
 722	struct sgx_enclave_restrict_permissions ioc;
 723	int ret, errno_save;
 724
 725	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
 726
 727	memset(&self->run, 0, sizeof(self->run));
 728	self->run.tcs = self->encl.encl_base;
 729
 730	memset(&ioc, 0, sizeof(ioc));
 731
 732	/*
 733	 * Ensure kernel supports needed ioctl() and system supports needed
 734	 * commands.
 735	 */
 736
 737	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS, &ioc);
 738	errno_save = ret == -1 ? errno : 0;
 739
 740	/*
 741	 * Invalid parameters were provided during sanity check,
 742	 * expect command to fail.
 743	 */
 744	ASSERT_EQ(ret, -1);
 745
 746	/* ret == -1 */
 747	if (errno_save == ENOTTY)
 748		SKIP(return,
 749		     "Kernel does not support SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS ioctl()");
 750	else if (errno_save == ENODEV)
 751		SKIP(return, "System does not support SGX2");
 752
 753	/*
 754	 * Attempt to make TCS page read-only. This is not allowed and
 755	 * should be prevented by the kernel.
 756	 */
 757	ioc.offset = encl_get_tcs_offset(&self->encl);
 758	ioc.length = PAGE_SIZE;
 759	ioc.permissions = SGX_SECINFO_R;
 760
 761	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS, &ioc);
 762	errno_save = ret == -1 ? errno : 0;
 763
 764	EXPECT_EQ(ret, -1);
 765	EXPECT_EQ(errno_save, EINVAL);
 766	EXPECT_EQ(ioc.result, 0);
 767	EXPECT_EQ(ioc.count, 0);
 768}
 769
 770/*
 771 * Enclave page permission test.
 772 *
 773 * Modify and restore enclave page's EPCM (enclave) permissions from
 774 * outside enclave (ENCLS[EMODPR] via kernel) as well as from within
 775 * enclave (via ENCLU[EMODPE]). Check for page fault if
 776 * VMA allows access but EPCM permissions do not.
 777 */
 778TEST_F(enclave, epcm_permissions)
 779{
 780	struct sgx_enclave_restrict_permissions restrict_ioc;
 781	struct encl_op_get_from_addr get_addr_op;
 782	struct encl_op_put_to_addr put_addr_op;
 783	struct encl_op_eaccept eaccept_op;
 784	struct encl_op_emodpe emodpe_op;
 785	unsigned long data_start;
 786	int ret, errno_save;
 787
 788	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
 789
 790	memset(&self->run, 0, sizeof(self->run));
 791	self->run.tcs = self->encl.encl_base;
 792
 793	/*
 794	 * Ensure kernel supports needed ioctl() and system supports needed
 795	 * commands.
 796	 */
 797	memset(&restrict_ioc, 0, sizeof(restrict_ioc));
 798
 799	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS,
 800		    &restrict_ioc);
 801	errno_save = ret == -1 ? errno : 0;
 802
 803	/*
 804	 * Invalid parameters were provided during sanity check,
 805	 * expect command to fail.
 806	 */
 807	ASSERT_EQ(ret, -1);
 808
 809	/* ret == -1 */
 810	if (errno_save == ENOTTY)
 811		SKIP(return,
 812		     "Kernel does not support SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS ioctl()");
 813	else if (errno_save == ENODEV)
 814		SKIP(return, "System does not support SGX2");
 815
 816	/*
 817	 * Page that will have its permissions changed is the second data
 818	 * page in the .data segment. This forms part of the local encl_buffer
 819	 * within the enclave.
 820	 *
 821	 * At start of test @data_start should have EPCM as well as PTE and
 822	 * VMA permissions of RW.
 823	 */
 824
 825	data_start = self->encl.encl_base +
 826		     encl_get_data_offset(&self->encl) + PAGE_SIZE;
 827
 828	/*
 829	 * Sanity check that page at @data_start is writable before making
 830	 * any changes to page permissions.
 831	 *
 832	 * Start by writing MAGIC to test page.
 833	 */
 834	put_addr_op.value = MAGIC;
 835	put_addr_op.addr = data_start;
 836	put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS;
 837
 838	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
 839
 840	EXPECT_EEXIT(&self->run);
 841	EXPECT_EQ(self->run.exception_vector, 0);
 842	EXPECT_EQ(self->run.exception_error_code, 0);
 843	EXPECT_EQ(self->run.exception_addr, 0);
 844
 845	/*
 846	 * Read memory that was just written to, confirming that
 847	 * page is writable.
 848	 */
 849	get_addr_op.value = 0;
 850	get_addr_op.addr = data_start;
 851	get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS;
 852
 853	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
 854
 855	EXPECT_EQ(get_addr_op.value, MAGIC);
 856	EXPECT_EEXIT(&self->run);
 857	EXPECT_EQ(self->run.exception_vector, 0);
 858	EXPECT_EQ(self->run.exception_error_code, 0);
 859	EXPECT_EQ(self->run.exception_addr, 0);
 860
 861	/*
 862	 * Change EPCM permissions to read-only. Kernel still considers
 863	 * the page writable.
 864	 */
 865	memset(&restrict_ioc, 0, sizeof(restrict_ioc));
 866
 867	restrict_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE;
 868	restrict_ioc.length = PAGE_SIZE;
 869	restrict_ioc.permissions = SGX_SECINFO_R;
 870
 871	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS,
 872		    &restrict_ioc);
 873	errno_save = ret == -1 ? errno : 0;
 874
 875	EXPECT_EQ(ret, 0);
 876	EXPECT_EQ(errno_save, 0);
 877	EXPECT_EQ(restrict_ioc.result, 0);
 878	EXPECT_EQ(restrict_ioc.count, 4096);
 879
 880	/*
 881	 * EPCM permissions changed from kernel, need to EACCEPT from enclave.
 882	 */
 883	eaccept_op.epc_addr = data_start;
 884	eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_REG | SGX_SECINFO_PR;
 885	eaccept_op.ret = 0;
 886	eaccept_op.header.type = ENCL_OP_EACCEPT;
 887
 888	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
 889
 890	EXPECT_EEXIT(&self->run);
 891	EXPECT_EQ(self->run.exception_vector, 0);
 892	EXPECT_EQ(self->run.exception_error_code, 0);
 893	EXPECT_EQ(self->run.exception_addr, 0);
 894	EXPECT_EQ(eaccept_op.ret, 0);
 895
 896	/*
 897	 * EPCM permissions of page is now read-only, expect #PF
 898	 * on EPCM when attempting to write to page from within enclave.
 899	 */
 900	put_addr_op.value = MAGIC2;
 901
 902	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
 903
 904	EXPECT_EQ(self->run.function, ERESUME);
 905	EXPECT_EQ(self->run.exception_vector, 14);
 906	EXPECT_EQ(self->run.exception_error_code, 0x8007);
 907	EXPECT_EQ(self->run.exception_addr, data_start);
 908
 909	self->run.exception_vector = 0;
 910	self->run.exception_error_code = 0;
 911	self->run.exception_addr = 0;
 912
 913	/*
 914	 * Received AEX but cannot return to enclave at same entrypoint,
 915	 * need different TCS from where EPCM permission can be made writable
 916	 * again.
 917	 */
 918	self->run.tcs = self->encl.encl_base + PAGE_SIZE;
 919
 920	/*
 921	 * Enter enclave at new TCS to change EPCM permissions to be
 922	 * writable again and thus fix the page fault that triggered the
 923	 * AEX.
 924	 */
 925
 926	emodpe_op.epc_addr = data_start;
 927	emodpe_op.flags = SGX_SECINFO_R | SGX_SECINFO_W;
 928	emodpe_op.header.type = ENCL_OP_EMODPE;
 929
 930	EXPECT_EQ(ENCL_CALL(&emodpe_op, &self->run, true), 0);
 931
 932	EXPECT_EEXIT(&self->run);
 933	EXPECT_EQ(self->run.exception_vector, 0);
 934	EXPECT_EQ(self->run.exception_error_code, 0);
 935	EXPECT_EQ(self->run.exception_addr, 0);
 936
 937	/*
 938	 * Attempt to return to main TCS to resume execution at faulting
 939	 * instruction, PTE should continue to allow writing to the page.
 940	 */
 941	self->run.tcs = self->encl.encl_base;
 942
 943	/*
 944	 * Wrong page permissions that caused original fault has
 945	 * now been fixed via EPCM permissions.
 946	 * Resume execution in main TCS to re-attempt the memory access.
 947	 */
 948	self->run.tcs = self->encl.encl_base;
 949
 950	EXPECT_EQ(vdso_sgx_enter_enclave((unsigned long)&put_addr_op, 0, 0,
 951					 ERESUME, 0, 0,
 952					 &self->run),
 953		  0);
 954
 955	EXPECT_EEXIT(&self->run);
 956	EXPECT_EQ(self->run.exception_vector, 0);
 957	EXPECT_EQ(self->run.exception_error_code, 0);
 958	EXPECT_EQ(self->run.exception_addr, 0);
 959
 960	get_addr_op.value = 0;
 961
 962	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
 963
 964	EXPECT_EQ(get_addr_op.value, MAGIC2);
 965	EXPECT_EEXIT(&self->run);
 966	EXPECT_EQ(self->run.user_data, 0);
 967	EXPECT_EQ(self->run.exception_vector, 0);
 968	EXPECT_EQ(self->run.exception_error_code, 0);
 969	EXPECT_EQ(self->run.exception_addr, 0);
 970}
 971
 972/*
 973 * Test the addition of pages to an initialized enclave via writing to
 974 * a page belonging to the enclave's address space but was not added
 975 * during enclave creation.
 976 */
 977TEST_F(enclave, augment)
 978{
 979	struct encl_op_get_from_addr get_addr_op;
 980	struct encl_op_put_to_addr put_addr_op;
 981	struct encl_op_eaccept eaccept_op;
 982	size_t total_size = 0;
 983	void *addr;
 984	int i;
 985
 986	if (!sgx2_supported())
 987		SKIP(return, "SGX2 not supported");
 988
 989	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
 990
 991	memset(&self->run, 0, sizeof(self->run));
 992	self->run.tcs = self->encl.encl_base;
 993
 994	for (i = 0; i < self->encl.nr_segments; i++) {
 995		struct encl_segment *seg = &self->encl.segment_tbl[i];
 996
 997		total_size += seg->size;
 998	}
 999
1000	/*
1001	 * Actual enclave size is expected to be larger than the loaded
1002	 * test enclave since enclave size must be a power of 2 in bytes
1003	 * and test_encl does not consume it all.
1004	 */
1005	EXPECT_LT(total_size + PAGE_SIZE, self->encl.encl_size);
1006
1007	/*
1008	 * Create memory mapping for the page that will be added. New
1009	 * memory mapping is for one page right after all existing
1010	 * mappings.
1011	 * Kernel will allow new mapping using any permissions if it
1012	 * falls into the enclave's address range but not backed
1013	 * by existing enclave pages.
1014	 */
1015	addr = mmap((void *)self->encl.encl_base + total_size, PAGE_SIZE,
1016		    PROT_READ | PROT_WRITE | PROT_EXEC,
1017		    MAP_SHARED | MAP_FIXED, self->encl.fd, 0);
1018	EXPECT_NE(addr, MAP_FAILED);
1019
1020	self->run.exception_vector = 0;
1021	self->run.exception_error_code = 0;
1022	self->run.exception_addr = 0;
1023
1024	/*
1025	 * Attempt to write to the new page from within enclave.
1026	 * Expected to fail since page is not (yet) part of the enclave.
1027	 * The first #PF will trigger the addition of the page to the
1028	 * enclave, but since the new page needs an EACCEPT from within the
1029	 * enclave before it can be used it would not be possible
1030	 * to successfully return to the failing instruction. This is the
1031	 * cause of the second #PF captured here having the SGX bit set,
1032	 * it is from hardware preventing the page from being used.
1033	 */
1034	put_addr_op.value = MAGIC;
1035	put_addr_op.addr = (unsigned long)addr;
1036	put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS;
1037
1038	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
1039
1040	EXPECT_EQ(self->run.function, ERESUME);
1041	EXPECT_EQ(self->run.exception_vector, 14);
1042	EXPECT_EQ(self->run.exception_addr, (unsigned long)addr);
1043
1044	if (self->run.exception_error_code == 0x6) {
1045		munmap(addr, PAGE_SIZE);
1046		SKIP(return, "Kernel does not support adding pages to initialized enclave");
1047	}
1048
1049	EXPECT_EQ(self->run.exception_error_code, 0x8007);
1050
1051	self->run.exception_vector = 0;
1052	self->run.exception_error_code = 0;
1053	self->run.exception_addr = 0;
1054
1055	/* Handle AEX by running EACCEPT from new entry point. */
1056	self->run.tcs = self->encl.encl_base + PAGE_SIZE;
1057
1058	eaccept_op.epc_addr = self->encl.encl_base + total_size;
1059	eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_REG | SGX_SECINFO_PENDING;
1060	eaccept_op.ret = 0;
1061	eaccept_op.header.type = ENCL_OP_EACCEPT;
1062
1063	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1064
1065	EXPECT_EEXIT(&self->run);
1066	EXPECT_EQ(self->run.exception_vector, 0);
1067	EXPECT_EQ(self->run.exception_error_code, 0);
1068	EXPECT_EQ(self->run.exception_addr, 0);
1069	EXPECT_EQ(eaccept_op.ret, 0);
1070
1071	/* Can now return to main TCS to resume execution. */
1072	self->run.tcs = self->encl.encl_base;
1073
1074	EXPECT_EQ(vdso_sgx_enter_enclave((unsigned long)&put_addr_op, 0, 0,
1075					 ERESUME, 0, 0,
1076					 &self->run),
1077		  0);
1078
1079	EXPECT_EEXIT(&self->run);
1080	EXPECT_EQ(self->run.exception_vector, 0);
1081	EXPECT_EQ(self->run.exception_error_code, 0);
1082	EXPECT_EQ(self->run.exception_addr, 0);
1083
1084	/*
1085	 * Read memory from newly added page that was just written to,
1086	 * confirming that data previously written (MAGIC) is present.
1087	 */
1088	get_addr_op.value = 0;
1089	get_addr_op.addr = (unsigned long)addr;
1090	get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS;
1091
1092	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
1093
1094	EXPECT_EQ(get_addr_op.value, MAGIC);
1095	EXPECT_EEXIT(&self->run);
1096	EXPECT_EQ(self->run.exception_vector, 0);
1097	EXPECT_EQ(self->run.exception_error_code, 0);
1098	EXPECT_EQ(self->run.exception_addr, 0);
1099
1100	munmap(addr, PAGE_SIZE);
1101}
1102
1103/*
1104 * Test for the addition of pages to an initialized enclave via a
1105 * pre-emptive run of EACCEPT on page to be added.
1106 */
1107TEST_F(enclave, augment_via_eaccept)
1108{
1109	struct encl_op_get_from_addr get_addr_op;
1110	struct encl_op_put_to_addr put_addr_op;
1111	struct encl_op_eaccept eaccept_op;
1112	size_t total_size = 0;
1113	void *addr;
1114	int i;
1115
1116	if (!sgx2_supported())
1117		SKIP(return, "SGX2 not supported");
1118
1119	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
1120
1121	memset(&self->run, 0, sizeof(self->run));
1122	self->run.tcs = self->encl.encl_base;
1123
1124	for (i = 0; i < self->encl.nr_segments; i++) {
1125		struct encl_segment *seg = &self->encl.segment_tbl[i];
1126
1127		total_size += seg->size;
1128	}
1129
1130	/*
1131	 * Actual enclave size is expected to be larger than the loaded
1132	 * test enclave since enclave size must be a power of 2 in bytes while
1133	 * test_encl does not consume it all.
1134	 */
1135	EXPECT_LT(total_size + PAGE_SIZE, self->encl.encl_size);
1136
1137	/*
1138	 * mmap() a page at end of existing enclave to be used for dynamic
1139	 * EPC page.
1140	 *
1141	 * Kernel will allow new mapping using any permissions if it
1142	 * falls into the enclave's address range but not backed
1143	 * by existing enclave pages.
1144	 */
1145
1146	addr = mmap((void *)self->encl.encl_base + total_size, PAGE_SIZE,
1147		    PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED,
1148		    self->encl.fd, 0);
1149	EXPECT_NE(addr, MAP_FAILED);
1150
1151	self->run.exception_vector = 0;
1152	self->run.exception_error_code = 0;
1153	self->run.exception_addr = 0;
1154
1155	/*
1156	 * Run EACCEPT on new page to trigger the #PF->EAUG->EACCEPT(again
1157	 * without a #PF). All should be transparent to userspace.
1158	 */
1159	eaccept_op.epc_addr = self->encl.encl_base + total_size;
1160	eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_REG | SGX_SECINFO_PENDING;
1161	eaccept_op.ret = 0;
1162	eaccept_op.header.type = ENCL_OP_EACCEPT;
1163
1164	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1165
1166	if (self->run.exception_vector == 14 &&
1167	    self->run.exception_error_code == 4 &&
1168	    self->run.exception_addr == self->encl.encl_base + total_size) {
1169		munmap(addr, PAGE_SIZE);
1170		SKIP(return, "Kernel does not support adding pages to initialized enclave");
1171	}
1172
1173	EXPECT_EEXIT(&self->run);
1174	EXPECT_EQ(self->run.exception_vector, 0);
1175	EXPECT_EQ(self->run.exception_error_code, 0);
1176	EXPECT_EQ(self->run.exception_addr, 0);
1177	EXPECT_EQ(eaccept_op.ret, 0);
1178
1179	/*
1180	 * New page should be accessible from within enclave - attempt to
1181	 * write to it.
1182	 */
1183	put_addr_op.value = MAGIC;
1184	put_addr_op.addr = (unsigned long)addr;
1185	put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS;
1186
1187	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
1188
1189	EXPECT_EEXIT(&self->run);
1190	EXPECT_EQ(self->run.exception_vector, 0);
1191	EXPECT_EQ(self->run.exception_error_code, 0);
1192	EXPECT_EQ(self->run.exception_addr, 0);
1193
1194	/*
1195	 * Read memory from newly added page that was just written to,
1196	 * confirming that data previously written (MAGIC) is present.
1197	 */
1198	get_addr_op.value = 0;
1199	get_addr_op.addr = (unsigned long)addr;
1200	get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS;
1201
1202	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
1203
1204	EXPECT_EQ(get_addr_op.value, MAGIC);
1205	EXPECT_EEXIT(&self->run);
1206	EXPECT_EQ(self->run.exception_vector, 0);
1207	EXPECT_EQ(self->run.exception_error_code, 0);
1208	EXPECT_EQ(self->run.exception_addr, 0);
1209
1210	munmap(addr, PAGE_SIZE);
1211}
1212
1213/*
1214 * SGX2 page type modification test in two phases:
1215 * Phase 1:
1216 * Create a new TCS, consisting out of three new pages (stack page with regular
1217 * page type, SSA page with regular page type, and TCS page with TCS page
1218 * type) in an initialized enclave and run a simple workload within it.
1219 * Phase 2:
1220 * Remove the three pages added in phase 1, add a new regular page at the
1221 * same address that previously hosted the TCS page and verify that it can
1222 * be modified.
1223 */
1224TEST_F(enclave, tcs_create)
1225{
1226	struct encl_op_init_tcs_page init_tcs_page_op;
1227	struct sgx_enclave_remove_pages remove_ioc;
1228	struct encl_op_get_from_addr get_addr_op;
1229	struct sgx_enclave_modify_types modt_ioc;
1230	struct encl_op_put_to_addr put_addr_op;
1231	struct encl_op_get_from_buf get_buf_op;
1232	struct encl_op_put_to_buf put_buf_op;
1233	void *addr, *tcs, *stack_end, *ssa;
1234	struct encl_op_eaccept eaccept_op;
1235	size_t total_size = 0;
1236	uint64_t val_64;
1237	int errno_save;
1238	int ret, i;
1239
1240	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl,
1241				    _metadata));
1242
1243	memset(&self->run, 0, sizeof(self->run));
1244	self->run.tcs = self->encl.encl_base;
1245
1246	/*
1247	 * Hardware (SGX2) and kernel support is needed for this test. Start
1248	 * with check that test has a chance of succeeding.
1249	 */
1250	memset(&modt_ioc, 0, sizeof(modt_ioc));
1251	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
1252
1253	if (ret == -1) {
1254		if (errno == ENOTTY)
1255			SKIP(return,
1256			     "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()");
1257		else if (errno == ENODEV)
1258			SKIP(return, "System does not support SGX2");
1259	}
1260
1261	/*
1262	 * Invalid parameters were provided during sanity check,
1263	 * expect command to fail.
1264	 */
1265	EXPECT_EQ(ret, -1);
1266
1267	/*
1268	 * Add three regular pages via EAUG: one will be the TCS stack, one
1269	 * will be the TCS SSA, and one will be the new TCS. The stack and
1270	 * SSA will remain as regular pages, the TCS page will need its
1271	 * type changed after populated with needed data.
1272	 */
1273	for (i = 0; i < self->encl.nr_segments; i++) {
1274		struct encl_segment *seg = &self->encl.segment_tbl[i];
1275
1276		total_size += seg->size;
1277	}
1278
1279	/*
1280	 * Actual enclave size is expected to be larger than the loaded
1281	 * test enclave since enclave size must be a power of 2 in bytes while
1282	 * test_encl does not consume it all.
1283	 */
1284	EXPECT_LT(total_size + 3 * PAGE_SIZE, self->encl.encl_size);
1285
1286	/*
1287	 * mmap() three pages at end of existing enclave to be used for the
1288	 * three new pages.
1289	 */
1290	addr = mmap((void *)self->encl.encl_base + total_size, 3 * PAGE_SIZE,
1291		    PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED,
1292		    self->encl.fd, 0);
1293	EXPECT_NE(addr, MAP_FAILED);
1294
1295	self->run.exception_vector = 0;
1296	self->run.exception_error_code = 0;
1297	self->run.exception_addr = 0;
1298
1299	stack_end = (void *)self->encl.encl_base + total_size;
1300	tcs = (void *)self->encl.encl_base + total_size + PAGE_SIZE;
1301	ssa = (void *)self->encl.encl_base + total_size + 2 * PAGE_SIZE;
1302
1303	/*
1304	 * Run EACCEPT on each new page to trigger the
1305	 * EACCEPT->(#PF)->EAUG->EACCEPT(again without a #PF) flow.
1306	 */
1307
1308	eaccept_op.epc_addr = (unsigned long)stack_end;
1309	eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_REG | SGX_SECINFO_PENDING;
1310	eaccept_op.ret = 0;
1311	eaccept_op.header.type = ENCL_OP_EACCEPT;
1312
1313	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1314
1315	if (self->run.exception_vector == 14 &&
1316	    self->run.exception_error_code == 4 &&
1317	    self->run.exception_addr == (unsigned long)stack_end) {
1318		munmap(addr, 3 * PAGE_SIZE);
1319		SKIP(return, "Kernel does not support adding pages to initialized enclave");
1320	}
1321
1322	EXPECT_EEXIT(&self->run);
1323	EXPECT_EQ(self->run.exception_vector, 0);
1324	EXPECT_EQ(self->run.exception_error_code, 0);
1325	EXPECT_EQ(self->run.exception_addr, 0);
1326	EXPECT_EQ(eaccept_op.ret, 0);
1327
1328	eaccept_op.epc_addr = (unsigned long)ssa;
1329
1330	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1331
1332	EXPECT_EEXIT(&self->run);
1333	EXPECT_EQ(self->run.exception_vector, 0);
1334	EXPECT_EQ(self->run.exception_error_code, 0);
1335	EXPECT_EQ(self->run.exception_addr, 0);
1336	EXPECT_EQ(eaccept_op.ret, 0);
1337
1338	eaccept_op.epc_addr = (unsigned long)tcs;
1339
1340	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1341
1342	EXPECT_EEXIT(&self->run);
1343	EXPECT_EQ(self->run.exception_vector, 0);
1344	EXPECT_EQ(self->run.exception_error_code, 0);
1345	EXPECT_EQ(self->run.exception_addr, 0);
1346	EXPECT_EQ(eaccept_op.ret, 0);
1347
1348	/*
1349	 * Three new pages added to enclave. Now populate the TCS page with
1350	 * needed data. This should be done from within enclave. Provide
1351	 * the function that will do the actual data population with needed
1352	 * data.
1353	 */
1354
1355	/*
1356	 * New TCS will use the "encl_dyn_entry" entrypoint that expects
1357	 * stack to begin in page before TCS page.
1358	 */
1359	val_64 = encl_get_entry(&self->encl, "encl_dyn_entry");
1360	EXPECT_NE(val_64, 0);
1361
1362	init_tcs_page_op.tcs_page = (unsigned long)tcs;
1363	init_tcs_page_op.ssa = (unsigned long)total_size + 2 * PAGE_SIZE;
1364	init_tcs_page_op.entry = val_64;
1365	init_tcs_page_op.header.type = ENCL_OP_INIT_TCS_PAGE;
1366
1367	EXPECT_EQ(ENCL_CALL(&init_tcs_page_op, &self->run, true), 0);
1368
1369	EXPECT_EEXIT(&self->run);
1370	EXPECT_EQ(self->run.exception_vector, 0);
1371	EXPECT_EQ(self->run.exception_error_code, 0);
1372	EXPECT_EQ(self->run.exception_addr, 0);
1373
1374	/* Change TCS page type to TCS. */
1375	memset(&modt_ioc, 0, sizeof(modt_ioc));
1376
1377	modt_ioc.offset = total_size + PAGE_SIZE;
1378	modt_ioc.length = PAGE_SIZE;
1379	modt_ioc.page_type = SGX_PAGE_TYPE_TCS;
1380
1381	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
1382	errno_save = ret == -1 ? errno : 0;
1383
1384	EXPECT_EQ(ret, 0);
1385	EXPECT_EQ(errno_save, 0);
1386	EXPECT_EQ(modt_ioc.result, 0);
1387	EXPECT_EQ(modt_ioc.count, 4096);
1388
1389	/* EACCEPT new TCS page from enclave. */
1390	eaccept_op.epc_addr = (unsigned long)tcs;
1391	eaccept_op.flags = SGX_SECINFO_TCS | SGX_SECINFO_MODIFIED;
1392	eaccept_op.ret = 0;
1393	eaccept_op.header.type = ENCL_OP_EACCEPT;
1394
1395	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1396
1397	EXPECT_EEXIT(&self->run);
1398	EXPECT_EQ(self->run.exception_vector, 0);
1399	EXPECT_EQ(self->run.exception_error_code, 0);
1400	EXPECT_EQ(self->run.exception_addr, 0);
1401	EXPECT_EQ(eaccept_op.ret, 0);
1402
1403	/* Run workload from new TCS. */
1404	self->run.tcs = (unsigned long)tcs;
1405
1406	/*
1407	 * Simple workload to write to data buffer and read value back.
1408	 */
1409	put_buf_op.header.type = ENCL_OP_PUT_TO_BUFFER;
1410	put_buf_op.value = MAGIC;
1411
1412	EXPECT_EQ(ENCL_CALL(&put_buf_op, &self->run, true), 0);
1413
1414	EXPECT_EEXIT(&self->run);
1415	EXPECT_EQ(self->run.exception_vector, 0);
1416	EXPECT_EQ(self->run.exception_error_code, 0);
1417	EXPECT_EQ(self->run.exception_addr, 0);
1418
1419	get_buf_op.header.type = ENCL_OP_GET_FROM_BUFFER;
1420	get_buf_op.value = 0;
1421
1422	EXPECT_EQ(ENCL_CALL(&get_buf_op, &self->run, true), 0);
1423
1424	EXPECT_EQ(get_buf_op.value, MAGIC);
1425	EXPECT_EEXIT(&self->run);
1426	EXPECT_EQ(self->run.exception_vector, 0);
1427	EXPECT_EQ(self->run.exception_error_code, 0);
1428	EXPECT_EQ(self->run.exception_addr, 0);
1429
1430	/*
1431	 * Phase 2 of test:
1432	 * Remove pages associated with new TCS, create a regular page
1433	 * where TCS page used to be and verify it can be used as a regular
1434	 * page.
1435	 */
1436
1437	/* Start page removal by requesting change of page type to PT_TRIM. */
1438	memset(&modt_ioc, 0, sizeof(modt_ioc));
1439
1440	modt_ioc.offset = total_size;
1441	modt_ioc.length = 3 * PAGE_SIZE;
1442	modt_ioc.page_type = SGX_PAGE_TYPE_TRIM;
1443
1444	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
1445	errno_save = ret == -1 ? errno : 0;
1446
1447	EXPECT_EQ(ret, 0);
1448	EXPECT_EQ(errno_save, 0);
1449	EXPECT_EQ(modt_ioc.result, 0);
1450	EXPECT_EQ(modt_ioc.count, 3 * PAGE_SIZE);
1451
1452	/*
1453	 * Enter enclave via TCS #1 and approve page removal by sending
1454	 * EACCEPT for each of three removed pages.
1455	 */
1456	self->run.tcs = self->encl.encl_base;
1457
1458	eaccept_op.epc_addr = (unsigned long)stack_end;
1459	eaccept_op.flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED;
1460	eaccept_op.ret = 0;
1461	eaccept_op.header.type = ENCL_OP_EACCEPT;
1462
1463	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1464
1465	EXPECT_EEXIT(&self->run);
1466	EXPECT_EQ(self->run.exception_vector, 0);
1467	EXPECT_EQ(self->run.exception_error_code, 0);
1468	EXPECT_EQ(self->run.exception_addr, 0);
1469	EXPECT_EQ(eaccept_op.ret, 0);
1470
1471	eaccept_op.epc_addr = (unsigned long)tcs;
1472	eaccept_op.ret = 0;
1473
1474	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1475
1476	EXPECT_EEXIT(&self->run);
1477	EXPECT_EQ(self->run.exception_vector, 0);
1478	EXPECT_EQ(self->run.exception_error_code, 0);
1479	EXPECT_EQ(self->run.exception_addr, 0);
1480	EXPECT_EQ(eaccept_op.ret, 0);
1481
1482	eaccept_op.epc_addr = (unsigned long)ssa;
1483	eaccept_op.ret = 0;
1484
1485	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1486
1487	EXPECT_EEXIT(&self->run);
1488	EXPECT_EQ(self->run.exception_vector, 0);
1489	EXPECT_EQ(self->run.exception_error_code, 0);
1490	EXPECT_EQ(self->run.exception_addr, 0);
1491	EXPECT_EQ(eaccept_op.ret, 0);
1492
1493	/* Send final ioctl() to complete page removal. */
1494	memset(&remove_ioc, 0, sizeof(remove_ioc));
1495
1496	remove_ioc.offset = total_size;
1497	remove_ioc.length = 3 * PAGE_SIZE;
1498
1499	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &remove_ioc);
1500	errno_save = ret == -1 ? errno : 0;
1501
1502	EXPECT_EQ(ret, 0);
1503	EXPECT_EQ(errno_save, 0);
1504	EXPECT_EQ(remove_ioc.count, 3 * PAGE_SIZE);
1505
1506	/*
1507	 * Enter enclave via TCS #1 and access location where TCS #3 was to
1508	 * trigger dynamic add of regular page at that location.
1509	 */
1510	eaccept_op.epc_addr = (unsigned long)tcs;
1511	eaccept_op.flags = SGX_SECINFO_R | SGX_SECINFO_W | SGX_SECINFO_REG | SGX_SECINFO_PENDING;
1512	eaccept_op.ret = 0;
1513	eaccept_op.header.type = ENCL_OP_EACCEPT;
1514
1515	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1516
1517	EXPECT_EEXIT(&self->run);
1518	EXPECT_EQ(self->run.exception_vector, 0);
1519	EXPECT_EQ(self->run.exception_error_code, 0);
1520	EXPECT_EQ(self->run.exception_addr, 0);
1521	EXPECT_EQ(eaccept_op.ret, 0);
1522
1523	/*
1524	 * New page should be accessible from within enclave - write to it.
1525	 */
1526	put_addr_op.value = MAGIC;
1527	put_addr_op.addr = (unsigned long)tcs;
1528	put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS;
1529
1530	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
1531
1532	EXPECT_EEXIT(&self->run);
1533	EXPECT_EQ(self->run.exception_vector, 0);
1534	EXPECT_EQ(self->run.exception_error_code, 0);
1535	EXPECT_EQ(self->run.exception_addr, 0);
1536
1537	/*
1538	 * Read memory from newly added page that was just written to,
1539	 * confirming that data previously written (MAGIC) is present.
1540	 */
1541	get_addr_op.value = 0;
1542	get_addr_op.addr = (unsigned long)tcs;
1543	get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS;
1544
1545	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
1546
1547	EXPECT_EQ(get_addr_op.value, MAGIC);
1548	EXPECT_EEXIT(&self->run);
1549	EXPECT_EQ(self->run.exception_vector, 0);
1550	EXPECT_EQ(self->run.exception_error_code, 0);
1551	EXPECT_EQ(self->run.exception_addr, 0);
1552
1553	munmap(addr, 3 * PAGE_SIZE);
1554}
1555
1556/*
1557 * Ensure sane behavior if user requests page removal, does not run
1558 * EACCEPT from within enclave but still attempts to finalize page removal
1559 * with the SGX_IOC_ENCLAVE_REMOVE_PAGES ioctl(). The latter should fail
1560 * because the removal was not EACCEPTed from within the enclave.
1561 */
1562TEST_F(enclave, remove_added_page_no_eaccept)
1563{
1564	struct sgx_enclave_remove_pages remove_ioc;
1565	struct encl_op_get_from_addr get_addr_op;
1566	struct sgx_enclave_modify_types modt_ioc;
1567	struct encl_op_put_to_addr put_addr_op;
1568	unsigned long data_start;
1569	int ret, errno_save;
1570
1571	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
1572
1573	memset(&self->run, 0, sizeof(self->run));
1574	self->run.tcs = self->encl.encl_base;
1575
1576	/*
1577	 * Hardware (SGX2) and kernel support is needed for this test. Start
1578	 * with check that test has a chance of succeeding.
1579	 */
1580	memset(&modt_ioc, 0, sizeof(modt_ioc));
1581	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
1582
1583	if (ret == -1) {
1584		if (errno == ENOTTY)
1585			SKIP(return,
1586			     "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()");
1587		else if (errno == ENODEV)
1588			SKIP(return, "System does not support SGX2");
1589	}
1590
1591	/*
1592	 * Invalid parameters were provided during sanity check,
1593	 * expect command to fail.
1594	 */
1595	EXPECT_EQ(ret, -1);
1596
1597	/*
1598	 * Page that will be removed is the second data page in the .data
1599	 * segment. This forms part of the local encl_buffer within the
1600	 * enclave.
1601	 */
1602	data_start = self->encl.encl_base +
1603		     encl_get_data_offset(&self->encl) + PAGE_SIZE;
1604
1605	/*
1606	 * Sanity check that page at @data_start is writable before
1607	 * removing it.
1608	 *
1609	 * Start by writing MAGIC to test page.
1610	 */
1611	put_addr_op.value = MAGIC;
1612	put_addr_op.addr = data_start;
1613	put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS;
1614
1615	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
1616
1617	EXPECT_EEXIT(&self->run);
1618	EXPECT_EQ(self->run.exception_vector, 0);
1619	EXPECT_EQ(self->run.exception_error_code, 0);
1620	EXPECT_EQ(self->run.exception_addr, 0);
1621
1622	/*
1623	 * Read memory that was just written to, confirming that data
1624	 * previously written (MAGIC) is present.
1625	 */
1626	get_addr_op.value = 0;
1627	get_addr_op.addr = data_start;
1628	get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS;
1629
1630	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
1631
1632	EXPECT_EQ(get_addr_op.value, MAGIC);
1633	EXPECT_EEXIT(&self->run);
1634	EXPECT_EQ(self->run.exception_vector, 0);
1635	EXPECT_EQ(self->run.exception_error_code, 0);
1636	EXPECT_EQ(self->run.exception_addr, 0);
1637
1638	/* Start page removal by requesting change of page type to PT_TRIM */
1639	memset(&modt_ioc, 0, sizeof(modt_ioc));
1640
1641	modt_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE;
1642	modt_ioc.length = PAGE_SIZE;
1643	modt_ioc.page_type = SGX_PAGE_TYPE_TRIM;
1644
1645	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
1646	errno_save = ret == -1 ? errno : 0;
1647
1648	EXPECT_EQ(ret, 0);
1649	EXPECT_EQ(errno_save, 0);
1650	EXPECT_EQ(modt_ioc.result, 0);
1651	EXPECT_EQ(modt_ioc.count, 4096);
1652
1653	/* Skip EACCEPT */
1654
1655	/* Send final ioctl() to complete page removal */
1656	memset(&remove_ioc, 0, sizeof(remove_ioc));
1657
1658	remove_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE;
1659	remove_ioc.length = PAGE_SIZE;
1660
1661	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &remove_ioc);
1662	errno_save = ret == -1 ? errno : 0;
1663
1664	/* Operation not permitted since EACCEPT was omitted. */
1665	EXPECT_EQ(ret, -1);
1666	EXPECT_EQ(errno_save, EPERM);
1667	EXPECT_EQ(remove_ioc.count, 0);
1668}
1669
1670/*
1671 * Request enclave page removal but instead of correctly following with
1672 * EACCEPT a read attempt to page is made from within the enclave.
1673 */
1674TEST_F(enclave, remove_added_page_invalid_access)
1675{
1676	struct encl_op_get_from_addr get_addr_op;
1677	struct encl_op_put_to_addr put_addr_op;
1678	struct sgx_enclave_modify_types ioc;
1679	unsigned long data_start;
1680	int ret, errno_save;
1681
1682	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
1683
1684	memset(&self->run, 0, sizeof(self->run));
1685	self->run.tcs = self->encl.encl_base;
1686
1687	/*
1688	 * Hardware (SGX2) and kernel support is needed for this test. Start
1689	 * with check that test has a chance of succeeding.
1690	 */
1691	memset(&ioc, 0, sizeof(ioc));
1692	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &ioc);
1693
1694	if (ret == -1) {
1695		if (errno == ENOTTY)
1696			SKIP(return,
1697			     "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()");
1698		else if (errno == ENODEV)
1699			SKIP(return, "System does not support SGX2");
1700	}
1701
1702	/*
1703	 * Invalid parameters were provided during sanity check,
1704	 * expect command to fail.
1705	 */
1706	EXPECT_EQ(ret, -1);
1707
1708	/*
1709	 * Page that will be removed is the second data page in the .data
1710	 * segment. This forms part of the local encl_buffer within the
1711	 * enclave.
1712	 */
1713	data_start = self->encl.encl_base +
1714		     encl_get_data_offset(&self->encl) + PAGE_SIZE;
1715
1716	/*
1717	 * Sanity check that page at @data_start is writable before
1718	 * removing it.
1719	 *
1720	 * Start by writing MAGIC to test page.
1721	 */
1722	put_addr_op.value = MAGIC;
1723	put_addr_op.addr = data_start;
1724	put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS;
1725
1726	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
1727
1728	EXPECT_EEXIT(&self->run);
1729	EXPECT_EQ(self->run.exception_vector, 0);
1730	EXPECT_EQ(self->run.exception_error_code, 0);
1731	EXPECT_EQ(self->run.exception_addr, 0);
1732
1733	/*
1734	 * Read memory that was just written to, confirming that data
1735	 * previously written (MAGIC) is present.
1736	 */
1737	get_addr_op.value = 0;
1738	get_addr_op.addr = data_start;
1739	get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS;
1740
1741	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
1742
1743	EXPECT_EQ(get_addr_op.value, MAGIC);
1744	EXPECT_EEXIT(&self->run);
1745	EXPECT_EQ(self->run.exception_vector, 0);
1746	EXPECT_EQ(self->run.exception_error_code, 0);
1747	EXPECT_EQ(self->run.exception_addr, 0);
1748
1749	/* Start page removal by requesting change of page type to PT_TRIM. */
1750	memset(&ioc, 0, sizeof(ioc));
1751
1752	ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE;
1753	ioc.length = PAGE_SIZE;
1754	ioc.page_type = SGX_PAGE_TYPE_TRIM;
1755
1756	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &ioc);
1757	errno_save = ret == -1 ? errno : 0;
1758
1759	EXPECT_EQ(ret, 0);
1760	EXPECT_EQ(errno_save, 0);
1761	EXPECT_EQ(ioc.result, 0);
1762	EXPECT_EQ(ioc.count, 4096);
1763
1764	/*
1765	 * Read from page that was just removed.
1766	 */
1767	get_addr_op.value = 0;
1768
1769	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
1770
1771	/*
1772	 * From kernel perspective the page is present but according to SGX the
1773	 * page should not be accessible so a #PF with SGX bit set is
1774	 * expected.
1775	 */
1776
1777	EXPECT_EQ(self->run.function, ERESUME);
1778	EXPECT_EQ(self->run.exception_vector, 14);
1779	EXPECT_EQ(self->run.exception_error_code, 0x8005);
1780	EXPECT_EQ(self->run.exception_addr, data_start);
1781}
1782
1783/*
1784 * Request enclave page removal and correctly follow with
1785 * EACCEPT but do not follow with removal ioctl() but instead a read attempt
1786 * to removed page is made from within the enclave.
1787 */
1788TEST_F(enclave, remove_added_page_invalid_access_after_eaccept)
1789{
1790	struct encl_op_get_from_addr get_addr_op;
1791	struct encl_op_put_to_addr put_addr_op;
1792	struct sgx_enclave_modify_types ioc;
1793	struct encl_op_eaccept eaccept_op;
1794	unsigned long data_start;
1795	int ret, errno_save;
1796
1797	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
1798
1799	memset(&self->run, 0, sizeof(self->run));
1800	self->run.tcs = self->encl.encl_base;
1801
1802	/*
1803	 * Hardware (SGX2) and kernel support is needed for this test. Start
1804	 * with check that test has a chance of succeeding.
1805	 */
1806	memset(&ioc, 0, sizeof(ioc));
1807	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &ioc);
1808
1809	if (ret == -1) {
1810		if (errno == ENOTTY)
1811			SKIP(return,
1812			     "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()");
1813		else if (errno == ENODEV)
1814			SKIP(return, "System does not support SGX2");
1815	}
1816
1817	/*
1818	 * Invalid parameters were provided during sanity check,
1819	 * expect command to fail.
1820	 */
1821	EXPECT_EQ(ret, -1);
1822
1823	/*
1824	 * Page that will be removed is the second data page in the .data
1825	 * segment. This forms part of the local encl_buffer within the
1826	 * enclave.
1827	 */
1828	data_start = self->encl.encl_base +
1829		     encl_get_data_offset(&self->encl) + PAGE_SIZE;
1830
1831	/*
1832	 * Sanity check that page at @data_start is writable before
1833	 * removing it.
1834	 *
1835	 * Start by writing MAGIC to test page.
1836	 */
1837	put_addr_op.value = MAGIC;
1838	put_addr_op.addr = data_start;
1839	put_addr_op.header.type = ENCL_OP_PUT_TO_ADDRESS;
1840
1841	EXPECT_EQ(ENCL_CALL(&put_addr_op, &self->run, true), 0);
1842
1843	EXPECT_EEXIT(&self->run);
1844	EXPECT_EQ(self->run.exception_vector, 0);
1845	EXPECT_EQ(self->run.exception_error_code, 0);
1846	EXPECT_EQ(self->run.exception_addr, 0);
1847
1848	/*
1849	 * Read memory that was just written to, confirming that data
1850	 * previously written (MAGIC) is present.
1851	 */
1852	get_addr_op.value = 0;
1853	get_addr_op.addr = data_start;
1854	get_addr_op.header.type = ENCL_OP_GET_FROM_ADDRESS;
1855
1856	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
1857
1858	EXPECT_EQ(get_addr_op.value, MAGIC);
1859	EXPECT_EEXIT(&self->run);
1860	EXPECT_EQ(self->run.exception_vector, 0);
1861	EXPECT_EQ(self->run.exception_error_code, 0);
1862	EXPECT_EQ(self->run.exception_addr, 0);
1863
1864	/* Start page removal by requesting change of page type to PT_TRIM. */
1865	memset(&ioc, 0, sizeof(ioc));
1866
1867	ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE;
1868	ioc.length = PAGE_SIZE;
1869	ioc.page_type = SGX_PAGE_TYPE_TRIM;
1870
1871	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &ioc);
1872	errno_save = ret == -1 ? errno : 0;
1873
1874	EXPECT_EQ(ret, 0);
1875	EXPECT_EQ(errno_save, 0);
1876	EXPECT_EQ(ioc.result, 0);
1877	EXPECT_EQ(ioc.count, 4096);
1878
1879	eaccept_op.epc_addr = (unsigned long)data_start;
1880	eaccept_op.ret = 0;
1881	eaccept_op.flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED;
1882	eaccept_op.header.type = ENCL_OP_EACCEPT;
1883
1884	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1885
1886	EXPECT_EEXIT(&self->run);
1887	EXPECT_EQ(self->run.exception_vector, 0);
1888	EXPECT_EQ(self->run.exception_error_code, 0);
1889	EXPECT_EQ(self->run.exception_addr, 0);
1890	EXPECT_EQ(eaccept_op.ret, 0);
1891
1892	/* Skip ioctl() to remove page. */
1893
1894	/*
1895	 * Read from page that was just removed.
1896	 */
1897	get_addr_op.value = 0;
1898
1899	EXPECT_EQ(ENCL_CALL(&get_addr_op, &self->run, true), 0);
1900
1901	/*
1902	 * From kernel perspective the page is present but according to SGX the
1903	 * page should not be accessible so a #PF with SGX bit set is
1904	 * expected.
1905	 */
1906
1907	EXPECT_EQ(self->run.function, ERESUME);
1908	EXPECT_EQ(self->run.exception_vector, 14);
1909	EXPECT_EQ(self->run.exception_error_code, 0x8005);
1910	EXPECT_EQ(self->run.exception_addr, data_start);
1911}
1912
1913TEST_F(enclave, remove_untouched_page)
1914{
1915	struct sgx_enclave_remove_pages remove_ioc;
1916	struct sgx_enclave_modify_types modt_ioc;
1917	struct encl_op_eaccept eaccept_op;
1918	unsigned long data_start;
1919	int ret, errno_save;
1920
1921	ASSERT_TRUE(setup_test_encl(ENCL_HEAP_SIZE_DEFAULT, &self->encl, _metadata));
1922
1923	/*
1924	 * Hardware (SGX2) and kernel support is needed for this test. Start
1925	 * with check that test has a chance of succeeding.
1926	 */
1927	memset(&modt_ioc, 0, sizeof(modt_ioc));
1928	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
1929
1930	if (ret == -1) {
1931		if (errno == ENOTTY)
1932			SKIP(return,
1933			     "Kernel does not support SGX_IOC_ENCLAVE_MODIFY_TYPES ioctl()");
1934		else if (errno == ENODEV)
1935			SKIP(return, "System does not support SGX2");
1936	}
1937
1938	/*
1939	 * Invalid parameters were provided during sanity check,
1940	 * expect command to fail.
1941	 */
1942	EXPECT_EQ(ret, -1);
1943
1944	/* SGX2 is supported by kernel and hardware, test can proceed. */
1945	memset(&self->run, 0, sizeof(self->run));
1946	self->run.tcs = self->encl.encl_base;
1947
1948	data_start = self->encl.encl_base +
1949			 encl_get_data_offset(&self->encl) + PAGE_SIZE;
1950
1951	memset(&modt_ioc, 0, sizeof(modt_ioc));
1952
1953	modt_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE;
1954	modt_ioc.length = PAGE_SIZE;
1955	modt_ioc.page_type = SGX_PAGE_TYPE_TRIM;
1956	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &modt_ioc);
1957	errno_save = ret == -1 ? errno : 0;
1958
1959	EXPECT_EQ(ret, 0);
1960	EXPECT_EQ(errno_save, 0);
1961	EXPECT_EQ(modt_ioc.result, 0);
1962	EXPECT_EQ(modt_ioc.count, 4096);
1963
1964	/*
1965	 * Enter enclave via TCS #1 and approve page removal by sending
1966	 * EACCEPT for removed page.
1967	 */
1968
1969	eaccept_op.epc_addr = data_start;
1970	eaccept_op.flags = SGX_SECINFO_TRIM | SGX_SECINFO_MODIFIED;
1971	eaccept_op.ret = 0;
1972	eaccept_op.header.type = ENCL_OP_EACCEPT;
1973
1974	EXPECT_EQ(ENCL_CALL(&eaccept_op, &self->run, true), 0);
1975	EXPECT_EEXIT(&self->run);
1976	EXPECT_EQ(self->run.exception_vector, 0);
1977	EXPECT_EQ(self->run.exception_error_code, 0);
1978	EXPECT_EQ(self->run.exception_addr, 0);
1979	EXPECT_EQ(eaccept_op.ret, 0);
1980
1981	memset(&remove_ioc, 0, sizeof(remove_ioc));
1982
1983	remove_ioc.offset = encl_get_data_offset(&self->encl) + PAGE_SIZE;
1984	remove_ioc.length = PAGE_SIZE;
1985	ret = ioctl(self->encl.fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &remove_ioc);
1986	errno_save = ret == -1 ? errno : 0;
1987
1988	EXPECT_EQ(ret, 0);
1989	EXPECT_EQ(errno_save, 0);
1990	EXPECT_EQ(remove_ioc.count, 4096);
1991}
1992
1993TEST_HARNESS_MAIN