enclave_ecalls.c 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. #include "pal_linux.h"
  2. #include "pal_security.h"
  3. #include "pal_internal.h"
  4. #include <api.h>
  5. #include "ecall_types.h"
  6. #define SGX_CAST(type, item) ((type)(item))
  7. extern void * enclave_base, * enclave_top;
  8. static struct atomic_int enclave_start_called = ATOMIC_INIT(0);
  9. /*
  10. * Called from enclave_entry.S to execute ecalls.
  11. *
  12. * During normal operation handle_ecall will not return. The exception is that
  13. * it will return if invalid parameters are passed. In this case
  14. * enclave_entry.S will go into an endless loop since a clean return to urts is
  15. * not easy in all cases.
  16. *
  17. * Parameters:
  18. *
  19. * ecall_index:
  20. * Number of requested ecall. Untrusted.
  21. *
  22. * ecall_args:
  23. * Pointer to arguments for requested ecall. Untrusted.
  24. *
  25. * exit_target:
  26. * Address to return to after EEXIT. Untrusted.
  27. *
  28. * untrusted_stack:
  29. * Address to urts stack. Restored before EEXIT and used for ocall
  30. * arguments. Untrusted.
  31. *
  32. * enclave_base_addr:
  33. * Base address of enclave. Calculated dynamically in enclave_entry.S.
  34. * Trusted.
  35. */
  36. void handle_ecall (long ecall_index, void * ecall_args, void * exit_target,
  37. void * untrusted_stack, void * enclave_base_addr)
  38. {
  39. if (ecall_index < 0 || ecall_index >= ECALL_NR)
  40. return;
  41. if (!enclave_top) {
  42. enclave_base = enclave_base_addr;
  43. enclave_top = enclave_base_addr + GET_ENCLAVE_TLS(enclave_size);
  44. }
  45. SET_ENCLAVE_TLS(exit_target, exit_target);
  46. SET_ENCLAVE_TLS(ustack_top, untrusted_stack);
  47. SET_ENCLAVE_TLS(ustack, untrusted_stack);
  48. SET_ENCLAVE_TLS(clear_child_tid, NULL);
  49. if (atomic_cmpxchg(&enclave_start_called, 0, 1) == 0) {
  50. // ENCLAVE_START not yet called, so only valid ecall is ENCLAVE_START.
  51. if (ecall_index != ECALL_ENCLAVE_START) {
  52. // To keep things simple, we treat an invalid ecall_index like an
  53. // unsuccessful call to ENCLAVE_START.
  54. return;
  55. }
  56. ms_ecall_enclave_start_t * ms =
  57. (ms_ecall_enclave_start_t *) ecall_args;
  58. if (!ms || !sgx_is_completely_outside_enclave(ms, sizeof(*ms))) {
  59. return;
  60. }
  61. /* pal_linux_main is responsible to check the passed arguments */
  62. pal_linux_main(ms->ms_args, ms->ms_args_size,
  63. ms->ms_env, ms->ms_env_size,
  64. ms->ms_sec_info);
  65. } else {
  66. // ENCLAVE_START already called (maybe successfully, maybe not), so
  67. // only valid ecall is THREAD_START.
  68. if (ecall_index != ECALL_THREAD_START) {
  69. return;
  70. }
  71. // Only allow THREAD_START after successful enclave initialization.
  72. if (!(pal_enclave_state.enclave_flags & PAL_ENCLAVE_INITIALIZED)) {
  73. return;
  74. }
  75. pal_start_thread();
  76. }
  77. // pal_linux_main and pal_start_thread should never return.
  78. }