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