db_main.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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 OSCAR lab, 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 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 General Public License for more details.
  13. You should have received a copy of the GNU 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.h"
  23. #include "pal_internal.h"
  24. #include "pal_security.h"
  25. #include "pal_debug.h"
  26. #include "pal_error.h"
  27. #include "api.h"
  28. #include <sysdeps/generic/ldsodefs.h>
  29. #include <elf/elf.h>
  30. #include <bits/dlfcn.h>
  31. /* allocate memory for page size constants */
  32. PAL_NUM allocsize, allocshift, allocmask;
  33. PAL_CONTROL __pal_control;
  34. PAL_CONTROL * pal_control_addr (void)
  35. {
  36. return &__pal_control;
  37. }
  38. /* initialize the value of pal_config attributes */
  39. struct pal_config pal_config;
  40. struct pal_sec_info pal_sec_info;
  41. #define leave \
  42. do { printf("PAL terminated at " __FILE__ ":%d\n", __LINE__); \
  43. _DkProcessExit(1); } while (0)
  44. int load_libraries (struct config_store * root_config, const char ** msg)
  45. {
  46. /* we will not make any assumption for where the libraries are loaded */
  47. char cfgbuf[CONFIG_MAX];
  48. int len, ret = 0;
  49. /* loader.preload: any other libraries to preload. The can be multiple
  50. URIs, seperated by commas */
  51. if ((len = get_config(root_config, "loader.preload", cfgbuf,
  52. CONFIG_MAX)) > 0) {
  53. char * c = cfgbuf, * token = c;
  54. do {
  55. if (*c == ',' || !(*(c))) {
  56. if (c > token) {
  57. *c = 0;
  58. if ((ret = load_elf_object(token, OBJECT_PRELOAD)) < 0) {
  59. if (msg)
  60. *msg = "Unable to load preload library\n";
  61. return ret;
  62. }
  63. }
  64. token = c + 1;
  65. }
  66. } while (*(c++));
  67. }
  68. return 0;
  69. }
  70. static void read_envs (const char ** envp)
  71. {
  72. if (!pal_config.root_config)
  73. goto done;
  74. char cfgbuf[CONFIG_MAX];
  75. /* loader.env.* and loader.exclude.env: filtering host environment
  76. * variables */
  77. int nenvs = get_config_entries(pal_config.root_config, "loader.env", cfgbuf,
  78. CONFIG_MAX);
  79. if (nenvs > 0) {
  80. struct env { const char * str; int len, idx; } * envs
  81. = __alloca(sizeof(struct env) * nenvs);
  82. char * cfg = cfgbuf;
  83. for (int i = 0 ; i < nenvs ; i++) {
  84. int len = strlen(cfg);
  85. char * str = __alloca(len + 1);
  86. envs[i].str = str;
  87. envs[i].len = len;
  88. envs[i].idx = -1;
  89. memcpy(str, cfg, len + 1);
  90. cfg += len + 1;
  91. }
  92. int envc = 0, add = nenvs;
  93. for (const char ** e = envp ; *e ; e++) {
  94. envc++;
  95. const char * p = *e;
  96. while (*p && *p != '=')
  97. p++;
  98. for (int i = 0 ; i < nenvs ; i++)
  99. if (envs[i].len == p - *e && !memcmp(envs[i].str, *e, p - *e)) {
  100. envs[i].idx = envc - 1;
  101. add--;
  102. break;
  103. }
  104. }
  105. if (add) {
  106. const char ** new_envp =
  107. malloc(sizeof(const char *) * (envc + add + 1));
  108. memcpy(new_envp, envp, sizeof(const char *) * envc);
  109. envp = new_envp;
  110. envp[envc + add] = NULL;
  111. }
  112. char key[CONFIG_MAX] = "loader.env.";
  113. const char ** ptr;
  114. for (int i = 0 ; i < nenvs ; i++) {
  115. const char * str = envs[i].str;
  116. int len = envs[i].len;
  117. int idx = envs[i].idx;
  118. int bytes;
  119. ptr = &envp[(idx == -1) ? envc++ : idx];
  120. memcpy(key + 11, str, len + 1);
  121. if ((bytes = get_config(pal_config.root_config, key, cfgbuf,
  122. CONFIG_MAX)) > 0) {
  123. char * e = malloc(len + bytes + 2);
  124. memcpy(e, str, len);
  125. e[len] = '=';
  126. memcpy(e + len + 1, cfgbuf, bytes + 1);
  127. *ptr = e;
  128. } else {
  129. char * e = malloc(len + 2);
  130. memcpy(e, str, len);
  131. e[len] = '=';
  132. e[len + 1] = 0;
  133. *ptr = e;
  134. }
  135. }
  136. }
  137. done:
  138. pal_config.environments = envp;
  139. }
  140. static void * find_heap_base (void)
  141. {
  142. /* This function is to allocate an area to map preloaded loibraries,
  143. but try to get around future address of PAL caused by ASLR.
  144. The top of heap must be at least 1/16 of the area below where PAL
  145. is loaded. The address is still randomized. */
  146. unsigned long heap_base = (unsigned long) pal_config.lib_text_start;
  147. unsigned long pal_size = pal_config.lib_data_end -
  148. pal_config.lib_text_start;
  149. unsigned long base = allocsize;
  150. while ((base >> 12) < pal_size)
  151. base <<= 1;
  152. while ((base << 6) < heap_base)
  153. base <<= 1;
  154. heap_base &= allocmask;
  155. while ((heap_base -= base) > base) {
  156. void * heap = (void *) heap_base;
  157. if (!_DkVirtualMemoryAlloc(&heap, allocsize, PAL_ALLOC_RESERVE,
  158. PAL_PROT_NONE))
  159. return heap;
  160. }
  161. return NULL;
  162. }
  163. void start_execution (int argc, const char ** argv);
  164. void pal_main (int argc, const char ** argv, const char ** envp)
  165. {
  166. char cfgbuf[CONFIG_MAX];
  167. int ret;
  168. pal_config.pagesize = _DkGetPagesize();
  169. pal_config.alloc_align = _DkGetAllocationAlignment();
  170. /* some constants for page manipulation and allocation alignment */
  171. allocsize = pal_config.alloc_align;
  172. allocshift = allocsize - 1;
  173. allocmask = ~allocshift;
  174. init_slab_mgr();
  175. /* reloaction of loader is done here. starting from this point, the global
  176. symbols of loader should be accessible. */
  177. pal_config.lib_text_start = (void *) &text_start;
  178. pal_config.lib_text_end = (void *) &text_end;
  179. pal_config.lib_data_start = (void *) &data_start;
  180. pal_config.lib_data_end = (void *) &data_end;
  181. __pal_control.pagesize = pal_config.pagesize;
  182. __pal_control.alloc_align = allocsize;
  183. __pal_control.library_begin = &text_start;
  184. __pal_control.library_end = &data_end;
  185. /*
  186. * _DkInitHost must set up the following values:
  187. * pal_config.manifest
  188. * pal_config.manifest_handle
  189. * pal_config.exec
  190. * pal_config.exec_handle
  191. * pal_config.root_config
  192. */
  193. if (_DkInitHost(&argc, &argv) < 0)
  194. leave;
  195. __pal_control.manifest_handle = pal_config.manifest_handle;
  196. __pal_control.executable = pal_config.exec;
  197. /* all of the preloaded libraries are loaded,
  198. time to play with executable */
  199. if (pal_config.exec_handle) {
  200. ret = load_elf_object_by_handle(pal_config.exec_handle, OBJECT_EXEC);
  201. if (ret < 0) {
  202. printf("Unable to load executable (%d)\n", PAL_STRERROR(ret));
  203. leave;
  204. }
  205. }
  206. read_envs(envp);
  207. if (!pal_config.heap_base)
  208. pal_config.heap_base = find_heap_base();
  209. if (pal_config.root_config) {
  210. struct config_store * cfg = pal_config.root_config;
  211. const char * msg;
  212. if (load_libraries(cfg, &msg) < 0) {
  213. printf("%s\n", msg);
  214. leave;
  215. }
  216. if (get_config(cfg, "loader.daemonize", cfgbuf,
  217. CONFIG_MAX) > 0 &&
  218. cfgbuf[0] == '1' && !cfgbuf[1])
  219. pal_config.daemonize = true;
  220. if (get_config(cfg, "loader.debug_type", cfgbuf,
  221. CONFIG_MAX) > 0) {
  222. PAL_HANDLE handle = NULL;
  223. if (!memcmp(cfgbuf, "inline", 7)) {
  224. _DkStreamOpen(&handle, "dev:tty", PAL_ACCESS_RDWR, 0, 0, 0);
  225. } else if (!memcmp(cfgbuf, "file", 5)) {
  226. if (get_config(cfg, "loader.debug_file", cfgbuf,
  227. CONFIG_MAX) > 0) {
  228. _DkStreamOpen(&handle, cfgbuf, PAL_ACCESS_RDWR,
  229. PAL_SHARE_OWNER_R|PAL_SHARE_OWNER_W,
  230. PAL_CREAT_TRY, 0);
  231. }
  232. }
  233. __pal_control.debug_stream = handle;
  234. }
  235. if ((ret = get_config(cfg, "loader.syscall_symbol", cfgbuf,
  236. CONFIG_MAX)) > 0)
  237. pal_config.syscall_sym_name = remalloc(cfgbuf, ret + 1);
  238. free_config(cfg);
  239. _DkStreamUnmap(cfg->raw_data, ALLOC_ALIGNUP(cfg->raw_size));
  240. free(cfg);
  241. pal_config.root_config = NULL;
  242. }
  243. __pal_control.manifest_handle = pal_config.manifest_handle;
  244. __pal_control.executable = pal_config.exec;
  245. /* Now we will start the execution */
  246. start_execution(argc, argv);
  247. /* We wish we will never reached here */
  248. printf("unexpected termination\n");
  249. leave;
  250. }