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