__libc_start_main.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include <elf.h>
  2. #include <poll.h>
  3. #include <fcntl.h>
  4. #include <signal.h>
  5. #include <unistd.h>
  6. #include "syscall.h"
  7. #include "atomic.h"
  8. #include "libc.h"
  9. static void dummy(void) {}
  10. weak_alias(dummy, _init);
  11. extern weak hidden void (*const __init_array_start)(void), (*const __init_array_end)(void);
  12. static void dummy1(void *p) {}
  13. weak_alias(dummy1, __init_ssp);
  14. #define AUX_CNT 38
  15. #ifdef __GNUC__
  16. __attribute__((__noinline__))
  17. #endif
  18. void __init_libc(char **envp, char *pn)
  19. {
  20. size_t i, *auxv, aux[AUX_CNT] = { 0 };
  21. __environ = envp;
  22. for (i=0; envp[i]; i++);
  23. libc.auxv = auxv = (void *)(envp+i+1);
  24. for (i=0; auxv[i]; i+=2) if (auxv[i]<AUX_CNT) aux[auxv[i]] = auxv[i+1];
  25. __hwcap = aux[AT_HWCAP];
  26. if (aux[AT_SYSINFO]) __sysinfo = aux[AT_SYSINFO];
  27. libc.page_size = aux[AT_PAGESZ];
  28. if (!pn) pn = (void*)aux[AT_EXECFN];
  29. if (!pn) pn = "";
  30. __progname = __progname_full = pn;
  31. for (i=0; pn[i]; i++) if (pn[i]=='/') __progname = pn+i+1;
  32. __init_tls(aux);
  33. __init_ssp((void *)aux[AT_RANDOM]);
  34. if (aux[AT_UID]==aux[AT_EUID] && aux[AT_GID]==aux[AT_EGID]
  35. && !aux[AT_SECURE]) return;
  36. struct pollfd pfd[3] = { {.fd=0}, {.fd=1}, {.fd=2} };
  37. int r =
  38. #ifdef SYS_poll
  39. __syscall(SYS_poll, pfd, 3, 0);
  40. #else
  41. __syscall(SYS_ppoll, pfd, 3, &(struct timespec){0}, 0, _NSIG/8);
  42. #endif
  43. if (r<0) a_crash();
  44. for (i=0; i<3; i++) if (pfd[i].revents&POLLNVAL)
  45. if (__sys_open("/dev/null", O_RDWR)<0)
  46. a_crash();
  47. libc.secure = 1;
  48. }
  49. static void libc_start_init(void)
  50. {
  51. _init();
  52. uintptr_t a = (uintptr_t)&__init_array_start;
  53. for (; a<(uintptr_t)&__init_array_end; a+=sizeof(void(*)()))
  54. (*(void (**)(void))a)();
  55. }
  56. weak_alias(libc_start_init, __libc_start_init);
  57. typedef int lsm2_fn(int (*)(int,char **,char **), int, char **);
  58. static lsm2_fn libc_start_main_stage2;
  59. int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv)
  60. {
  61. char **envp = argv+argc+1;
  62. /* External linkage, and explicit noinline attribute if available,
  63. * are used to prevent the stack frame used during init from
  64. * persisting for the entire process lifetime. */
  65. __init_libc(envp, argv[0]);
  66. /* Barrier against hoisting application code or anything using ssp
  67. * or thread pointer prior to its initialization above. */
  68. lsm2_fn *stage2 = libc_start_main_stage2;
  69. __asm__ ( "" : "+r"(stage2) : : "memory" );
  70. return stage2(main, argc, argv);
  71. }
  72. static int libc_start_main_stage2(int (*main)(int,char **,char **), int argc, char **argv)
  73. {
  74. char **envp = argv+argc+1;
  75. __libc_start_init();
  76. /* Pass control to the application */
  77. exit(main(argc, argv, envp));
  78. return 0;
  79. }