main.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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. #define _GNU_SOURCE 1
  4. #ifndef __GNUC__
  5. #define __GNUC__ 1
  6. #endif
  7. #include <linux/unistd.h>
  8. #include <asm/mman.h>
  9. #include <stdint.h>
  10. #include <stddef.h>
  11. #include <fcntl.h>
  12. #include <elf/elf.h>
  13. #include <sysdeps/generic/ldsodefs.h>
  14. #include <asm-errno.h>
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. #include "pal_security.h"
  18. #include "utils.h"
  19. struct pal_sec_info * pal_sec_info_addr = NULL;
  20. unsigned long pagesize = 4096;
  21. unsigned long pageshift = 4095;
  22. unsigned long pagemask = ~4095;
  23. #if __WORDSIZE == 2
  24. # define FILEBUF_SIZE 512
  25. #else
  26. # define FILEBUF_SIZE 832
  27. #endif
  28. char libname[80];
  29. const char * execname;
  30. char pipe_prefix[10];
  31. int find_manifest (int * pargc, const char *** pargv)
  32. {
  33. int argc = *pargc;
  34. const char ** argv = *pargv, * name = *argv;
  35. if (!argc)
  36. return -EINVAL;
  37. int fd = INLINE_SYSCALL(open, 2, name, O_RDONLY|O_CLOEXEC);
  38. if (IS_ERR(fd))
  39. return -ERRNO(fd);
  40. char filebuf[4];
  41. INLINE_SYSCALL(read, 3, fd, filebuf, 2);
  42. /* check if the first argument is a manifest, in case it is
  43. a runnable script. */
  44. if (!memcmp(filebuf, "#!", 2)) {
  45. char * path = __alloca(80);
  46. if (!path)
  47. return -ENOMEM;
  48. int bytes = INLINE_SYSCALL(read, 3, fd, path, 80);
  49. for (int i = 0 ; i < bytes ; i++)
  50. if (path[i] == ' ' || path[i] == '\n') {
  51. path[i] = 0;
  52. bytes = i;
  53. break;
  54. }
  55. memcpy(libname, path, bytes + 1);
  56. goto opened;
  57. }
  58. INLINE_SYSCALL(close, 1, fd);
  59. memcpy(libname, name, strlen(name) + 1);
  60. argc--;
  61. argv++;
  62. name = *argv;
  63. if (!argc)
  64. return -EINVAL;
  65. fd = INLINE_SYSCALL(open, 2, name, O_RDONLY|O_CLOEXEC);
  66. if (IS_ERR(fd))
  67. return -ERRNO(fd);
  68. /* check if the first argument is a executable. If it is, try finding
  69. all the possible manifest files */
  70. INLINE_SYSCALL(read, 3, fd, filebuf, 4);
  71. if (!memcmp(filebuf, "\177ELF", 4)) {
  72. int len = strlen(name);
  73. char * execpath = malloc(len + 1);
  74. fast_strcpy(execpath, name, len);
  75. execname = execpath;
  76. char * filename = __alloca(len + 10);
  77. fast_strcpy(filename, name, len);
  78. fast_strcpy(filename + len, ".manifest", 9);
  79. fd = INLINE_SYSCALL(open, 2, filename, O_RDONLY|O_CLOEXEC);
  80. if (!IS_ERR(fd))
  81. goto opened;
  82. fd = INLINE_SYSCALL(open, 2, "manifest", O_RDONLY|O_CLOEXEC);
  83. if (!IS_ERR(fd))
  84. goto opened;
  85. return -ENOENT;
  86. }
  87. opened:
  88. *pargc = argc;
  89. *pargv = argv;
  90. return fd;
  91. }
  92. int load_manifest (int fd, struct config_store * config)
  93. {
  94. int nbytes = INLINE_SYSCALL(lseek, 3, fd, 0, SEEK_END);
  95. if (IS_ERR(nbytes))
  96. return -ERRNO(nbytes);
  97. void * config_raw = (void *)
  98. INLINE_SYSCALL(mmap, 6, NULL, nbytes,
  99. PROT_READ|PROT_WRITE, MAP_PRIVATE,
  100. fd, 0);
  101. if (IS_ERR_P(config_raw))
  102. return -ERRNO_P(config_raw);
  103. config->raw_data = config_raw;
  104. config->raw_size = nbytes;
  105. config->malloc = malloc;
  106. config->free = NULL;
  107. const char * errstring = NULL;
  108. int ret = read_config(config, NULL, &errstring);
  109. if (ret < 0) {
  110. printf("can't read manifest: %s\n", errstring);
  111. return ret;
  112. }
  113. return 0;
  114. }
  115. static int do_relocate (ElfW(Dyn) * dyn, ElfW(Addr) addr)
  116. {
  117. ElfW(Dyn) * dt_rela = NULL;
  118. ElfW(Dyn) * dt_relacount = NULL;
  119. for ( ; dyn->d_tag != DT_NULL ; dyn++)
  120. switch (dyn->d_tag) {
  121. case DT_RELA: dt_rela = dyn; break;
  122. case DT_RELACOUNT: dt_relacount = dyn; break;
  123. }
  124. if (!dt_rela || !dt_relacount)
  125. return -EINVAL;
  126. ElfW(Rela) * r = (void *) (addr + dt_rela->d_un.d_ptr);
  127. ElfW(Rela) * end = r + dt_relacount->d_un.d_val;
  128. for ( ; r < end ; r++)
  129. *(ElfW(Addr) *) (addr + r->r_offset) = addr + r->r_addend;
  130. return 0;
  131. }
  132. static void get_pal_sec_info (const ElfW(Dyn) * dyn, ElfW(Addr) addr)
  133. {
  134. const ElfW(Dyn) * dt_symtab = NULL;
  135. const ElfW(Dyn) * dt_strtab = NULL;
  136. const ElfW(Dyn) * dt_rela = NULL;
  137. const ElfW(Dyn) * dt_relasz = NULL;
  138. const ElfW(Dyn) * dt_relacount = NULL;
  139. for ( ; dyn->d_tag != DT_NULL ; dyn++)
  140. switch (dyn->d_tag) {
  141. case DT_SYMTAB: dt_symtab = dyn; break;
  142. case DT_STRTAB: dt_strtab = dyn; break;
  143. case DT_RELA: dt_rela = dyn; break;
  144. case DT_RELASZ: dt_relasz = dyn; break;
  145. case DT_RELACOUNT: dt_relacount = dyn; break;
  146. }
  147. if (!dt_symtab || !dt_strtab || !dt_rela || !dt_relasz || !dt_relacount)
  148. return;
  149. ElfW(Sym) * symtab = (void *) (addr + dt_symtab->d_un.d_ptr);
  150. const char * strtab = (void *) (addr + dt_strtab->d_un.d_ptr);
  151. ElfW(Rela) * r = (void *) (addr + dt_rela->d_un.d_ptr);
  152. ElfW(Rela) * rel = r + dt_relacount->d_un.d_val;
  153. ElfW(Rela) * end = r + dt_relasz->d_un.d_val / sizeof(ElfW(Rela));
  154. for (r = rel ; r < end ; r++) {
  155. ElfW(Sym) * sym = &symtab[ELFW(R_SYM) (r->r_info)];
  156. if (!sym->st_name)
  157. continue;
  158. const char * name = strtab + sym->st_name;
  159. if (!memcmp(name, "pal_sec_info", 13))
  160. pal_sec_info_addr = (void *) addr + sym->st_value;
  161. }
  162. }
  163. static int load_static (const char * filename,
  164. unsigned long * entry, unsigned long * load_addr,
  165. unsigned long * text_start, unsigned long * text_end,
  166. unsigned long * phoff, int * phnum)
  167. {
  168. int ret = 0;
  169. int fd = INLINE_SYSCALL(open, 2, filename, O_RDONLY|O_CLOEXEC);
  170. if (IS_ERR(fd))
  171. return -ERRNO(fd);
  172. char filebuf[FILEBUF_SIZE];
  173. ret = INLINE_SYSCALL(read, 3, fd, filebuf, FILEBUF_SIZE);
  174. if (INTERNAL_SYSCALL_ERROR(ret))
  175. goto out;
  176. const ElfW(Ehdr) * header = (void *) filebuf;
  177. const ElfW(Phdr) * phdr = (void *) filebuf + header->e_phoff;
  178. const ElfW(Phdr) * ph;
  179. const ElfW(Dyn) * dyn = NULL;
  180. ElfW(Addr) base = 0;
  181. *text_start = (unsigned long) -1;
  182. *text_end = 0;
  183. *phoff = header->e_phoff;
  184. *phnum = header->e_phnum;
  185. struct loadcmd {
  186. ElfW(Addr) mapstart, mapend, dataend, allocend;
  187. off_t mapoff;
  188. int prot;
  189. } loadcmds[16], *c;
  190. int nloadcmds = 0;
  191. for (ph = phdr ; ph < &phdr[header->e_phnum] ; ph++)
  192. switch (ph->p_type) {
  193. case PT_DYNAMIC:
  194. dyn = (void *) ph->p_vaddr;
  195. break;
  196. case PT_LOAD:
  197. if (nloadcmds == 16) {
  198. ret = -EINVAL;
  199. goto out;
  200. }
  201. c = &loadcmds[nloadcmds++];
  202. c->mapstart = ph->p_vaddr & pagemask;
  203. c->mapend = (ph->p_vaddr + ph->p_filesz + pageshift) & pagemask;
  204. c->dataend = ph->p_vaddr + ph->p_filesz;
  205. c->allocend = ph->p_vaddr + ph->p_memsz;
  206. c->mapoff = ph->p_offset & pagemask;
  207. c->prot = (ph->p_flags & PF_R ? PROT_READ : 0) |
  208. (ph->p_flags & PF_W ? PROT_WRITE : 0) |
  209. (ph->p_flags & PF_X ? PROT_EXEC : 0);
  210. break;
  211. }
  212. c = loadcmds;
  213. int maplength = loadcmds[nloadcmds - 1].allocend - c->mapstart;
  214. ElfW(Addr) addr = INLINE_SYSCALL(mmap, 6, NULL, maplength, c->prot,
  215. MAP_PRIVATE | MAP_FILE, fd, c->mapoff);
  216. *load_addr = base = addr;
  217. dyn = (void *) (base + (ElfW(Addr)) dyn);
  218. goto postmap;
  219. for ( ; c < &loadcmds[nloadcmds] ; c++) {
  220. addr = INLINE_SYSCALL(mmap, 6, base + c->mapstart,
  221. c->mapend - c->mapstart, c->prot,
  222. MAP_PRIVATE | MAP_FILE | MAP_FIXED,
  223. fd, c->mapoff);
  224. postmap:
  225. if (IS_ERR_P(addr)) {
  226. ret = -ERRNO_P(addr);
  227. goto out;
  228. }
  229. if (c == loadcmds)
  230. INLINE_SYSCALL(munmap, 2, base + c->mapend,
  231. maplength - c->mapend);
  232. if (c->prot & PROT_EXEC) {
  233. if (base + c->mapstart < *text_start)
  234. *text_start = base + c->mapstart;
  235. if (base + c->mapend > *text_end)
  236. *text_end = base + c->mapend;
  237. }
  238. if (c->allocend > c->dataend) {
  239. ElfW(Addr) zero, zeroend, zeropage;
  240. zero = base + c->dataend;
  241. zeroend = (base + c->allocend + pageshift) & pagemask;
  242. zeropage = (zero + pageshift) & pagemask;
  243. if (zeroend < zeropage)
  244. zeropage = zeroend;
  245. if (zeropage > zero)
  246. memset((void *) zero, 0, zeropage - zero);
  247. if (zeroend > zeropage) {
  248. addr = INLINE_SYSCALL(mmap, 6,
  249. zeropage, zeroend - zeropage, c->prot,
  250. MAP_PRIVATE | MAP_ANON | MAP_FIXED,
  251. -1, 0);
  252. if (IS_ERR_P(addr)) {
  253. ret = -ERRNO_P(addr);
  254. goto out;
  255. }
  256. }
  257. }
  258. }
  259. get_pal_sec_info(dyn, base);
  260. *entry = base + header->e_entry;
  261. out:
  262. INLINE_SYSCALL(close, 1, fd);
  263. return ret;
  264. }
  265. void __attribute__((noinline)) ___dl_debug_state (void) {}
  266. extern __typeof(___dl_debug_state) _dl_debug_state
  267. __attribute ((alias ("___dl_debug_state")));
  268. struct link_map {
  269. ElfW(Addr) l_addr;
  270. const char * l_name;
  271. const ElfW(Dyn) * l_ld;
  272. struct link_map * l_next, * l_prev;
  273. };
  274. static struct link_map init_link_map;
  275. struct r_debug {
  276. int r_version;
  277. struct link_map * r_map;
  278. ElfW(Addr) r_brk;
  279. enum {
  280. RT_CONSISTENT,
  281. RT_ADD,
  282. RT_DELETE
  283. } r_state;
  284. ElfW(Addr) r_ldbase;
  285. };
  286. struct r_debug ___r_debug =
  287. { 1, NULL, (ElfW(Addr)) &___dl_debug_state, RT_CONSISTENT, 0 };
  288. extern __typeof(___r_debug) _r_debug
  289. __attribute ((alias ("___r_debug")));
  290. static void run_library (unsigned long entry, void * stack,
  291. int argc, const char ** argv)
  292. {
  293. *((void **) (stack -= sizeof(void *))) = NULL;
  294. for (int i = argc - 1 ; i >= 0 ; i--)
  295. *((const void **) (stack -= sizeof(void *))) = argv[i];
  296. *((unsigned long *) (stack -= sizeof(unsigned long))) = argc;
  297. asm volatile ("movq %0, %%rsp\r\n"
  298. "pushq %1\r\n"
  299. "retq\r\n"
  300. :: "r"(stack), "r"(entry) : "memory");
  301. }
  302. int install_syscall_filter (const char * lib_name, unsigned long lib_start,
  303. unsigned long lib_end, int trace);
  304. int install_initial_syscall_filter ();
  305. extern bool do_fork;
  306. extern bool do_trace;
  307. int init_child (int argc, const char ** argv, const char ** envp);
  308. int init_parent (pid_t child, int argc, const char ** argv, const char ** envp);
  309. int run_parent (pid_t child, int argc, const char ** argv, const char ** envp);
  310. void start(void);
  311. unsigned long pal_addr = 0;
  312. asm (".global start\r\n"
  313. " .type start,@function\r\n"
  314. ".global main\r\n"
  315. " .type do_main,@function\r\n");
  316. /* At the begining of entry point, rsp starts at argc, then argvs,
  317. envps and auxvs. Here we store rsp to rdi, so it will not be
  318. messed up by function calls */
  319. asm ("start:\r\n"
  320. " movq %rsp, %rdi\r\n"
  321. " call do_main\r\n");
  322. struct config_store root_config;
  323. int free_heaps (void);
  324. static int mcast_s (PAL_HANDLE handle, int port)
  325. {
  326. handle->mcast.srv = PAL_IDX_POISON;
  327. int ret = 0;
  328. int fd = INLINE_SYSCALL(socket, 3, AF_INET, SOCK_DGRAM, 0);
  329. if (IS_ERR(fd))
  330. return -ERRNO(fd);
  331. struct in_addr local;
  332. local.s_addr = INADDR_ANY;
  333. ret = INLINE_SYSCALL(setsockopt, 5, fd, IPPROTO_IP, IP_MULTICAST_IF,
  334. &local, sizeof(local));
  335. if (IS_ERR(ret))
  336. return -ERRNO(ret);
  337. handle->__in.flags |= WFD(1)|WRITEABLE(1);
  338. handle->mcast.srv = fd;
  339. return 0;
  340. }
  341. static int mcast_c (PAL_HANDLE handle, int port)
  342. {
  343. handle->mcast.cli = PAL_IDX_POISON;
  344. int ret = 0;
  345. int fd = INLINE_SYSCALL(socket, 3, AF_INET, SOCK_DGRAM, 0);
  346. if (IS_ERR(fd))
  347. return -ERRNO(fd);
  348. int reuse = 1;
  349. INLINE_SYSCALL(setsockopt, 5, fd, SOL_SOCKET, SO_REUSEADDR,
  350. &reuse, sizeof(reuse));
  351. struct sockaddr_in addr;
  352. addr.sin_family = AF_INET;
  353. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  354. addr.sin_port = htons(port);
  355. ret = INLINE_SYSCALL(bind, 3, fd, &addr, sizeof(addr));
  356. if (IS_ERR(ret))
  357. return -ERRNO(ret);
  358. struct in_addr local;
  359. local.s_addr = INADDR_ANY;
  360. ret = INLINE_SYSCALL(setsockopt, 5, fd, IPPROTO_IP, IP_MULTICAST_IF,
  361. &local, sizeof(local));
  362. if (IS_ERR(ret))
  363. return -ERRNO(ret);
  364. struct ip_mreq group;
  365. inet_pton(AF_INET, MCAST_GROUP, &group.imr_multiaddr.s_addr);
  366. group.imr_interface.s_addr = htonl(INADDR_ANY);
  367. ret = INLINE_SYSCALL(setsockopt, 5, fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
  368. &group, sizeof(group));
  369. if (IS_ERR(ret))
  370. return -ERRNO(ret);
  371. handle->__in.flags |= RFD(0);
  372. handle->mcast.cli = fd;
  373. handle->mcast.nonblocking = PAL_FALSE;
  374. return 0;
  375. }
  376. union pal_handle mcast_handle;
  377. void do_main (void * args)
  378. {
  379. void **all_args = (void **) args;
  380. int argc = (uintptr_t) all_args[0];
  381. const char **argv = (const char **) &all_args[1];
  382. const char **envp = argv + argc + 1;
  383. ElfW(Addr) addr = 0;
  384. void ** auxv = (void **) envp;
  385. ElfW(auxv_t) * av;
  386. char cfgbuf[CONFIG_MAX];
  387. int ret = 0;
  388. while (*(auxv++));
  389. /* VERY IMPORTANT: This is the filter that gets applied to the startup code
  390. * before applying the real filter in the function install_syscall_filter. If
  391. * you face any issues, you may have to enable certain syscalls here to
  392. * successfully make changes to startup code.
  393. */
  394. ret = install_initial_syscall_filter();
  395. if (ret < 0) {
  396. printf("Unable to install initial system call filter\n");
  397. goto exit;
  398. }
  399. for (av = (void *) auxv ; av->a_type != AT_NULL ; av++)
  400. switch (av->a_type) {
  401. case AT_BASE:
  402. addr = (ElfW(Addr)) av->a_un.a_val;
  403. break;
  404. }
  405. if (!addr) {
  406. asm ("leaq start(%%rip), %0\r\n"
  407. "subq 1f(%%rip), %0\r\n"
  408. ".section\t.data.rel.ro\r\n"
  409. "1:\t.quad start\r\n"
  410. ".previous\r\n"
  411. : "=r" (addr) : : "cc");
  412. }
  413. ElfW(Dyn) * dyn = (ElfW(Dyn) *) (addr + (ElfW(Addr)) &_DYNAMIC);
  414. do_relocate(dyn, addr);
  415. init_link_map.l_addr = addr;
  416. init_link_map.l_ld = dyn;
  417. init_link_map.l_name = libname;
  418. ___r_debug.r_map = &init_link_map;
  419. ___r_debug.r_ldbase = addr;
  420. int manifest;
  421. if (!argc || (manifest = find_manifest(&argc, &argv)) < 0) {
  422. printf("USAGE: %s [executable|manifest] args ...\n", libname);
  423. goto exit;
  424. }
  425. ret = load_manifest(manifest, &root_config);
  426. if (ret < 0)
  427. goto exit;
  428. if (!execname) {
  429. if (get_config(&root_config, "loader.exec", cfgbuf, CONFIG_MAX) > 0
  430. && is_file_uri(cfgbuf))
  431. execname = file_uri_to_path(cfgbuf, strlen(cfgbuf));
  432. }
  433. pid_t pid = 0;
  434. if (do_fork && (pid = INLINE_SYSCALL(fork, 0)) > 0) {
  435. ret = run_parent(pid, argc, argv, envp);
  436. goto exit;
  437. }
  438. if (IS_ERR(pid)) {
  439. ret = -ERRNO(pid);
  440. goto exit;
  441. }
  442. unsigned long pal_entry = 0;
  443. unsigned long pal_start = 0;
  444. unsigned long pal_end = 0;
  445. unsigned long pal_phoff = 0;
  446. int pal_phnum = 0;
  447. ret = load_static(PAL_LOADER, &pal_entry, &pal_addr, &pal_start, &pal_end,
  448. &pal_phoff, &pal_phnum);
  449. if (ret < 0) {
  450. printf("Unable to load PAL loader\n");
  451. goto exit;
  452. }
  453. if (!pal_sec_info_addr)
  454. goto exit;
  455. int rand = INLINE_SYSCALL(open, 2, "/dev/urandom", O_RDONLY);
  456. if (IS_ERR(rand)) {
  457. ret = -ERRNO(rand);
  458. goto exit;
  459. }
  460. ret = INLINE_SYSCALL(mkdir, 2, GRAPHENE_PIPEDIR, 0777);
  461. if (IS_ERR(ret) && ERRNO(ret) != EEXIST) {
  462. if (ERRNO(ret) == ENOENT) {
  463. ret = INLINE_SYSCALL(mkdir, 2, GRAPHENE_TMPDIR, 0777);
  464. if (!IS_ERR(ret)) {
  465. INLINE_SYSCALL(chmod, 2, GRAPHENE_TMPDIR, 0777);
  466. ret = INLINE_SYSCALL(mkdir, 2, GRAPHENE_PIPEDIR, 0777);
  467. }
  468. }
  469. if (IS_ERR(ret))
  470. goto exit;
  471. }
  472. if (!IS_ERR(ret))
  473. INLINE_SYSCALL(chmod, 2, GRAPHENE_PIPEDIR, 0777);
  474. unsigned int domainid = 0;
  475. char * tmpdir = __alloca(GRAPHENE_PIPEDIR_LEN + 12);
  476. memcpy(tmpdir, GRAPHENE_PIPEDIR, GRAPHENE_PIPEDIR_LEN + 1);
  477. while (!domainid) {
  478. ret = INLINE_SYSCALL(read, 3, rand, &domainid,
  479. sizeof(unsigned int));
  480. if (IS_ERR(ret)) {
  481. ret = -ERRNO(ret);
  482. goto exit;
  483. }
  484. if (domainid) {
  485. snprintf(tmpdir + GRAPHENE_PIPEDIR_LEN, 12, "/%08x", domainid);
  486. ret = INLINE_SYSCALL(mkdir, 2, tmpdir, 0700);
  487. if (IS_ERR(ret)) {
  488. if ((ret = -ERRNO(ret)) != -EEXIST)
  489. goto exit;
  490. domainid = 0;
  491. }
  492. }
  493. }
  494. snprintf(pipe_prefix, sizeof(pipe_prefix), "%08x", domainid);
  495. unsigned short mcast_port = 0;
  496. do {
  497. ret = INLINE_SYSCALL(read, 3, rand, &mcast_port,
  498. sizeof(unsigned short));
  499. if (IS_ERR(ret)) {
  500. ret = -ERRNO(ret);
  501. goto exit;
  502. }
  503. } while (mcast_port < 1024);
  504. SET_HANDLE_TYPE(&mcast_handle, mcast);
  505. mcast_s(&mcast_handle, mcast_port);
  506. mcast_c(&mcast_handle, mcast_port);
  507. mcast_handle.mcast.port = mcast_port;
  508. pal_sec_info_addr->domain_id = domainid;
  509. pal_sec_info_addr->pipe_prefix = pipe_prefix;
  510. pal_sec_info_addr->rand_gen = rand;
  511. pal_sec_info_addr->mcast_port = mcast_port;
  512. pal_sec_info_addr->mcast_handle = &mcast_handle;
  513. pal_sec_info_addr->_dl_debug_state = &___dl_debug_state;
  514. pal_sec_info_addr->_r_debug = &___r_debug;
  515. ret = init_child(argc, argv, envp);
  516. if (ret < 0)
  517. goto exit;
  518. free_heaps();
  519. ret = install_syscall_filter(libname, pal_start, pal_end, do_trace);
  520. if (ret < 0) {
  521. printf("Unable to install system call filter\n");
  522. goto exit;
  523. }
  524. /* after installing syscall, you can't execute any system call */
  525. for (av = (void *) auxv ; av->a_type != AT_NULL ; av++)
  526. switch (av->a_type) {
  527. case AT_ENTRY:
  528. av->a_un.a_val = pal_entry;
  529. break;
  530. case AT_BASE:
  531. av->a_un.a_val = pal_start;
  532. break;
  533. case AT_PHDR:
  534. av->a_un.a_val = pal_start + pal_phoff;
  535. break;
  536. case AT_PHNUM:
  537. av->a_un.a_val = pal_phnum;
  538. break;
  539. }
  540. run_library(pal_entry, envp, argc, argv);
  541. exit:
  542. INLINE_SYSCALL(exit_group, 1, ret);
  543. }