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