apache / incubator-teaclave-sgx-sdk

Apache Teaclave (incubating) SGX SDK helps developers to write Intel SGX applications in the Rust programming language, and also known as Rust SGX SDK.
https://teaclave.apache.org
Apache License 2.0
1.17k stars 259 forks source link

The reason for TCSPolicy requirement on env_logger? #271

Open adaszko opened 3 years ago

adaszko commented 3 years ago

Hi!

I was trying to use the logging library within an enclave as described at https://github.com/apache/incubator-teaclave-sgx-sdk/tree/master/samplecode/logger#usage and came across the TCSPolicy = 0 requirement. Everything works great with that setting. The problem is, unfortunately, I have a different library that needs TCSPolicy = 1 (my colleague opened an issue about it some time ago: https://github.com/apache/incubator-teaclave-sgx-sdk/issues/240). So there's a conflict.

Now, while I can see why a library won't work if it depends on Thread Local Storage (TLS), it's not clear to me why log/env_logger depends on TCSPolicy = 1. Can you shed some light on why the forked version of log/env_logger crates need that? Is it possible to bypass that requirement somehow?

Thanks in advance

dingelish commented 3 years ago

Hi @adaszko ,

Long story short: i just solved it in https://github.com/mesalock-linux/env_logger-sgx/commit/ae2a39b53827b0ca074a2966a554ba1a998d7836 . To get rid of the TCSPolicy limitation, use this line in your enclave's Cargo.toml

env_logger = { git = "https://github.com/mesalock-linux/env_logger-sgx", default-features = false, features = ["mesalock_sgx"] }

Details: First I looked into the dependency tree of env_logger-sgx:

$ cargo tree
env_logger v0.7.1 (/home/ding/incubator-teaclave-sgx-sdk/samplecode/logger/env_logger-sgx)
├── humantime v1.3.0 (https://github.com/mesalock-linux/humantime-sgx#d50b0b44)
│   ├── quick-error v1.2.2 (https://github.com/mesalock-linux/quick-error-sgx#c77b8867)
│   └── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       ├── hashbrown_tstd v0.7.1 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       │   [build-dependencies]
│       │   └── autocfg v1.0.1
│       ├── sgx_alloc v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       ├── sgx_backtrace_sys v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       │   └── sgx_libc v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       │       └── sgx_types v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       │   [build-dependencies]
│       │   ├── cc v1.0.60
│       │   └── sgx_build_helper v0.1.3 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       ├── sgx_demangle v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       ├── sgx_libc v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
│       ├── sgx_tprotected_fs v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       │   ├── sgx_trts v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       │   │   ├── sgx_libc v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
│       │   │   └── sgx_types v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       │   └── sgx_types v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       ├── sgx_trts v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
│       ├── sgx_types v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│       └── sgx_unwind v0.1.1 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│           [build-dependencies]
│           └── sgx_build_helper v0.1.3 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
├── log v0.4.8 (https://github.com/mesalock-linux/log-sgx#d08c18ff)
│   ├── cfg-if v0.1.10
│   └── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
├── regex v1.3.1 (https://github.com/mesalock-linux/regex-sgx#cf45cc1a)
│   ├── aho-corasick v0.7.10 (https://github.com/mesalock-linux/aho-corasick-sgx#ae5c0d76)
│   │   ├── memchr v2.2.1 (https://github.com/mesalock-linux/rust-memchr-sgx#44e36be5)
│   │   │   ├── sgx_libc v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
│   │   │   ├── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
│   │   │   └── sgx_types v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7)
│   │   └── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
│   ├── memchr v2.2.1 (https://github.com/mesalock-linux/rust-memchr-sgx#44e36be5) (*)
│   ├── regex-syntax v0.6.12 (https://github.com/mesalock-linux/regex-sgx#cf45cc1a)
│   │   └── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
│   ├── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
│   └── thread_local v1.0.0 (https://github.com/mesalock-linux/thread_local-rs-sgx#eb03eee1)
│       ├── lazy_static v1.4.0
│       │   └── spin v0.5.2
│       └── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
├── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)
└── termcolor v1.0.5 (https://github.com/mesalock-linux/termcolor-sgx#d8866cb9)
    └── sgx_tstd v1.1.2 (https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.2#8f065be7) (*)

we can see that env_logger-sgx depends on thread_local which further requires secured thread local storage. an enclave cannot have stable thread local storage without BOUND TCS policy.

so the solution is to remove regex from this dependency tree. this is done by a small fix in env_logger-sgx and make it work without any external dependencies. see the above line for usage :-)

adaszko commented 3 years ago

Awesome, thank you!

I did some tests and it's almost perfect. One glitch that I found is that within Rust tests, the --nocapture flag isn't being respected. What I mean by that is when I initialize the logger like so (note the is_test(true) call) :

    #[no_mangle]
    pub extern "C" fn ecall_init_test_logger() {
        let mut builder = env_logger::Builder::from_default_env();
        builder.is_test(true);
        builder.init()
    }

and then log from inside the enclave, it doesn't matter whether I pass --nocapture to a test or not — the output is the same in both cases. The way to suppress/enable it, is of course the RUST_LOG environment variable, but it has the shortcoming of not depending on the test success/failure. It's still beneficial to have --nocapture working, because it allows cargo to produce almost no output at all when a test succeeds (which is what we want), but dump everything out to output, when it fails, which is when you need the most information to debug the failure.

Hope I'm not missing some configuration here option here. Cheers!