-
Notifications
You must be signed in to change notification settings - Fork 193
/
pal_tcb.h
134 lines (116 loc) · 5.77 KB
/
pal_tcb.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#pragma once
#include <stdatomic.h>
#include <stdbool.h>
#include <stdint.h>
#include "pal.h"
#include "sgx_arch.h"
struct untrusted_area {
void* addr;
size_t size;
uint64_t in_use; /* must be uint64_t, because SET_ENCLAVE_TCB() currently supports only 8-byte
* types. TODO: fix this. */
bool valid;
};
struct aex_notify_entropy {
uint32_t entropy_cache;
int32_t count;
};
typedef struct aex_notify_entropy aex_notify_entropy_t;
/*
* Beside the classic thread control block (like ustack, thread, etc.) the TCB area is also used to
* pass parameters needed during enclave or thread initialization. Some of them are thread specific
* (like tcs_offset) and some of them are identical for all threads (like enclave_size).
*/
struct pal_enclave_tcb {
PAL_TCB common;
/* private to Linux-SGX PAL */
uint64_t enclave_size;
uint64_t tcs_offset;
uint64_t initial_stack_addr;
uint64_t tmp_rip;
uint64_t sig_stack_low;
uint64_t sig_stack_high;
void* ecall_return_addr;
void* ssa;
sgx_pal_gpr_t* gpr;
void* exit_target;
uintptr_t fsbase;
void* pre_ocall_stack;
void* ustack_top;
void* ustack;
struct pal_handle_thread* thread;
uint64_t ocall_exit_called;
uint64_t thread_started;
uint64_t ready_for_exceptions;
uint64_t manifest_size;
void* heap_min;
void* heap_max;
int* clear_child_tid;
struct untrusted_area untrusted_area_cache;
/* below fields are used by AEX Notify */
uint64_t ready_for_aex_notify; /* Set when it is ready to enable aex-notify*/
uint64_t aex_notify_flag; /* Used to indicate whether we need to handle aex-notify across enclave boundary*/
uint64_t aex_counter; /* Counter for AEXs*/
aex_notify_entropy_t entropy; /* An entropy used in aex-notify mitigation*/
};
#ifndef DEBUG
extern uint64_t dummy_debug_variable;
#endif
#ifdef IN_ENCLAVE
static inline struct pal_enclave_tcb* pal_get_enclave_tcb(void) {
return (struct pal_enclave_tcb*)pal_get_tcb();
}
#define GET_ENCLAVE_TCB(member) \
({ \
struct pal_enclave_tcb* tmp; \
uint64_t val; \
static_assert(sizeof(tmp->member) == 8, "pal_enclave_tcb member should have 8-byte type"); \
__asm__("movq %%gs:%c1, %0" \
: "=r"(val) \
: "i"(offsetof(struct pal_enclave_tcb, member)) \
: "memory"); \
(__typeof(tmp->member))val; \
})
#define SET_ENCLAVE_TCB(member, value) \
do { \
struct pal_enclave_tcb* tmp; \
static_assert(sizeof(tmp->member) == 8, "pal_enclave_tcb member should have 8-byte type"); \
static_assert(sizeof(value) == 8, "only 8-byte type can be set to pal_enclave_tcb"); \
__asm__("movq %0, %%gs:%c1" \
: \
: "ir"(value), "i"(offsetof(struct pal_enclave_tcb, member)) \
: "memory"); \
} while (0)
__attribute_no_stack_protector
static inline void pal_set_tcb_stack_canary(uint64_t canary) {
((char*)&canary)[0] = 0; /* prevent C-string-based stack leaks from exposing the cookie */
SET_ENCLAVE_TCB(common.stack_protector_canary, canary);
}
#else /* IN_ENCLAVE */
/* private to untrusted Linux PAL, unique to each untrusted thread */
typedef struct pal_host_tcb {
struct pal_host_tcb* self;
sgx_arch_tcs_t* tcs; /* TCS page of SGX corresponding to thread, for EENTER */
void* stack; /* bottom of stack, for later freeing when thread exits */
void* alt_stack; /* bottom of alt stack, for child thread to init alt stack */
uint8_t is_in_aex_profiling; /* non-zero if thread is currently doing AEX profiling */
atomic_ulong eenter_cnt; /* # of EENTERs, corresponds to # of ECALLs */
atomic_ulong eexit_cnt; /* # of EEXITs, corresponds to # of OCALLs */
atomic_ulong aex_cnt; /* # of AEXs, corresponds to # of interrupts/signals */
atomic_ulong sync_signal_cnt; /* # of sync signals, corresponds to # of SIGSEGV/SIGILL/.. */
atomic_ulong async_signal_cnt; /* # of async signals, corresponds to # of SIGINT/SIGCONT/.. */
uint64_t profile_sample_time; /* last time sgx_profile_sample() recorded a sample */
int32_t last_async_event; /* last async signal, reported to the enclave on ocall return */
} PAL_HOST_TCB;
extern void pal_host_tcb_init(PAL_HOST_TCB* tcb, void* stack, void* alt_stack);
static inline PAL_HOST_TCB* pal_get_host_tcb(void) {
PAL_HOST_TCB* tcb;
__asm__("movq %%gs:%c1, %0\n"
: "=r"(tcb)
: "i"(offsetof(PAL_HOST_TCB, self))
: "memory");
return tcb;
}
extern bool g_sgx_enable_stats;
void update_and_print_stats(bool process_wide);
#endif /* IN_ENCLAVE */