db_main.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
  2. /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
  3. /* Copyright (C) 2014 Stony Brook University
  4. This file is part of Graphene Library OS.
  5. Graphene Library OS is free software: you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public License
  7. as published by the Free Software Foundation, either version 3 of the
  8. License, or (at your option) any later version.
  9. Graphene Library OS is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. /*
  16. * db_main.c
  17. *
  18. * This file contains the main function of the PAL loader, which loads and
  19. * processes environment, arguments and manifest.
  20. */
  21. #include "pal_defs.h"
  22. #include "pal_linux_defs.h"
  23. #include "pal.h"
  24. #include "pal_internal.h"
  25. #include "pal_linux.h"
  26. #include "pal_debug.h"
  27. #include "pal_error.h"
  28. #include "pal_security.h"
  29. #include "api.h"
  30. #include <asm/mman.h>
  31. #include <asm/ioctls.h>
  32. #include <elf/elf.h>
  33. #include <sysdeps/generic/ldsodefs.h>
  34. #include "ecall_types.h"
  35. #include "enclave_pages.h"
  36. #define RTLD_BOOTSTRAP
  37. #define _ENTRY enclave_entry
  38. struct pal_linux_state linux_state;
  39. struct pal_sec pal_sec;
  40. unsigned int pagesz = PRESET_PAGESIZE;
  41. unsigned long _DkGetPagesize (void)
  42. {
  43. return pagesz;
  44. }
  45. unsigned long _DkGetAllocationAlignment (void)
  46. {
  47. return pagesz;
  48. }
  49. void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
  50. {
  51. *start = (PAL_PTR) pal_sec.heap_min;
  52. *end = (PAL_PTR) get_reserved_pages(NULL, pagesz);
  53. }
  54. PAL_NUM _DkGetProcessId (void)
  55. {
  56. return linux_state.process_id;
  57. }
  58. PAL_NUM _DkGetHostId (void)
  59. {
  60. return 0;
  61. }
  62. #include "elf-x86_64.h"
  63. #include "dynamic_link.h"
  64. void setup_pal_map (struct link_map * map);
  65. static struct link_map pal_map;
  66. void init_untrusted_slab_mgr ();
  67. int init_enclave (void);
  68. int init_enclave_key (void);
  69. int init_child_process (PAL_HANDLE * parent_handle);
  70. /*
  71. * Creates a dummy file handle with the given name.
  72. *
  73. * The handle is not backed by any file. Reads will return EOF and writes will
  74. * fail.
  75. */
  76. static PAL_HANDLE setup_dummy_file_handle (const char * name)
  77. {
  78. if (!strpartcmp_static(name, "file:"))
  79. return NULL;
  80. name += static_strlen("file:");
  81. int len = strlen(name);
  82. PAL_HANDLE handle = malloc(HANDLE_SIZE(file) + len + 1);
  83. SET_HANDLE_TYPE(handle, file);
  84. HANDLE_HDR(handle)->flags |= RFD(0);
  85. handle->file.fd = PAL_IDX_POISON;
  86. handle->file.append = 0;
  87. handle->file.pass = 0;
  88. char * path = (void *) handle + HANDLE_SIZE(file);
  89. get_norm_path(name, path, 0, len + 1);
  90. handle->file.realpath = path;
  91. handle->file.total = 0;
  92. handle->file.stubs = NULL;
  93. return handle;
  94. }
  95. static int loader_filter (const char * key, int len)
  96. {
  97. if (len > 7 && key[0] == 'l' && key[1] == 'o' && key[2] == 'a' && key[3] == 'd' &&
  98. key[4] == 'e' && key[5] == 'r' && key[6] == '.')
  99. return 0;
  100. if (len > 4 && key[0] == 's' && key[1] == 'g' && key[2] == 'x' && key[3] == '.')
  101. return 0;
  102. return 1;
  103. }
  104. /*
  105. * Takes a pointer+size to an untrusted memory region containing a
  106. * NUL-separated list of strings. It builds a argv-style list in trusted memory
  107. * with those strings.
  108. *
  109. * It is responsible for handling the access to untrusted memory safely
  110. * (returns NULL on error) and ensures that all strings are properly
  111. * terminated. The content of the strings is NOT further sanitized.
  112. *
  113. * The argv-style list is allocated on the heap and the caller is responsible
  114. * to free it (For argv and envp we rely on auto free on termination in
  115. * practice).
  116. */
  117. static const char** make_argv_list(void * uptr_src, uint64_t src_size) {
  118. const char **argv;
  119. if (src_size == 0) {
  120. argv = malloc(sizeof(char *));
  121. argv[0] = NULL;
  122. return argv;
  123. }
  124. char * data = malloc(src_size);
  125. if (!data) {
  126. return NULL;
  127. }
  128. if (!sgx_copy_to_enclave(data, src_size, uptr_src, src_size)) {
  129. goto free_and_err;
  130. }
  131. data[src_size - 1] = '\0';
  132. uint64_t argc = 0;
  133. for (uint64_t i = 0; i < src_size; i++) {
  134. if (data[i] == '\0') {
  135. argc++;
  136. }
  137. }
  138. size_t argv_size;
  139. if (__builtin_mul_overflow(argc + 1, sizeof(char *), &argv_size)) {
  140. goto free_and_err;
  141. }
  142. argv = malloc(argv_size);
  143. if (!argv) {
  144. goto free_and_err;
  145. }
  146. argv[argc] = NULL;
  147. uint64_t data_i = 0;
  148. for (uint64_t arg_i = 0; arg_i < argc; arg_i++) {
  149. argv[arg_i] = &data[data_i];
  150. while (data[data_i] != '\0') {
  151. data_i++;
  152. }
  153. data_i++;
  154. }
  155. return argv;
  156. free_and_err:
  157. free(data);
  158. return NULL;
  159. }
  160. extern void * enclave_base;
  161. extern void * enclave_top;
  162. void pal_linux_main(char * uptr_args, uint64_t args_size,
  163. char * uptr_env, uint64_t env_size,
  164. struct pal_sec * uptr_sec_info)
  165. {
  166. /*
  167. * Our arguments are comming directly from the urts. We are responsible to
  168. * check them.
  169. */
  170. PAL_HANDLE parent = NULL;
  171. unsigned long start_time = _DkSystemTimeQuery();
  172. int rv;
  173. struct pal_sec sec_info;
  174. if (!sgx_copy_to_enclave(&sec_info, sizeof(sec_info), uptr_sec_info, sizeof(sec_info))) {
  175. return;
  176. }
  177. pal_sec.heap_min = GET_ENCLAVE_TLS(heap_min);
  178. pal_sec.heap_max = GET_ENCLAVE_TLS(heap_max);
  179. pal_sec.exec_addr = GET_ENCLAVE_TLS(exec_addr);
  180. pal_sec.exec_size = GET_ENCLAVE_TLS(exec_size);
  181. /* Zero the heap. We need to take care to not zero the exec area. */
  182. void* zero1_start = pal_sec.heap_min;
  183. void* zero1_end = pal_sec.heap_max;
  184. void* zero2_start = pal_sec.heap_max;
  185. void* zero2_end = pal_sec.heap_max;
  186. if (pal_sec.exec_addr != NULL) {
  187. zero1_end = MIN(zero1_end, pal_sec.exec_addr);
  188. zero2_start = MIN(zero2_start, pal_sec.exec_addr + pal_sec.exec_size);
  189. }
  190. memset(zero1_start, 0, zero1_end - zero1_start);
  191. memset(zero2_start, 0, zero2_end - zero2_start);
  192. /* relocate PAL itself */
  193. pal_map.l_addr = elf_machine_load_address();
  194. pal_map.l_name = ENCLAVE_FILENAME;
  195. elf_get_dynamic_info((void *) pal_map.l_addr + elf_machine_dynamic(),
  196. pal_map.l_info, pal_map.l_addr);
  197. ELF_DYNAMIC_RELOCATE(&pal_map);
  198. /*
  199. * We can't verify the following arguments from the urts. So we copy
  200. * them directly but need to be careful when we use them.
  201. */
  202. pal_sec.instance_id = sec_info.instance_id;
  203. COPY_ARRAY(pal_sec.exec_name, sec_info.exec_name);
  204. pal_sec.exec_name[sizeof(pal_sec.exec_name) - 1] = '\0';
  205. COPY_ARRAY(pal_sec.manifest_name, sec_info.manifest_name);
  206. pal_sec.manifest_name[sizeof(pal_sec.manifest_name) - 1] = '\0';
  207. COPY_ARRAY(pal_sec.proc_fds, sec_info.proc_fds);
  208. COPY_ARRAY(pal_sec.pipe_prefix, sec_info.pipe_prefix);
  209. pal_sec.mcast_port = sec_info.mcast_port;
  210. pal_sec.mcast_srv = sec_info.mcast_srv;
  211. pal_sec.mcast_cli = sec_info.mcast_cli;
  212. #ifdef DEBUG
  213. pal_sec.in_gdb = sec_info.in_gdb;
  214. #endif
  215. #if PRINT_ENCLAVE_STAT == 1
  216. pal_sec.start_time = sec_info.start_time;
  217. #endif
  218. /* For {p,u,g}ids we can at least do some minimal checking. */
  219. /* ppid should be positive when interpreted as signed. It's 0 if we don't
  220. * have a graphene parent process. */
  221. if (sec_info.ppid > INT32_MAX) {
  222. return;
  223. }
  224. pal_sec.ppid = sec_info.ppid;
  225. /* As ppid but we always have a pid, so 0 is invalid. */
  226. if (sec_info.pid > INT32_MAX || sec_info.pid == 0) {
  227. return;
  228. }
  229. pal_sec.pid = sec_info.pid;
  230. /* -1 is treated as special value for example by chown. */
  231. if (sec_info.uid == (PAL_IDX)-1 || sec_info.gid == (PAL_IDX)-1) {
  232. return;
  233. }
  234. pal_sec.uid = sec_info.uid;
  235. pal_sec.gid = sec_info.gid;
  236. /* set up page allocator and slab manager */
  237. init_slab_mgr(pagesz);
  238. init_untrusted_slab_mgr();
  239. init_pages();
  240. init_enclave_key();
  241. /* now we can add a link map for PAL itself */
  242. setup_pal_map(&pal_map);
  243. /* initialize enclave properties */
  244. rv = init_enclave();
  245. if (rv) {
  246. SGX_DBG(DBG_E, "Failed to initalize enclave properties: %d\n", rv);
  247. ocall_exit(rv);
  248. }
  249. if (args_size > MAX_ARGS_SIZE || env_size > MAX_ENV_SIZE) {
  250. return;
  251. }
  252. const char ** arguments = make_argv_list(uptr_args, args_size);
  253. if (!arguments) {
  254. return;
  255. }
  256. const char ** environments = make_argv_list(uptr_env, env_size);
  257. if (!environments) {
  258. return;
  259. }
  260. pal_state.start_time = start_time;
  261. /* if there is a parent, create parent handle */
  262. if (pal_sec.ppid) {
  263. if ((rv = init_child_process(&parent)) < 0) {
  264. SGX_DBG(DBG_E, "Failed to initialize child process: %d\n", rv);
  265. ocall_exit(rv);
  266. }
  267. }
  268. linux_state.uid = pal_sec.uid;
  269. linux_state.gid = pal_sec.gid;
  270. linux_state.process_id = (start_time & (~0xffff)) | pal_sec.pid;
  271. /* now let's mark our enclave as initialized */
  272. pal_enclave_state.enclave_flags |= PAL_ENCLAVE_INITIALIZED;
  273. SET_ENCLAVE_TLS(ready_for_exceptions, 1UL);
  274. /*
  275. * We create dummy handles for exec and manifest here to make the logic in
  276. * pal_main happy and pass the path of them. The handles can't be used to
  277. * read anything.
  278. */
  279. PAL_HANDLE manifest, exec = NULL;
  280. manifest = setup_dummy_file_handle(pal_sec.manifest_name);
  281. if (pal_sec.exec_name[0] != '\0') {
  282. exec = setup_dummy_file_handle(pal_sec.exec_name);
  283. } else {
  284. SGX_DBG(DBG_I, "Run without executable\n");
  285. }
  286. uint64_t manifest_size = GET_ENCLAVE_TLS(manifest_size);
  287. void* manifest_addr = enclave_top - ALIGN_UP_PTR(manifest_size, pagesz);
  288. /* parse manifest data into config storage */
  289. struct config_store * root_config =
  290. malloc(sizeof(struct config_store));
  291. root_config->raw_data = manifest_addr;
  292. root_config->raw_size = manifest_size;
  293. root_config->malloc = malloc;
  294. root_config->free = free;
  295. const char * errstring = NULL;
  296. if ((rv = read_config(root_config, loader_filter, &errstring)) < 0) {
  297. SGX_DBG(DBG_E, "Can't read manifest: %s, error code %d\n", errstring, rv);
  298. ocall_exit(rv);
  299. }
  300. pal_state.root_config = root_config;
  301. __pal_control.manifest_preload.start = (PAL_PTR) manifest_addr;
  302. __pal_control.manifest_preload.end = (PAL_PTR) manifest_addr + manifest_size;
  303. init_trusted_files();
  304. init_trusted_children();
  305. #if PRINT_ENCLAVE_STAT == 1
  306. printf(" >>>>>>>> "
  307. "Enclave loading time = %10ld milliseconds\n",
  308. _DkSystemTimeQuery() - pal_sec.start_time);
  309. #endif
  310. /* set up thread handle */
  311. PAL_HANDLE first_thread = malloc(HANDLE_SIZE(thread));
  312. SET_HANDLE_TYPE(first_thread, thread);
  313. first_thread->thread.tcs =
  314. enclave_base + GET_ENCLAVE_TLS(tcs_offset);
  315. SET_ENCLAVE_TLS(thread, (__pal_control.first_thread = first_thread));
  316. /* call main function */
  317. pal_main(pal_sec.instance_id, manifest, exec,
  318. pal_sec.exec_addr, parent, first_thread,
  319. arguments, environments);
  320. }
  321. /* the following code is borrowed from CPUID */
  322. static void cpuid (unsigned int leaf, unsigned int subleaf,
  323. unsigned int words[])
  324. {
  325. _DkCpuIdRetrieve(leaf, subleaf, words);
  326. }
  327. #define FOUR_CHARS_VALUE(s, w) \
  328. (s)[0] = (w) & 0xff; \
  329. (s)[1] = ((w) >> 8) & 0xff; \
  330. (s)[2] = ((w) >> 16) & 0xff; \
  331. (s)[3] = ((w) >> 24) & 0xff;
  332. #define BPI 32
  333. #define POWER2(power) \
  334. (1ULL << (power))
  335. #define RIGHTMASK(width) \
  336. (((unsigned long) (width) >= BPI) ? ~0ULL : POWER2(width)-1ULL)
  337. #define BIT_EXTRACT_LE(value, start, after) \
  338. (((unsigned long) (value) & RIGHTMASK(after)) >> start)
  339. static char * cpu_flags[]
  340. = { "fpu", // "x87 FPU on chip"
  341. "vme", // "virtual-8086 mode enhancement"
  342. "de", // "debugging extensions"
  343. "pse", // "page size extensions"
  344. "tsc", // "time stamp counter"
  345. "msr", // "RDMSR and WRMSR support"
  346. "pae", // "physical address extensions"
  347. "mce", // "machine check exception"
  348. "cx8", // "CMPXCHG8B inst."
  349. "apic", // "APIC on chip"
  350. NULL,
  351. "sep", // "SYSENTER and SYSEXIT"
  352. "mtrr", // "memory type range registers"
  353. "pge", // "PTE global bit"
  354. "mca", // "machine check architecture"
  355. "cmov", // "conditional move/compare instruction"
  356. "pat", // "page attribute table"
  357. "pse36", // "page size extension"
  358. "pn", // "processor serial number"
  359. "clflush", // "CLFLUSH instruction"
  360. NULL,
  361. "dts", // "debug store"
  362. "acpi", // "Onboard thermal control"
  363. "mmx", // "MMX Technology"
  364. "fxsr", // "FXSAVE/FXRSTOR"
  365. "sse", // "SSE extensions"
  366. "sse2", // "SSE2 extensions"
  367. "ss", // "self snoop"
  368. "ht", // "hyper-threading / multi-core supported"
  369. "tm", // "therm. monitor"
  370. "ia64", // "IA64"
  371. "pbe", // "pending break event"
  372. };
  373. void _DkGetCPUInfo (PAL_CPU_INFO * ci)
  374. {
  375. unsigned int words[PAL_CPUID_WORD_NUM];
  376. const size_t VENDOR_ID_SIZE = 13;
  377. char* vendor_id = malloc(VENDOR_ID_SIZE);
  378. cpuid(0, 0, words);
  379. FOUR_CHARS_VALUE(&vendor_id[0], words[PAL_CPUID_WORD_EBX]);
  380. FOUR_CHARS_VALUE(&vendor_id[4], words[PAL_CPUID_WORD_EDX]);
  381. FOUR_CHARS_VALUE(&vendor_id[8], words[PAL_CPUID_WORD_ECX]);
  382. vendor_id[VENDOR_ID_SIZE - 1] = '\0';
  383. ci->cpu_vendor = vendor_id;
  384. // Must be an Intel CPU
  385. assert(!memcmp(vendor_id, "GenuineIntel", 12));
  386. const size_t BRAND_SIZE = 49;
  387. char* brand = malloc(BRAND_SIZE);
  388. cpuid(0x80000002, 0, words);
  389. memcpy(&brand[ 0], words, sizeof(unsigned int) * PAL_CPUID_WORD_NUM);
  390. cpuid(0x80000003, 0, words);
  391. memcpy(&brand[16], words, sizeof(unsigned int) * PAL_CPUID_WORD_NUM);
  392. cpuid(0x80000004, 0, words);
  393. memcpy(&brand[32], words, sizeof(unsigned int) * PAL_CPUID_WORD_NUM);
  394. brand[BRAND_SIZE - 1] = '\0';
  395. ci->cpu_brand = brand;
  396. /* According to SDM: EBX[15:0] is to enumerate processor topology
  397. * of the system. However this value is intended for display/diagnostic
  398. * purposes. The actual number of logical processors available to
  399. * BIOS/OS/App may be different. We use this leaf for now as it's the
  400. * best option we have so far to get the cpu number */
  401. cpuid(0xb, 1, words);
  402. ci->cpu_num = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EBX], 0, 16);
  403. cpuid(1, 0, words);
  404. ci->cpu_family = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 8, 12) +
  405. BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 20, 28);
  406. ci->cpu_model = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 4, 8) +
  407. (BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 16, 20) << 4);
  408. ci->cpu_stepping = BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EAX], 0, 4);
  409. int flen = 0, fmax = 80;
  410. char * flags = malloc(fmax);
  411. for (int i = 0 ; i < 32 ; i++) {
  412. if (!cpu_flags[i])
  413. continue;
  414. if (BIT_EXTRACT_LE(words[PAL_CPUID_WORD_EDX], i, i + 1)) {
  415. int len = strlen(cpu_flags[i]);
  416. if (flen + len + 1 > fmax) {
  417. char * new_flags = malloc(fmax * 2);
  418. memcpy(new_flags, flags, flen);
  419. free(flags);
  420. fmax *= 2;
  421. flags = new_flags;
  422. }
  423. memcpy(flags + flen, cpu_flags[i], len);
  424. flen += len;
  425. flags[flen++] = ' ';
  426. }
  427. }
  428. flags[flen ? flen - 1 : 0] = 0;
  429. ci->cpu_flags = flags;
  430. }