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
1994