db_main.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440
  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_freebsd_defs.h"
  23. #include "pal.h"
  24. #include "pal_internal.h"
  25. #include "pal_freebsd.h"
  26. #include "pal_debug.h"
  27. #include "pal_error.h"
  28. #include "pal_security.h"
  29. #include "api.h"
  30. #include <sys/mman.h>
  31. #include <fcntl.h>
  32. #include <errno.h>
  33. #include <elf/elf.h>
  34. #include <sysdeps/generic/ldsodefs.h>
  35. #include <sys/types.h>
  36. /* At the begining of entry point, rsp starts at argc, then argvs,
  37. envps and auxvs. Here we store rsp to rdi, so it will not be
  38. messed up by function calls */
  39. asm (".global pal_start \n"
  40. " .type pal_start,@function \n"
  41. "pal_start: \n "
  42. " movq %rsp, %rdi \n"
  43. " call pal_bsd_main@PLT \n");
  44. #define RTLD_BOOTSTRAP
  45. /* pal_start is the entry point of libpal.so, which calls pal_main */
  46. #define _ENTRY pal_start
  47. struct pal_bsd_state bsd_state;
  48. struct pal_sec pal_sec;
  49. static int pagesz = PRESET_PAGESIZE;
  50. static uid_t uid;
  51. static gid_t gid;
  52. static void pal_init_bootstrap (void * args, const char ** pal_name,
  53. int * pargc,
  54. const char *** pargv,
  55. const char *** penvp,
  56. ElfW(Addr) * baseaddr)
  57. {
  58. /*
  59. * fetch arguments and environment variables, the previous stack
  60. * pointer is in rdi (arg). The stack structure starting at rdi
  61. * will look like:
  62. * auxv[m - 1] = AT_NULL
  63. * ...
  64. * auxv[0]
  65. * envp[n - 1] = NULL
  66. * ...
  67. * envp[0]
  68. * argv[argc] = NULL
  69. * argv[argc - 1]
  70. * ...
  71. * argv[0]
  72. * argc
  73. * ---------------------------------------
  74. * user stack
  75. */
  76. const char ** all_args = (const char **) args;
  77. /* Workaround because sometimes BSD misaligns arguments on stack */
  78. if (all_args[0] == 0)
  79. all_args++;
  80. int argc = (uintptr_t) all_args[0];
  81. const char ** argv = &all_args[1];
  82. const char ** envp = argv + argc + 1;
  83. /* fetch environment information from aux vectors */
  84. void ** auxv = (void **) envp + 1;
  85. for (; *(auxv - 1); auxv++);
  86. ElfW(auxv_t) *av;
  87. ElfW(Addr) base = 0;
  88. for (av = (ElfW(auxv_t) *)auxv ; av->a_type != AT_NULL ; av++)
  89. switch (av->a_type) {
  90. case AT_PAGESZ:
  91. pagesz = av->a_un.a_val;
  92. break;
  93. case AT_UID:
  94. case AT_EUID:
  95. uid ^= av->a_un.a_val;
  96. break;
  97. case AT_GID:
  98. case AT_EGID:
  99. gid ^= av->a_un.a_val;
  100. break;
  101. case AT_BASE:
  102. base = (ElfW(Addr)) av->a_un.a_val;
  103. break;
  104. }
  105. *pal_name = argv[0];
  106. argv++;
  107. argc--;
  108. *pargc = argc;
  109. *pargv = argv;
  110. *penvp = envp;
  111. *baseaddr = base;
  112. }
  113. unsigned long _DkGetPagesize (void)
  114. {
  115. return pagesz;
  116. }
  117. unsigned long _DkGetAllocationAlignment (void)
  118. {
  119. return pagesz;
  120. }
  121. void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end)
  122. {
  123. void * end_addr, * start_addr;
  124. if ((void *) TEXT_START - (void *) USER_ADDRESS_LOWEST >
  125. (void *) USER_ADDRESS_HIGHEST - (void *) DATA_END){
  126. end_addr = (void *) ALLOC_ALIGNDOWN(TEXT_START);
  127. start_addr = pal_sec.user_addr_base ? :
  128. (void *) USER_ADDRESS_LOWEST;
  129. } else {
  130. end_addr = (void *) USER_ADDRESS_HIGHEST;
  131. start_addr = (void *) ALLOC_ALIGNUP(DATA_END);
  132. }
  133. assert(ALLOC_ALIGNED(start_addr) && ALLOC_ALIGNED(end_addr));
  134. while (1) {
  135. if (start_addr >= end_addr)
  136. init_fail(PAL_ERROR_NOMEM, "no user memory available");
  137. void * mem = (void *) ARCH_MMAP(start_addr,
  138. pal_state.alloc_align,
  139. PROT_NONE,
  140. MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE,
  141. -1, 0);
  142. if (!IS_ERR_P(mem)) {
  143. INLINE_SYSCALL(munmap, 2, mem, pal_state.alloc_align);
  144. if (mem == start_addr)
  145. break;
  146. }
  147. start_addr = (void *) ((unsigned long) start_addr << 1);
  148. }
  149. *end = (PAL_PTR) end_addr - USER_ADDRESS_RESERVED;
  150. *start = (PAL_PTR) start_addr;
  151. }
  152. PAL_NUM _DkGetProcessId (void)
  153. {
  154. return (bsd_state.start_time & (~0xffff)) | bsd_state.pid;
  155. }
  156. PAL_NUM _DkGetHostId (void)
  157. {
  158. return 0;
  159. }
  160. int create_domain_dir (void)
  161. {
  162. int ret = 0;
  163. const char * path;
  164. ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_PIPEDIR), 0777);
  165. if (IS_ERR(ret) && ERRNO(ret) != EEXIST) {
  166. if (ERRNO(ret) == ENOENT) {
  167. ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_TEMPDIR), 0777);
  168. if (!IS_ERR(ret)) {
  169. INLINE_SYSCALL(chmod, 2, GRAPHENE_TEMPDIR, 0777);
  170. ret = INLINE_SYSCALL(mkdir, 2, (path = GRAPHENE_PIPEDIR), 0777);
  171. }
  172. }
  173. if (IS_ERR(ret)) {
  174. printf("Cannot create directory %s, please check permission\n",
  175. path);
  176. return -PAL_ERROR_DENIED;
  177. }
  178. }
  179. if (!IS_ERR(ret))
  180. INLINE_SYSCALL(chmod, 2, GRAPHENE_PIPEDIR, 0777);
  181. char * pipedir = __alloca(sizeof(GRAPHENE_PIPEDIR) + 10);
  182. unsigned int id;
  183. do {
  184. if (!getrand(&id, sizeof(unsigned int))) {
  185. printf("Unable to generate random numbers\n");
  186. return -PAL_ERROR_DENIED;
  187. }
  188. snprintf(pipedir, sizeof(GRAPHENE_PIPEDIR) + 10,
  189. GRAPHENE_PIPEDIR "/%08x", id);
  190. ret = INLINE_SYSCALL(mkdir, 2, pipedir, 0700);
  191. if (IS_ERR(ret) && ERRNO(ret) != -EEXIST) {
  192. printf("Cannot create directory %s, please fix permission\n",
  193. pipedir);
  194. return -PAL_ERROR_DENIED;
  195. }
  196. } while (IS_ERR(ret));
  197. pal_sec.domain_id = id;
  198. return 0;
  199. }
  200. #include "dynamic_link.h"
  201. void setup_pal_map (struct link_map * map);
  202. static struct link_map pal_map;
  203. #ifdef __x86_64__
  204. # include "elf-x86_64.h"
  205. #endif
  206. void pal_bsd_main (void * args)
  207. {
  208. const char * pal_name = NULL;
  209. PAL_HANDLE parent = NULL, exec = NULL, manifest = NULL;
  210. const char ** argv, ** envp;
  211. int argc, ret;
  212. struct timeval time;
  213. INLINE_SYSCALL(gettimeofday, 2, &time, NULL);
  214. /* parse argc, argv, envp and auxv */
  215. pal_init_bootstrap(args, &pal_name, &argc, &argv, &envp, &pal_map.l_addr);
  216. pal_map.l_name = pal_name;
  217. elf_get_dynamic_info((void *) pal_map.l_addr + elf_machine_dynamic(),
  218. pal_map.l_info, pal_map.l_addr);
  219. ELF_DYNAMIC_RELOCATE(&pal_map);
  220. init_slab_mgr(pagesz);
  221. setup_pal_map(&pal_map);
  222. bsd_state.start_time = 1000000ULL * time.tv_sec + time.tv_usec;
  223. bsd_state.pid = INLINE_SYSCALL(getpid, 0);
  224. bsd_state.uid = uid;
  225. bsd_state.gid = gid;
  226. PAL_HANDLE first_thread = malloc(HANDLE_SIZE(thread));
  227. SET_HANDLE_TYPE(first_thread, thread);
  228. first_thread->thread.tid = bsd_state.pid;
  229. init_child_process(&parent, &exec, &manifest);
  230. if (parent)
  231. goto done_init;
  232. int fd = INLINE_SYSCALL(open, 3, argv[0], O_RDONLY|O_CLOEXEC, 0);
  233. if (IS_ERR(fd))
  234. goto done_init;
  235. int len = strlen(argv[0]);
  236. PAL_HANDLE file = malloc(HANDLE_SIZE(file) + len + 1);
  237. SET_HANDLE_TYPE(file, file);
  238. file->__in.flags |= RFD(0)|WFD(0)|WRITEABLE(0);
  239. file->file.fd = fd;
  240. char * path = (void *) file + HANDLE_SIZE(file);
  241. get_norm_path(argv[0], path, 0, len + 1);
  242. file->file.realpath = path;
  243. if (!check_elf_object(file)) {
  244. exec = file;
  245. goto done_init;
  246. }
  247. manifest = file;
  248. done_init:
  249. /* Create domain directory for pipes */
  250. if(!pal_sec.domain_id){
  251. if ((ret = create_domain_dir()) < 0)
  252. init_fail(-ret, "cannot create pipe directory");
  253. }
  254. signal_setup();
  255. /* jump to main function */
  256. pal_main(pal_sec.domain_id, (void *) pal_map.l_addr,
  257. pal_name, argc, argv, envp, parent, first_thread, exec, manifest);
  258. }
  259. /* the following code is borrowed from CPUID */
  260. #define WORD_EAX 0
  261. #define WORD_EBX 1
  262. #define WORD_ECX 2
  263. #define WORD_EDX 3
  264. #define WORD_NUM 4
  265. static void cpuid (int cpuid_fd, unsigned int reg,
  266. unsigned int words[], unsigned int ecx)
  267. {
  268. asm("cpuid"
  269. : "=a" (words[WORD_EAX]),
  270. "=b" (words[WORD_EBX]),
  271. "=c" (words[WORD_ECX]),
  272. "=d" (words[WORD_EDX])
  273. : "a" (reg),
  274. "c" (ecx));
  275. }
  276. #define FOUR_CHARS_VALUE(s, w) \
  277. (s)[0] = (w) & 0xff; \
  278. (s)[1] = ((w) >> 8) & 0xff; \
  279. (s)[2] = ((w) >> 16) & 0xff; \
  280. (s)[3] = ((w) >> 24) & 0xff;
  281. #define BPI 32
  282. #define POWER2(power) \
  283. (1ULL << (power))
  284. #define RIGHTMASK(width) \
  285. (((unsigned long) (width) >= BPI) ? ~0ULL : POWER2(width)-1ULL)
  286. #define BIT_EXTRACT_LE(value, start, after) \
  287. (((unsigned long) (value) & RIGHTMASK(after)) >> start)
  288. static char * cpu_flags[]
  289. = { "fpu", // "x87 FPU on chip"
  290. "vme", // "virtual-8086 mode enhancement"
  291. "de", // "debugging extensions"
  292. "pse", // "page size extensions"
  293. "tsc", // "time stamp counter"
  294. "msr", // "RDMSR and WRMSR support"
  295. "pae", // "physical address extensions"
  296. "mce", // "machine check exception"
  297. "cx8", // "CMPXCHG8B inst."
  298. "apic", // "APIC on chip"
  299. NULL,
  300. "sep", // "SYSENTER and SYSEXIT"
  301. "mtrr", // "memory type range registers"
  302. "pge", // "PTE global bit"
  303. "mca", // "machine check architecture"
  304. "cmov", // "conditional move/compare instruction"
  305. "pat", // "page attribute table"
  306. "pse36", // "page size extension"
  307. "pn", // "processor serial number"
  308. "clflush", // "CLFLUSH instruction"
  309. NULL,
  310. "dts" // "debug store"
  311. "tm", // "thermal monitor and clock ctrl"
  312. "mmx", // "MMX Technology"
  313. "fxsr", // "FXSAVE/FXRSTOR"
  314. "sse", // "SSE extensions"
  315. "sse2", // "SSE2 extensions"
  316. "ss", // "self snoop"
  317. "ht", // "hyper-threading / multi-core supported"
  318. "tm", // "therm. monitor"
  319. "ia64", // "IA64"
  320. "pbe", // "pending break event"
  321. };
  322. void _DkGetCPUInfo (PAL_CPU_INFO * ci)
  323. {
  324. unsigned int words[WORD_NUM];
  325. char * vendor_id = malloc(12);
  326. cpuid(2, 0, words, 0);
  327. FOUR_CHARS_VALUE(&vendor_id[0], words[WORD_EBX]);
  328. FOUR_CHARS_VALUE(&vendor_id[4], words[WORD_EDX]);
  329. FOUR_CHARS_VALUE(&vendor_id[8], words[WORD_ECX]);
  330. ci->cpu_vendor = vendor_id;
  331. char * brand = malloc(48);
  332. cpuid(-2, 0x80000002, words, 0);
  333. memcpy(&brand[ 0], words, sizeof(unsigned int) * WORD_NUM);
  334. cpuid(-2, 0x80000003, words, 0);
  335. memcpy(&brand[16], words, sizeof(unsigned int) * WORD_NUM);
  336. cpuid(-2, 0x80000004, words, 0);
  337. memcpy(&brand[32], words, sizeof(unsigned int) * WORD_NUM);
  338. ci->cpu_brand = brand;
  339. cpuid(2, 1, words, 0);
  340. ci->cpu_num = BIT_EXTRACT_LE(words[WORD_EBX], 16, 24);
  341. ci->cpu_family = BIT_EXTRACT_LE(words[WORD_EAX], 8, 12) + 1;
  342. ci->cpu_model = BIT_EXTRACT_LE(words[WORD_EAX], 4, 8);
  343. ci->cpu_stepping = BIT_EXTRACT_LE(words[WORD_EAX], 0, 4);
  344. int flen = 0, fmax = 80;
  345. char * flags = malloc(fmax);
  346. for (int i = 0 ; i < 32 ; i++) {
  347. if (!cpu_flags[i])
  348. break;
  349. if (BIT_EXTRACT_LE(words[WORD_EDX], i, i + 1)) {
  350. int len = strlen(cpu_flags[i]);
  351. if (flen + len + 1 > fmax) {
  352. char * new_flags = malloc(fmax * 2);
  353. memcpy(new_flags, flags, flen);
  354. free(flags);
  355. fmax *= 2;
  356. flags = new_flags;
  357. }
  358. memcpy(flags + flen, cpu_flags[i], len);
  359. flen += len;
  360. flags[flen++] = ' ';
  361. }
  362. }
  363. flags[flen ? flen - 1 : 0] = 0;
  364. ci->cpu_flags = flags;
  365. }