Leaking Uninitialized Secure Enclave Memory via Structure Padding (Extended Abstract)
aa r X i v : . [ c s . CR ] O c t Leaking Uninitialized Secure Enclave Memory via Structure Padding(Extended Abstract)
Sangho Lee Taesoo Kim
Georgia Institute of Technology
Abstract
Intel Software Guard Extensions (SGX) aims to pro-vide an isolated execution environment, known as anenclave, for a user-level process to maximize its con-fidentiality and integrity. In this paper, we study howuninitialized data inside a secure enclave can be leakedvia structure padding. We found that, during
ECALL and
OCALL , proxy functions that are automatically generatedby the Intel SGX Software Development Kit (SDK)fully copy structure variables from an enclave to thenormal memory to return the result of an
ECALL functionand to pass input parameters to an
OCALL function. If thestructure variables contain padding bytes, uninitializedenclave memory, which might contain confidential datalike a private key, can be copied to the normal memorythrough the padding bytes. We also consider potentialcountermeasures against these security threats.
Intel Software Guard Extensions (SGX) is a hardware-based trusted execution environment (TEE) technologythat allows a user-level process to have an isolated exe-cution environment, known as an enclave . Even systemsoftware, such as operating system and hypervisor, can-not access enclave memory, known as the enclave pagecache (EPC), because Intel processor’s memory man-agement unit (MMU) prohibits such attempts at hard-ware level. Further, physical attacks, such as a cold-boot attack, are not possible because every data storedin EPC banks is encrypted by the memory encryptionengine (MEE) before it leaves from the processor pack-age.Intel SGX has two restricted interfaces to allowSGX encalves to interact with non-enclave applications:
ECALL and
OCALL . Non-enclave applications should usethe
ECALL interfaces to execute trusted functions withinenclaves. They cannot call any other enclave functionswithout corresponding
ECALL interfaces. Also, SGX en-claves should use the
OCALL interfaces to execute un- trusted functions (e.g., system calls). Their any otherattempts to execute untrusted functions (e.g., jumpinginto non-enclave code) result in faults.Intel SGX Software Development Kit (SDK) isshipped with a tool called
Edger8r [1] that automati-cally and securely generated code for
ECALL and
OCALL interfaces. Although SGX enclaves can access bothEPCs and normal memory, non-enclave applicationscan only access the normal memory. Thus, all inputand output values for the
ECALL and
OCALL interfacesbetween them need to be stored in the normal mem-ory first and then copied to the memory of callee andcaller later. The
Edger8r tool creates all such edgeroutines automatically. It decodes the user-provided en-clave definition language (EDL) files specifying
ECALL and
OCALL interfaces, and generates proxy functions tosecurely exchange input and output parameters for theinterfaces. That is, the proxy functions copy data be-tween enclaves and non-enclave applications as well ascheck the sanity of input or output data (e.g., they checkthe address range if a parameter is a pointer).The proxy functions generated by
Edger8r need tobe secure because they are designed to copy certaindata (i.e., input values to an
OCALL interface and a re-turn value of an
ECALL interface) from the enclave tothe normal memory. If the proxy functions have secu-rity problems, they might be exploited to extract sensi-tive data from the enclave that is neither input to
OCALL nor output of
ECALL , which results in incomplete confi-dentiality of Intel SGX.In this paper, we explore the security problems ofthe proxy functions generated by the
Edger8r tool forthe
ECALL and
OCALL interfaces of Intel SGX. Morespecifically, we focus on the possibility of data leakagebecause of structure padding . When handling struc-ture data types (e.g., struct in C), modern compil-ers intentionally align their members by putting somepadding bytes, perhaps to reduce memory/cache accesstime [4]. These padding bytes, however, are usuallyignored when initializing structure variables such that1 typedef struct { uint64_t val1; uint8_t val2; /* 7-byte padding */ uint64_t val3; } test_struct; Figure 1:
Structure with padding (in x86_64 ). The total sizeof this structure is 24 bytes because of the padding. they can contain uninitialized memory values [2]. If theproxy functions generated by
Edger8r do not considerthis security problem, uninitialized enclave data can beleaked through padding.We confirm that when the data types of input valuesto an
OCALL interface or a return value of an
ECALL inter-face are structures containing padding bytes, uninitial-ized enclave data is copied to the normal memory viathe padding bytes during
OCALL or ECALL by the proxyfunctions. This is because the proxy functions are gen-erated to copy the entire memory of a structure variable,not to copy its individual members. That is, they do notperform deep copy.We expect that the impact of this data leakage prob-lem through uninitialized structure padding is similarto that of the Heartbleed vulnerability. As Heartbleeddoes, this security problem allows us to leak a numberof bytes from secure enclaves. More importantly, alldata within secure enclaves is supposed to be in plain-text . This is because the secure enclaves, by design,ensure the data confidentiality and isolation such thatwe do not need to redundantly encrypt the data. Thatis, the secure enclaves likely manage the plaintext ofsensitive information (e.g., RSA private key, password,and biometric information) in their memory, which canbe leaked through the uninitialized structure padding.Therefore, when developing SGX applications, devel-opers should carefully consider whether their applica-tions can suffer from this critical security problem.Possible countermeasures to this uninitializedpadding problem are as follows: (1) perform per-member deep copy during
ECALL and
OCALL , (2)use the directive to avoid padding,(3) enforce memset to fully initialize structure vari-ables, and (4) adopt advanced structure initializationtechniques [2, 3].
Figure 1 shows an example C structure, test_struct , which contains padding bytes usedfor aligning its member variables. The test_struct test_struct ecall_test_struct( char *encrypted_input, size_t input_size) { char *input; test_struct *ret; input = ( char *)malloc( sizeof ( char ) * input_size); decrypt_fun(encrypted_input, input, input_size); /* Do something */ free(input); ret = (test_struct*)malloc( sizeof (test_struct)); /* Do something */ ret->val1 = ...; ret->val2 = ...; ret->val3 = ...; return *ret; } Figure 2:
ECALL returning test_struct . The padding inside test_struct is not initialized. structure has three member variables, val1 , val2 and val3 , in which the first and third member variables’sizes are eight bytes whereas the second membervariable’s size is one byte. If there is no directive, modern C compilers will put seven-bytepadding between val2 and val3 to align all of the threemember variables for memory access efficiency [4],so that the size of test_struct will be 24 bytes.That is, if we have a variable ts whose type is test_struct , initializing its individual members (i.e., ts.val1=0 , ts.val2=0 , ts.val3=0 ) is not enoughto fully clean up this variable such that its paddingbytes can contain uninitialized data. Instead, wehave to explicitly initialize padding bytes by using memset(&ts, 0, sizeof(test_struct)) . In this section, we explain how uninitialized enclavememory can be leaked through structure padding. Wefocus on the following two cases: (1)
ECALL returninga structure variable with padding (§3.1) and (2)
OCALL having an input structure variable with padding (§3.2).We used Intel SGX SDK for Linux version 1.9 and areal system with Core i7-6700K to test the explainedproblems and confirmed that all the problems really ex-isted.
ECALL
Returning Padded Structure
We explain how
ECALL functions returning a struc-ture variable can leak sensitive enclave data through2 typedef struct ms_ecall_test_struct_t { test_struct ms_retval; char * ms_encrypted_input; size_t ms_input_size; } ms_ecall_test_struct_t; ... static sgx_status_t SGX_CDECL sgx_ecall_test_struct( void * pms) { CHECK_REF_POINTER(pms, sizeof (ms_ecall_test_struct_t)); ms_ecall_test_struct_t* ms = SGX_CAST(ms_ecall_test_struct_t*, pms); sgx_status_t status = SGX_SUCCESS; ms->ms_retval = ecall_test_struct(ms->ms_encrypted_input, ms->ms_input_size); /* no deep copy during returning a value */ return status; } Figure 3:
Proxy function for ecall_test_struct . The en-tire content of test_struct including the padding is returnedto the non-enclave memory. padding. Figure 2 shows an example
ECALL functionthat returns a padded structure, test_struct , explainedin §2. This function receives two input values, performssome computations with them, and eventually returns test_struct . Since this function does not clear thepadding bytes of test_struct , they can contain unini-tialized enclave data and be returned to a proxy functiongenerated by the
Edger8r tool.Figure 3 represents a proxy function for the ecall_test_struct function, which is automaticallygenerated by
Edger8r to be executed inside an en-clave. As shown in Line 16, this proxy function justfully copies the return value of ecall_test_struct into ms->ms_retval , a non-enclave marshalled struc-ture for storing input and out values for this
ECALL func-tion, instead of individually copying its members to pms->ms_retval .Therefore, we conclude that an
ECALL proxy functioncan copy uninitialized padding bytes from an enclave toa non-enclave memory region when returning a struc-ture variable, which can potentially contain uninitial-ized sensitive enclave data.
OCALL
Receiving Padded Structure as Input
Next, we explain how
OCALL functions receivinga structure variable as input can leak sensitive datathrough padding. Figure 4 shows an example
OCALL function, ocall_test_struct , that receives a paddedstructure, test_struct , as input. This function tries toaccess every single byte of a test_struct variable, ts , void ocall_test_struct(test_struct ts, int val) { /* Do something with ts and val */ uint8_t * bytes = ( uint8_t *)&ts; for ( int i = 0; sizeof (test_struct); ++i) { printf("%0x ", bytes[i]); } } Figure 4:
OCALL receiving test_struct as input. This func-tion can access the data in the padding if it is not initialized. typedef struct ms_ocall_test_struct_t { test_struct ms_ts; int ms_val; } ms_ocall_test_struct_t; ... sgx_status_t SGX_CDECL ocall_test_struct(test_struct ts, int val) { sgx_status_t status = SGX_SUCCESS; ms_ocall_test_struct_t* ms = NULL; size_t ocalloc_size = sizeof (ms_ocall_test_struct_t); void *__tmp = NULL; __tmp = sgx_ocalloc(ocalloc_size); if (__tmp == NULL) { sgx_ocfree(); return SGX_ERROR_UNEXPECTED; } ms = (ms_ocall_test_struct_t*)__tmp; __tmp = ( void *)(( size_t )__tmp + sizeof (ms_ocall_test_struct_t)); ms->ms_ts = ts; /* no deep copy */ ms->ms_val = val; status = sgx_ocall(2, ms); sgx_ocfree(); return status; } Figure 5:
Proxy function for ocall_test_struct . The en-tire content of test_struct including the padding is passedto ocall_test_struct() as an input parameter. implying that if this input struct contains padding withsensitive enclave data, this function can access them italso.Figure 5 shows a proxy function of ocall_test_struct that will be executed insidean enclave. This function allocates a non-enclavememory region for a marshalled structure (Line 16)and copies an input structure variable, ts , into it (Line25) while doing not handle the individual members ofthe structure.Therefore, we conclude that an OCALL proxy functioncan copy uninitialized padding bytes from an enclaveto a non-enclave memory region when the correspond-ing
OCALL function receives a structure variable as input,3hich can potentially contain uninitialized sensitive en-clave data.
In this section, we explain possible countermeasuresagainst the sensitive enclave data leakage problembecause of padding, which can be implemented inthe future. First, we can revise the
Edger8r tool togenerate proxy functions that individually copy themember of a structure variable during
ECALL and
OCALL (i.e., deep copy). For example, in Figure 5, we can do ms->ms_ts.val1=ts.val1 , ms->ms_ts.val2=ts.val2 ,and ms->ms_ts.val3=ts.val3 , instead of ms->ms_ts=ts to do not leak uninitialized padding.However, it makes proxy functions be complicatedespecially when they are dealing with a complex struc-ture variable recursively containing other structures.Second, we can enforce directive toeliminate any padding, but it introduces performanceoverhead because of a lack of memory alignment.Third, whenever we allocate a structure variable insidean enclave, we can use memset() to fully initialize allof its memory. This countermeasure can avoid anypotential data leakage problems, but it can experienceperformance degradation. Fourth, as Lu et al. [2] andMilburn et al. [3] do, we can implement advancedmemory initialization techniques to selectively initial- ize padding bytes only when they can leak sensitivedata. We believe that this is the most practical solutionagainst the explored problems such that, in the future,we will figure out the best memory initializationtechnique for Intel SGX to eradicate the uninitializedenclave data leakage problem. Responsible Disclosure
We have reported this uninitialized padding problem toIntel on June 23, 2017. After having numerous discus-sions with us, Intel SGX SDK developers informed thatthis padding issue will be explicitly warned in the SDKdocumentation to describe this issue and potential miti-gation approaches.
References [1] I
NTEL C ORPORATION . The Edger8r Tool. https://software.intel.com/en-us/node/708941 .[2] L U , K., S ONG , C., K IM , T., AND L EE , W. UniSan: ProactiveKernel Memory Initialization to Eliminate Data Leakages. In Proceedings of the 23rd ACM Conference on Computer andCommunications Security (CCS) (Vienna, Austria, Oct. 2016).[3] M
ILBURN , A., B OS , H., AND G IUFFRIDA , C. SafeInit: Com-prehensive and Practical Mitigation of Uninitialized Read Vul-nerabilities. In
Proceedings of the 2017 Annual Network andDistributed System Security Symposium (NDSS) (San Diego,CA, Feb.–Mar. 2017).[4] R
AYMOND , E. S. The Lost Art of C Structure Packing, 2017. ..