global_init.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (C) 2011-2018 Intel Corporation. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * * Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * * Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in
  12. * the documentation and/or other materials provided with the
  13. * distribution.
  14. * * Neither the name of Intel Corporation nor the names of its
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. */
  31. #include "internal/global_init.h"
  32. #include "linux/elf_parser.h"
  33. #include "sgx_spinlock.h"
  34. #include "global_data.h"
  35. #include "internal/util.h"
  36. #include "thread_data.h"
  37. #include "sgx_trts.h"
  38. #include <assert.h>
  39. #include <stdlib.h>
  40. typedef void (*cxa_function_t)(void *para);
  41. typedef struct _exit_function_t
  42. {
  43. struct
  44. {
  45. uintptr_t fun;
  46. uintptr_t para;
  47. void *dso_handle;
  48. } cxa;
  49. struct _exit_function_t *next;
  50. } exit_function_t;
  51. static exit_function_t *g_exit_function = NULL;
  52. static sgx_spinlock_t g_exit_function_lock = SGX_SPINLOCK_INITIALIZER;
  53. static uintptr_t g_exit_function_cookie = 0;
  54. #define ENC_CXA_FUNC_POINTER(x) (uintptr_t)(x) ^ g_exit_function_cookie
  55. #define DEC_CXA_FUNC_POINTER(x) (cxa_function_t)((x) ^ g_exit_function_cookie)
  56. #define ENC_CXA_PARA_POINTER(x) (uintptr_t)(x) ^ g_exit_function_cookie
  57. #define DEC_CXA_PARA_POINTER(x) (void *)((x) ^ g_exit_function_cookie)
  58. typedef void (*fp_t)(void);
  59. /* required by global constructor when -fuse-cxa-atexit is enabled */
  60. void *__dso_handle __attribute__((weak)) = &(__dso_handle);
  61. int __cxa_atexit(void (*fun)(void *), void *para, void *dso)
  62. {
  63. if(unlikely(g_exit_function_cookie == 0))
  64. {
  65. uintptr_t rand = 0;
  66. do
  67. {
  68. if(SGX_SUCCESS != sgx_read_rand((unsigned char *)&rand, sizeof(rand)))
  69. {
  70. return -1;
  71. }
  72. } while(rand == 0);
  73. sgx_spin_lock(&g_exit_function_lock);
  74. if(g_exit_function_cookie == 0)
  75. {
  76. g_exit_function_cookie = rand;
  77. }
  78. sgx_spin_unlock(&g_exit_function_lock);
  79. }
  80. if(!sgx_is_within_enclave(fun, 0))
  81. {
  82. return -1;
  83. }
  84. exit_function_t *exit_function = (exit_function_t *)malloc(sizeof(exit_function_t));
  85. if(!exit_function)
  86. {
  87. return -1;
  88. }
  89. exit_function->cxa.fun = ENC_CXA_FUNC_POINTER(fun);
  90. exit_function->cxa.para = ENC_CXA_PARA_POINTER(para);
  91. exit_function->cxa.dso_handle = dso;
  92. sgx_spin_lock(&g_exit_function_lock);
  93. exit_function->next = g_exit_function;
  94. g_exit_function = exit_function;
  95. sgx_spin_unlock(&g_exit_function_lock);
  96. return 0;
  97. }
  98. int atexit(void (*fun)(void))
  99. {
  100. return __cxa_atexit((void (*)(void *))fun, NULL, __dso_handle);
  101. }
  102. static void do_atexit_aux(void)
  103. {
  104. sgx_spin_lock(&g_exit_function_lock);
  105. exit_function_t *exit_function = g_exit_function;
  106. g_exit_function = NULL;
  107. sgx_spin_unlock(&g_exit_function_lock);
  108. while (exit_function != NULL)
  109. {
  110. cxa_function_t cxa_func = DEC_CXA_FUNC_POINTER(exit_function->cxa.fun);
  111. void *para = DEC_CXA_PARA_POINTER(exit_function->cxa.para);
  112. cxa_func(para);
  113. exit_function_t *tmp = exit_function;
  114. exit_function = exit_function->next;
  115. free(tmp);
  116. }
  117. }
  118. /* auxiliary routines */
  119. static void do_ctors_aux(void)
  120. {
  121. /* SGX RTS does not support .ctors currently */
  122. fp_t *p = NULL;
  123. uintptr_t init_array_addr = 0;
  124. size_t init_array_size = 0;
  125. const void *enclave_start = (const void*)&__ImageBase;
  126. if (0 != elf_get_init_array(enclave_start, &init_array_addr, &init_array_size)|| init_array_addr == 0 || init_array_size == 0)
  127. return;
  128. fp_t *fp_start = (fp_t*)(init_array_addr + (uintptr_t)(enclave_start));
  129. fp_t *fp_end = fp_start + (init_array_size / sizeof(fp_t));
  130. /* traverse .init_array in forward order */
  131. for (p = fp_start; p < fp_end; p++)
  132. {
  133. (*p)();
  134. }
  135. }
  136. /* auxiliary routines */
  137. static void do_dtors_aux(void)
  138. {
  139. fp_t *p = NULL;
  140. uintptr_t uninit_array_addr;
  141. size_t uninit_array_size;
  142. const void *enclave_start = (const void*)&__ImageBase;
  143. elf_get_uninit_array(enclave_start, &uninit_array_addr, &uninit_array_size);
  144. if (uninit_array_addr == 0 || uninit_array_size == 0)
  145. return;
  146. fp_t *fp_start = (fp_t*)(uninit_array_addr + (uintptr_t)(enclave_start));
  147. fp_t *fp_end = fp_start + (uninit_array_size / sizeof(fp_t));
  148. /* traverse .fini_array in reverse order */
  149. for (p = fp_end - 1; p >= fp_start; p--)
  150. {
  151. (*p)();
  152. }
  153. }
  154. void init_global_object(void)
  155. {
  156. do_ctors_aux();
  157. }
  158. void uninit_global_object(void)
  159. {
  160. do_atexit_aux();
  161. do_dtors_aux();
  162. }