xref: /openbmc/linux/tools/testing/selftests/sgx/main.c (revision 31e67366)
1 // SPDX-License-Identifier: GPL-2.0
2 /*  Copyright(c) 2016-20 Intel Corporation. */
3 
4 #include <elf.h>
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <stdbool.h>
8 #include <stdio.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <sys/ioctl.h>
14 #include <sys/mman.h>
15 #include <sys/stat.h>
16 #include <sys/time.h>
17 #include <sys/types.h>
18 #include "defines.h"
19 #include "main.h"
20 #include "../kselftest.h"
21 
22 static const uint64_t MAGIC = 0x1122334455667788ULL;
23 vdso_sgx_enter_enclave_t eenter;
24 
25 struct vdso_symtab {
26 	Elf64_Sym *elf_symtab;
27 	const char *elf_symstrtab;
28 	Elf64_Word *elf_hashtab;
29 };
30 
31 static void *vdso_get_base_addr(char *envp[])
32 {
33 	Elf64_auxv_t *auxv;
34 	int i;
35 
36 	for (i = 0; envp[i]; i++)
37 		;
38 
39 	auxv = (Elf64_auxv_t *)&envp[i + 1];
40 
41 	for (i = 0; auxv[i].a_type != AT_NULL; i++) {
42 		if (auxv[i].a_type == AT_SYSINFO_EHDR)
43 			return (void *)auxv[i].a_un.a_val;
44 	}
45 
46 	return NULL;
47 }
48 
49 static Elf64_Dyn *vdso_get_dyntab(void *addr)
50 {
51 	Elf64_Ehdr *ehdr = addr;
52 	Elf64_Phdr *phdrtab = addr + ehdr->e_phoff;
53 	int i;
54 
55 	for (i = 0; i < ehdr->e_phnum; i++)
56 		if (phdrtab[i].p_type == PT_DYNAMIC)
57 			return addr + phdrtab[i].p_offset;
58 
59 	return NULL;
60 }
61 
62 static void *vdso_get_dyn(void *addr, Elf64_Dyn *dyntab, Elf64_Sxword tag)
63 {
64 	int i;
65 
66 	for (i = 0; dyntab[i].d_tag != DT_NULL; i++)
67 		if (dyntab[i].d_tag == tag)
68 			return addr + dyntab[i].d_un.d_ptr;
69 
70 	return NULL;
71 }
72 
73 static bool vdso_get_symtab(void *addr, struct vdso_symtab *symtab)
74 {
75 	Elf64_Dyn *dyntab = vdso_get_dyntab(addr);
76 
77 	symtab->elf_symtab = vdso_get_dyn(addr, dyntab, DT_SYMTAB);
78 	if (!symtab->elf_symtab)
79 		return false;
80 
81 	symtab->elf_symstrtab = vdso_get_dyn(addr, dyntab, DT_STRTAB);
82 	if (!symtab->elf_symstrtab)
83 		return false;
84 
85 	symtab->elf_hashtab = vdso_get_dyn(addr, dyntab, DT_HASH);
86 	if (!symtab->elf_hashtab)
87 		return false;
88 
89 	return true;
90 }
91 
92 static unsigned long elf_sym_hash(const char *name)
93 {
94 	unsigned long h = 0, high;
95 
96 	while (*name) {
97 		h = (h << 4) + *name++;
98 		high = h & 0xf0000000;
99 
100 		if (high)
101 			h ^= high >> 24;
102 
103 		h &= ~high;
104 	}
105 
106 	return h;
107 }
108 
109 static Elf64_Sym *vdso_symtab_get(struct vdso_symtab *symtab, const char *name)
110 {
111 	Elf64_Word bucketnum = symtab->elf_hashtab[0];
112 	Elf64_Word *buckettab = &symtab->elf_hashtab[2];
113 	Elf64_Word *chaintab = &symtab->elf_hashtab[2 + bucketnum];
114 	Elf64_Sym *sym;
115 	Elf64_Word i;
116 
117 	for (i = buckettab[elf_sym_hash(name) % bucketnum]; i != STN_UNDEF;
118 	     i = chaintab[i]) {
119 		sym = &symtab->elf_symtab[i];
120 		if (!strcmp(name, &symtab->elf_symstrtab[sym->st_name]))
121 			return sym;
122 	}
123 
124 	return NULL;
125 }
126 
127 bool report_results(struct sgx_enclave_run *run, int ret, uint64_t result,
128 		  const char *test)
129 {
130 	bool valid = true;
131 
132 	if (ret) {
133 		printf("FAIL: %s() returned: %d\n", test, ret);
134 		valid = false;
135 	}
136 
137 	if (run->function != EEXIT) {
138 		printf("FAIL: %s() function, expected: %u, got: %u\n", test, EEXIT,
139 		       run->function);
140 		valid = false;
141 	}
142 
143 	if (result != MAGIC) {
144 		printf("FAIL: %s(), expected: 0x%lx, got: 0x%lx\n", test, MAGIC,
145 		       result);
146 		valid = false;
147 	}
148 
149 	if (run->user_data) {
150 		printf("FAIL: %s() user data, expected: 0x0, got: 0x%llx\n",
151 		       test, run->user_data);
152 		valid = false;
153 	}
154 
155 	return valid;
156 }
157 
158 static int user_handler(long rdi, long rsi, long rdx, long ursp, long r8, long r9,
159 			struct sgx_enclave_run *run)
160 {
161 	run->user_data = 0;
162 	return 0;
163 }
164 
165 int main(int argc, char *argv[], char *envp[])
166 {
167 	struct sgx_enclave_run run;
168 	struct vdso_symtab symtab;
169 	Elf64_Sym *eenter_sym;
170 	uint64_t result = 0;
171 	struct encl encl;
172 	unsigned int i;
173 	void *addr;
174 	int ret;
175 
176 	memset(&run, 0, sizeof(run));
177 
178 	if (!encl_load("test_encl.elf", &encl)) {
179 		encl_delete(&encl);
180 		ksft_exit_skip("cannot load enclaves\n");
181 	}
182 
183 	if (!encl_measure(&encl))
184 		goto err;
185 
186 	if (!encl_build(&encl))
187 		goto err;
188 
189 	/*
190 	 * An enclave consumer only must do this.
191 	 */
192 	for (i = 0; i < encl.nr_segments; i++) {
193 		struct encl_segment *seg = &encl.segment_tbl[i];
194 
195 		addr = mmap((void *)encl.encl_base + seg->offset, seg->size,
196 			    seg->prot, MAP_SHARED | MAP_FIXED, encl.fd, 0);
197 		if (addr == MAP_FAILED) {
198 			fprintf(stderr, "mmap() failed, errno=%d.\n", errno);
199 			exit(KSFT_FAIL);
200 		}
201 	}
202 
203 	memset(&run, 0, sizeof(run));
204 	run.tcs = encl.encl_base;
205 
206 	addr = vdso_get_base_addr(envp);
207 	if (!addr)
208 		goto err;
209 
210 	if (!vdso_get_symtab(addr, &symtab))
211 		goto err;
212 
213 	eenter_sym = vdso_symtab_get(&symtab, "__vdso_sgx_enter_enclave");
214 	if (!eenter_sym)
215 		goto err;
216 
217 	eenter = addr + eenter_sym->st_value;
218 
219 	ret = sgx_call_vdso((void *)&MAGIC, &result, 0, EENTER, NULL, NULL, &run);
220 	if (!report_results(&run, ret, result, "sgx_call_vdso"))
221 		goto err;
222 
223 
224 	/* Invoke the vDSO directly. */
225 	result = 0;
226 	ret = eenter((unsigned long)&MAGIC, (unsigned long)&result, 0, EENTER,
227 		     0, 0, &run);
228 	if (!report_results(&run, ret, result, "eenter"))
229 		goto err;
230 
231 	/* And with an exit handler. */
232 	run.user_handler = (__u64)user_handler;
233 	run.user_data = 0xdeadbeef;
234 	ret = eenter((unsigned long)&MAGIC, (unsigned long)&result, 0, EENTER,
235 		     0, 0, &run);
236 	if (!report_results(&run, ret, result, "user_handler"))
237 		goto err;
238 
239 	printf("SUCCESS\n");
240 	encl_delete(&encl);
241 	exit(KSFT_PASS);
242 
243 err:
244 	encl_delete(&encl);
245 	exit(KSFT_FAIL);
246 }
247