intel / linux-sgx

Intel SGX for Linux*
https://www.intel.com/content/www/us/en/developer/tools/software-guard-extensions/linux-overview.html
Other
1.33k stars 543 forks source link

Using libc in SGX #358

Closed gogo9th closed 5 years ago

gogo9th commented 5 years ago

Hi, I have 3 urgent questions...

Q1. I am trying to use libz3.a (https://github.com/Z3Prover/z3) in SGX. However, if I include "-lz3" in the Enclave_Link_Flag variable, I get hundreds of "undefined reference to ..." errors. All of them are calls to functions defined in libz3.a. Is it that I need to define every single function in libz3.a in the Enclave.edl file? This doesn't seem to be a right solution...

Q2. Also, I am trying to call std library functions such as "printf" and "strcat". However, I cannot use these functions within the Enclave code. I thought libsgx_tstdc.a contains LibC functions, but this library does not have "printf" and "strcat". I wonder if it's impossible to use "printf" and "strcat" and any other common LibC functions within the Enclave.

Q3. I wonder if there is any documentation or tutorials for all functions SGX libraries offer.

I would really appreciate your help!

naishai commented 5 years ago

Hi, Regarding your first question, try to put it in the flags after the library which calls it. You can also try the whole-archive option which makes sure all the code remains (bigger output). Regarding your other questions, see here: https://download.01.org/intel-sgx/linux-2.4/docs/Intel_SGX_Developer_Reference_Linux_2.4_Open_Source.pdf page 371 - Unsupported C Standard Functions printf requires access to the untrusted side, so you need to create a trusted function, format the string there, and then define an ocall to pass the string outside the ecnlave. BTW, from security perspective, it is recommended to use print functions with known number of elements. More info here: https://github.com/intel/safestringlib/wiki/SDL-List-of-Banned-Functions Ishai

gogo9th commented 5 years ago

Thanks a lot for your kind reply. The PDF link is very useful!

About your recommendation of including the library after other libraries that call it, this solution still doesn't work... I created libtest.a which has "int test(void)" and included this library in Makefile's Enclave_Link_Flags as follows:

Enclave_Link_Flags := $(SGX_COMMON_CFLAGS) -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_LIBRARY_PATH) -LEnclave \ -Wl,--whole-archive -l$(Trts_Library_Name) -ltest -Wl,--no-whole-archive \ -Wl,--start-group -lsgx_tstdc -lsgx_tstdcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \ -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \ -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \ -Wl,--defsym,__ImageBase=0

But the error message says the function "test" is undefined. But if I include "int test(void)" in Enclave.edl as a trusted function, the error goes away and compiles okay. Does this mean that all third-party library functions called by Enclave.cpp should be defined in Enclave.edl? My goal is to use the function "Z3_mk_config()" defined in a third-party library libz3.a, but I get bunch of undefined reference errors. So just like I solved the issue for libtest.a, I tried to include Z3_mk_config() in Enclave.edl:

enclave { from "Sealing/Sealing.edl" import *;

include "z3_include/z3.h"

trusted {
    /* define ECALLs here. */
    public int generate_random_number(void);
    int test(void);
    Z3_config Z3_API Z3_mk_config(void);
};
untrusted {
    /* define OCALLs here. */
    void ocall_print([in, string]const char* str);
    void ocall_int_print(int num);
};

};

But I get the error: "unexpected token: typedef" which was used in z3.h. This means I have to modify z3.h... I just wonder if there is any very easy way to use third-party static libraries from within Enclave...

naishai commented 5 years ago

Hi, EDL file is used for generating ECALLS and OCALLS, function calls which enter and exit the enclave. No need to define any library functions there. Your enclave code should be able to call statically linked library functions. However, there might be many missing symbols within that library, depending on the way it was built and what other system and other APIs it is using. A quick look in the Z3 code shows that it is using for example std:ostream which is not implemented in the tstdcxx library of SGX SDK, and probably there are more. Most pre-built libraries will not work out-of-the-box inside enclaves, as they are usually using I/O APIs and other system APIs. You should review the missing symbols list and try to build the library in such a way that most of them will be eliminated, and then implement the missing ones yourself. Some libraries have compilation flags to eliminate I/O calls. You can find an example of such work in SGX SSL project, which is a port of OpenSSL that work inside enclaves. Ishai

gogo9th commented 5 years ago

Hi Ishai,

I appreciate your response. Now I understand that SGX requires some tuning for static libraries that use unsupported functions.

And about this:

EDL file is used for generating ECALLS and OCALLS, function calls which enter and exit the enclave. No need to define any library functions there.

You are correct and I figured out why this didn't work for me previously. My testing library was compiled by gcc, but my Enclave.cpp was compiled by g++. And my testing library's header file (.h) didn't wrap its entire contents with "#ifdef cplusplus extern C { #endif" and "#ifdef cplusplus } #endif ".

Thanks a lot for your great insights!