Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support exception handling in enclaves #21

Closed
CodeMonkeyLeet opened this issue Nov 21, 2017 · 1 comment
Closed

Support exception handling in enclaves #21

CodeMonkeyLeet opened this issue Nov 21, 2017 · 1 comment
Labels
functionality Issue describes an enhancement or addition of functionality to Open Enclave SDK
Milestone

Comments

@CodeMonkeyLeet
Copy link
Contributor

We need to design out and implement exception handling support in enclaves for both Linux and Windows. This does not include supporting Structured Exception Handling for Windows.

@CodeMonkeyLeet CodeMonkeyLeet added the story Issue describes a user scenario to be enabled. Unit of prioritization for project planning. label Nov 21, 2017
@CodeMonkeyLeet CodeMonkeyLeet added this to the 2017.12 milestone Nov 21, 2017
@CodeMonkeyLeet CodeMonkeyLeet added this to To do in Public preview via automation Nov 21, 2017
@CodeMonkeyLeet CodeMonkeyLeet moved this from Backlog to Current milestone in Public preview Dec 1, 2017
@lk2100 lk2100 self-assigned this Dec 16, 2017
@CodeMonkeyLeet CodeMonkeyLeet moved this from Current milestone to In progress in Public preview Jan 3, 2018
@CodeMonkeyLeet CodeMonkeyLeet moved this from In progress to In review in Public preview Feb 3, 2018
@CodeMonkeyLeet
Copy link
Contributor Author

#84 resolves signal handling on Linux. Currently evaluating software exception handling.

@lk2100 lk2100 closed this as completed Mar 28, 2018
Public preview automation moved this from In review to Done Mar 28, 2018
@CodeMonkeyLeet CodeMonkeyLeet added functionality Issue describes an enhancement or addition of functionality to Open Enclave SDK and removed story Issue describes a user scenario to be enabled. Unit of prioritization for project planning. labels Jun 29, 2018
Britel pushed a commit that referenced this issue Nov 19, 2018
* Remove TcpsCalls.edl from application code

Signed-off-by: Dave Thaler <dthaler@microsoft.com>
oe-bors bot pushed a commit that referenced this issue Jun 17, 2019
1871: Add support for recursive calls to oe_once/pthread_once. r=yakman2020 a=johnkord

This change addresses one scenario I encountered when integrating the OpenSSL library into Open Enclave: I noticed my enclave hanging during the call to oe_initialize_openssl (which calls pthread_once), where the hanging never terminated. This hang was partially due to this local static lock:

```C
static oe_spinlock_t _lock = OE_SPINLOCK_INITIALIZER;
```

This is an issue for OpenSSL because when invoking pthread_once to initialize OpenSSL's library, OpenSSL itself will also call pthread_once on several of its internal initialization functions. Our invocation of pthread_once will acquire the spinlock "_lock", and then when OpenSSL's pthread_once invocations attempt to acquire this lock, they will hang forever. Here is what a backtrace looks like without this change:

```gdb
(gdb) run
Starting program: /home/johnkord/openenclave/build/tests/crypto/enclave/host/cryptohost ./enc/cryptoenc
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
=== begin _test_asn1_parsing()
^C
Program received signal SIGINT, Interrupt.
oe_spin_lock (spinlock=0x7ffff25a464c <oe_once._lock>) at /home/johnkord/openenclave/enclave/core/sgx/spinlock.c:43
43              while (*spinlock)
(gdb) where
#0  oe_spin_lock (spinlock=0x7ffff25a464c <oe_once._lock>) at /home/johnkord/openenclave/enclave/core/sgx/spinlock.c:43
#1  0x00007ffff228f4f0 in oe_once (once=0x7ffff25a12f4 <base>, func=0x7ffff2120a80 <ossl_init_base_ossl_>) at /home/johnkord/openenclave/enclave/core/sgx/once.c:22
#2  0x00007ffff225f846 in oe_pthread_once (once=0x7ffff25a12f4 <base>, func=0x7ffff2120a80 <ossl_init_base_ossl_>) at /home/johnkord/openenclave/enclave/core/pthread.c:97
#3  0x00007ffff20cdf76 in pthread_once (once=0x7ffff25a12f4 <base>, func=0x7ffff2120a80 <ossl_init_base_ossl_>)
    at /home/johnkord/openenclave/include/openenclave/corelibc/bits/pthread_once.h:10
#4  0x00007ffff214a986 in CRYPTO_THREAD_run_once ()
#5  0x00007ffff212059d in OPENSSL_init_crypto ()
#6  0x00007ffff209ca78 in _initialize () at /home/johnkord/openenclave/enclave/init.c:13
#7  0x00007ffff228f57f in oe_once (once=0x7ffff259f3f0 <_once>, func=0x7ffff209ca60 <_initialize>) at /home/johnkord/openenclave/enclave/core/sgx/once.c:27
#8  0x00007ffff225f846 in oe_pthread_once (once=0x7ffff259f3f0 <_once>, func=0x7ffff209ca60 <_initialize>) at /home/johnkord/openenclave/enclave/core/pthread.c:97
#9  0x00007ffff20cdf76 in pthread_once (once=0x7ffff259f3f0 <_once>, func=0x7ffff209ca60 <_initialize>) at /home/johnkord/openenclave/include/openenclave/corelibc/bits/pthread_once.h:10
#10 0x00007ffff209ca4b in oe_initialize_openssl () at /home/johnkord/openenclave/enclave/init.c:20
#11 0x00007ffff208cf67 in oe_cert_read_pem (cert=0x7ffff2de0820, pem_data=0x7ffff2590980 <_CERT>, pem_size=1351) at /home/johnkord/openenclave/enclave/cert.c:464
#12 0x00007ffff2070acf in _test_asn1_parsing () at /home/johnkord/openenclave/tests/crypto/asn1_tests.c:337
#13 0x00007ffff20708f9 in TestASN1 () at /home/johnkord/openenclave/tests/crypto/asn1_tests.c:368
#14 0x00007ffff2082cb9 in TestAll () at /home/johnkord/openenclave/tests/crypto/tests.c:9
#15 0x00007ffff206f1fd in test () at /home/johnkord/openenclave/tests/crypto/enclave/enc/enc.c:47
#16 0x00007ffff208351c in ecall_test (input_buffer=0x7ffff25e0790 "", input_buffer_size=16, output_buffer=0x7ffff25e07a0 "", output_buffer_size=16, output_bytes_written=0x7ffff2de0c78)
    at /home/johnkord/openenclave/build/tests/crypto/enclave/enc/crypto_t.c:50
#17 0x00007ffff22675cf in _handle_call_enclave_function (arg_in=140737488347080) at /home/johnkord/openenclave/enclave/core/sgx/calls.c:326
#18 0x00007ffff22661b7 in _handle_ecall (td=0x7ffff2de6000, func=2, arg_in=140737488347080, output_arg1=0x7ffff2de0fc8, output_arg2=0x7ffff2de0fc0)
    at /home/johnkord/openenclave/enclave/core/sgx/calls.c:432
#19 0x00007ffff2265b59 in __oe_handle_main (arg1=281483566645248, arg2=140737488347080, cssa=0, tcs=0x7ffff2de2000, output_arg1=0x7ffff2de0fc8, output_arg2=0x7ffff2de0fc0)
    at /home/johnkord/openenclave/enclave/core/sgx/calls.c:861
#20 0x00007ffff229765b in oe_enter () at /home/johnkord/openenclave/enclave/core/sgx/enter.S:162
#21 0x0000000000428cb1 in __morestack () at /home/johnkord/openenclave/host/sgx/linux/enter.S:95
#22 0x000000000040af37 in _do_eenter (enclave=0x67f100, tcs=0x7ffff2de2000, aep=0x428b24 <OE_AEP>, code_in=OE_CODE_ECALL, func_in=2, arg_in=140737488347080, code_out=0x7fffffffdde0,
    func_out=0x7fffffffddde, result_out=0x7fffffffdddc, arg_out=0x7fffffffddd0) at /home/johnkord/openenclave/host/sgx/calls.c:231
#23 oe_ecall (enclave=0x67f100, func=2, arg=140737488347080, arg_out_ptr=0x7fffffffdfc0) at /home/johnkord/openenclave/host/sgx/calls.c:669
#24 0x000000000040bd65 in _call_enclave_function (is_internal_call=false, enclave=0x67f100, function_id=0, input_buffer=0x68ccf0, input_buffer_size=16, output_buffer=0x68cd00,
    output_buffer_size=16, output_bytes_written=0x7fffffffe1a8) at /home/johnkord/openenclave/host/sgx/calls.c:748
#25 0x000000000040bb3a in oe_call_enclave_function (enclave=0x67f100, function_id=0, input_buffer=0x68ccf0, input_buffer_size=16, output_buffer=0x68cd00, output_buffer_size=16,
    output_bytes_written=0x7fffffffe1a8) at /home/johnkord/openenclave/host/sgx/calls.c:775
#26 0x0000000000408011 in test (enclave=0x67f100) at /home/johnkord/openenclave/build/tests/crypto/enclave/host/crypto_u.c:67
#27 0x0000000000407aec in main (argc=2, argv=0x7fffffffe3d8) at /home/johnkord/openenclave/tests/crypto/enclave/host/host.c:58
```

The solution to this problem was designed by @anakrish and we both pair-programmed it earlier this year. In short, this implementation uses the oe_once_t (i.e. pthread_once_t) variable as the spinlock instead of a local static spinlock, and it uses the atomic function `__sync_val_compare_and_swap` to handle that variable safely.

This solution seems logical to me, but I'm mostly inexperienced when it comes to low level locks like this, and I've never used pthread_once before this change. So definitely, please point out if any invalid assumptions that have been made.

Questions I have:
1. Is OE_ATOMIC_MEMORY_BARRIER_RELEASE in the right location? Originally, I had it inside one of the conditions, but I don't know exactly what that operation does. It seems logical that if each potential thread invokes the ACQUIRE operation, it should probably also invoke the RELEASE, but I have no idea. Double check me here, please :)
2. Is there any harm in using a pthread_once_t variable like this? If we can't, then I'm not really sure how to solve this problem, as we can't extend on the pthread_once_t type with oe_once_t, because OpenSSL allocates/manages the memory of their own pthread_once_t variables. I assume other third party libraries would also have the same expectations
3. Are there any better atomic functions to call besides this `__sync_val_compare_and_swap` ? Here is the reference we used when designing/implementing this: https://gcc.gnu.org/onlinedocs/gcc-7.4.0/gcc/_005f_005fsync-Builtins.html . These atomic functions are referred to as "legacy" now, so there are probably modern functions we can invoke instead.

Co-authored-by: John Kordich <johnkord@microsoft.com>
Co-authored-by: Anand Krishnamoorthi <anakrish@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
functionality Issue describes an enhancement or addition of functionality to Open Enclave SDK
Projects
No open projects
Development

No branches or pull requests

2 participants