db_main.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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. int init_untrusted_slab_mgr (int pagesize);
  67. int init_enclave (void);
  68. int init_enclave_key (void);
  69. int init_child_process (PAL_HANDLE * parent_handle);
  70. static PAL_HANDLE setup_file_handle (const char * name, int fd)
  71. {
  72. if (!strpartcmp_static(name, "file:"))
  73. return NULL;
  74. name += static_strlen("file:");
  75. int len = strlen(name);
  76. PAL_HANDLE handle = malloc(HANDLE_SIZE(file) + len + 1);
  77. SET_HANDLE_TYPE(handle, file);
  78. HANDLE_HDR(handle)->flags |= RFD(0);
  79. handle->file.fd = fd;
  80. handle->file.append = 0;
  81. handle->file.pass = 0;
  82. char * path = (void *) handle + HANDLE_SIZE(file);
  83. get_norm_path(name, path, 0, len + 1);
  84. handle->file.realpath = path;
  85. handle->file.total = 0;
  86. handle->file.stubs = NULL;
  87. return handle;
  88. }
  89. static int loader_filter (const char * key, int len)
  90. {
  91. if (key[0] == 'l' && key[1] == 'o' && key[2] == 'a' && key[3] == 'd' &&
  92. key[4] == 'e' && key[5] == 'r' && key[6] == '.')
  93. return 0;
  94. if (key[0] == 's' && key[1] == 'g' && key[2] == 'x' && key[3] == '.')
  95. return 0;
  96. return 1;
  97. }
  98. extern void * enclave_base;
  99. void pal_linux_main(const char ** arguments, const char ** environments,
  100. struct pal_sec * sec_info)
  101. {
  102. PAL_HANDLE parent = NULL;
  103. unsigned long start_time = _DkSystemTimeQuery();
  104. int rv;
  105. /* relocate PAL itself */
  106. pal_map.l_addr = (ElfW(Addr)) sec_info->enclave_addr;
  107. pal_map.l_name = sec_info->enclave_image;
  108. elf_get_dynamic_info((void *) pal_map.l_addr + elf_machine_dynamic(),
  109. pal_map.l_info, pal_map.l_addr);
  110. ELF_DYNAMIC_RELOCATE(&pal_map);
  111. memcpy(&pal_sec, sec_info, sizeof(struct pal_sec));
  112. /* set up page allocator and slab manager */
  113. init_slab_mgr(pagesz);
  114. init_untrusted_slab_mgr(pagesz);
  115. init_pages();
  116. init_enclave_key();
  117. /* now we can add a link map for PAL itself */
  118. setup_pal_map(&pal_map);
  119. /* initialize enclave properties */
  120. init_enclave();
  121. pal_state.start_time = start_time;
  122. /* if there is a parent, create parent handle */
  123. if (pal_sec.ppid) {
  124. if ((rv = init_child_process(&parent)) < 0) {
  125. SGX_DBG(DBG_E, "Failed to initialize child process: %d\n", rv);
  126. ocall_exit(rv);
  127. }
  128. }
  129. linux_state.uid = pal_sec.uid;
  130. linux_state.gid = pal_sec.gid;
  131. linux_state.process_id = (start_time & (~0xffff)) | pal_sec.pid;
  132. /* now let's mark our enclave as initialized */
  133. pal_enclave_state.enclave_flags |= PAL_ENCLAVE_INITIALIZED;
  134. /* create executable handle */
  135. PAL_HANDLE manifest, exec = NULL;
  136. /* create manifest handle */
  137. manifest =
  138. setup_file_handle(pal_sec.manifest_name, pal_sec.manifest_fd);
  139. if (pal_sec.exec_fd != PAL_IDX_POISON) {
  140. exec = setup_file_handle(pal_sec.exec_name, pal_sec.exec_fd);
  141. } else {
  142. SGX_DBG(DBG_I, "Run without executable\n");
  143. }
  144. /* parse manifest data into config storage */
  145. struct config_store * root_config =
  146. malloc(sizeof(struct config_store));
  147. root_config->raw_data = pal_sec.manifest_addr;
  148. root_config->raw_size = pal_sec.manifest_size;
  149. root_config->malloc = malloc;
  150. root_config->free = free;
  151. const char * errstring = NULL;
  152. if ((rv = read_config(root_config, loader_filter, &errstring)) < 0) {
  153. SGX_DBG(DBG_E, "Can't read manifest: %s, error code %d\n", errstring, rv);
  154. ocall_exit(rv);
  155. }
  156. pal_state.root_config = root_config;
  157. __pal_control.manifest_preload.start = (PAL_PTR) pal_sec.manifest_addr;
  158. __pal_control.manifest_preload.end = (PAL_PTR) pal_sec.manifest_addr +
  159. pal_sec.manifest_size;
  160. init_trusted_files();
  161. init_trusted_children();
  162. #if PRINT_ENCLAVE_STAT == 1
  163. printf(" >>>>>>>> "
  164. "Enclave loading time = %10ld milliseconds\n",
  165. _DkSystemTimeQuery() - sec_info->start_time);
  166. #endif
  167. /* set up thread handle */
  168. PAL_HANDLE first_thread = malloc(HANDLE_SIZE(thread));
  169. SET_HANDLE_TYPE(first_thread, thread);
  170. first_thread->thread.tcs =
  171. enclave_base + GET_ENCLAVE_TLS(tcs_offset);
  172. SET_ENCLAVE_TLS(thread, (__pal_control.first_thread = first_thread));
  173. /* call main function */
  174. pal_main(pal_sec.instance_id, manifest, exec,
  175. pal_sec.exec_addr, parent, first_thread,
  176. arguments, environments);
  177. }
  178. /* the following code is borrowed from CPUID */
  179. #define WORD_EAX 0
  180. #define WORD_EBX 1
  181. #define WORD_ECX 2
  182. #define WORD_EDX 3
  183. #define WORD_NUM 4
  184. static void cpuid (unsigned int leaf, unsigned int subleaf,
  185. unsigned int words[])
  186. {
  187. _DkCpuIdRetrieve(leaf, subleaf, words);
  188. }
  189. #define FOUR_CHARS_VALUE(s, w) \
  190. (s)[0] = (w) & 0xff; \
  191. (s)[1] = ((w) >> 8) & 0xff; \
  192. (s)[2] = ((w) >> 16) & 0xff; \
  193. (s)[3] = ((w) >> 24) & 0xff;
  194. #define BPI 32
  195. #define POWER2(power) \
  196. (1ULL << (power))
  197. #define RIGHTMASK(width) \
  198. (((unsigned long) (width) >= BPI) ? ~0ULL : POWER2(width)-1ULL)
  199. #define BIT_EXTRACT_LE(value, start, after) \
  200. (((unsigned long) (value) & RIGHTMASK(after)) >> start)
  201. static char * cpu_flags[]
  202. = { "fpu", // "x87 FPU on chip"
  203. "vme", // "virtual-8086 mode enhancement"
  204. "de", // "debugging extensions"
  205. "pse", // "page size extensions"
  206. "tsc", // "time stamp counter"
  207. "msr", // "RDMSR and WRMSR support"
  208. "pae", // "physical address extensions"
  209. "mce", // "machine check exception"
  210. "cx8", // "CMPXCHG8B inst."
  211. "apic", // "APIC on chip"
  212. NULL,
  213. "sep", // "SYSENTER and SYSEXIT"
  214. "mtrr", // "memory type range registers"
  215. "pge", // "PTE global bit"
  216. "mca", // "machine check architecture"
  217. "cmov", // "conditional move/compare instruction"
  218. "pat", // "page attribute table"
  219. "pse36", // "page size extension"
  220. "pn", // "processor serial number"
  221. "clflush", // "CLFLUSH instruction"
  222. NULL,
  223. "dts", // "debug store"
  224. "acpi", // "Onboard thermal control"
  225. "mmx", // "MMX Technology"
  226. "fxsr", // "FXSAVE/FXRSTOR"
  227. "sse", // "SSE extensions"
  228. "sse2", // "SSE2 extensions"
  229. "ss", // "self snoop"
  230. "ht", // "hyper-threading / multi-core supported"
  231. "tm", // "therm. monitor"
  232. "ia64", // "IA64"
  233. "pbe", // "pending break event"
  234. };
  235. void _DkGetCPUInfo (PAL_CPU_INFO * ci)
  236. {
  237. unsigned int words[WORD_NUM];
  238. const size_t VENDOR_ID_SIZE = 13;
  239. char* vendor_id = malloc(VENDOR_ID_SIZE);
  240. cpuid(0, 0, words);
  241. FOUR_CHARS_VALUE(&vendor_id[0], words[WORD_EBX]);
  242. FOUR_CHARS_VALUE(&vendor_id[4], words[WORD_EDX]);
  243. FOUR_CHARS_VALUE(&vendor_id[8], words[WORD_ECX]);
  244. vendor_id[VENDOR_ID_SIZE - 1] = '\0';
  245. ci->cpu_vendor = vendor_id;
  246. // Must be an Intel CPU
  247. assert(!memcmp(vendor_id, "GenuineIntel", 12));
  248. const size_t BRAND_SIZE = 49;
  249. char* brand = malloc(BRAND_SIZE);
  250. cpuid(0x80000002, 0, words);
  251. memcpy(&brand[ 0], words, sizeof(unsigned int) * WORD_NUM);
  252. cpuid(0x80000003, 0, words);
  253. memcpy(&brand[16], words, sizeof(unsigned int) * WORD_NUM);
  254. cpuid(0x80000004, 0, words);
  255. memcpy(&brand[32], words, sizeof(unsigned int) * WORD_NUM);
  256. brand[BRAND_SIZE - 1] = '\0';
  257. ci->cpu_brand = brand;
  258. /* According to SDM: EBX[15:0] is to enumerate processor topology
  259. * of the system. However this value is intended for display/diagnostic
  260. * purposes. The actual number of logical processors available to
  261. * BIOS/OS/App may be different. We use this leaf for now as it's the
  262. * best option we have so far to get the cpu number */
  263. cpuid(0xb, 1, words);
  264. ci->cpu_num = BIT_EXTRACT_LE(words[WORD_EBX], 0, 16);
  265. cpuid(1, 0, words);
  266. ci->cpu_family = BIT_EXTRACT_LE(words[WORD_EAX], 8, 12) +
  267. BIT_EXTRACT_LE(words[WORD_EAX], 20, 28);
  268. ci->cpu_model = BIT_EXTRACT_LE(words[WORD_EAX], 4, 8) +
  269. (BIT_EXTRACT_LE(words[WORD_EAX], 16, 20) << 4);
  270. ci->cpu_stepping = BIT_EXTRACT_LE(words[WORD_EAX], 0, 4);
  271. int flen = 0, fmax = 80;
  272. char * flags = malloc(fmax);
  273. for (int i = 0 ; i < 32 ; i++) {
  274. if (!cpu_flags[i])
  275. continue;
  276. if (BIT_EXTRACT_LE(words[WORD_EDX], i, i + 1)) {
  277. int len = strlen(cpu_flags[i]);
  278. if (flen + len + 1 > fmax) {
  279. char * new_flags = malloc(fmax * 2);
  280. memcpy(new_flags, flags, flen);
  281. free(flags);
  282. fmax *= 2;
  283. flags = new_flags;
  284. }
  285. memcpy(flags + flen, cpu_flags[i], len);
  286. flen += len;
  287. flags[flen++] = ' ';
  288. }
  289. }
  290. flags[flen ? flen - 1 : 0] = 0;
  291. ci->cpu_flags = flags;
  292. }