keystone-enclave / keystone

Keystone Enclave (QEMU + HiFive Unleashed)
Other
464 stars 134 forks source link

Using <iostream> in Keystone Enclave Leads to Futex Facility Error #446

Closed AlfiRam closed 5 months ago

AlfiRam commented 5 months ago

Describe the bug Including the <iostream> header in an enclave application leads to a futex facility error, preventing the application from running successfully within the Keystone enclave environment. I am trying to create an enclave app with MS SEAL, and that library uses the <iostream> header frequently in its source code.

Build Failure N/A

Screenshots or Error Log

Verifying archive integrity... MD5 checksums are OK. All good.
Uncompressing Keystone Enclave Package
The futex facility returned an unexpected error code.
[runtime] non-handleable interrupt/exception at 0x10c54 on 0x0 (scause: 0x3)

Additional context Steps to reproduce:

  1. Create a simple enclave application that includes <iostream>:

    #include <iostream>
    
    int main() {
        std::cout << "Testing iostream in enclave...\n";
        return 0;
    }
  2. Compile and run the application in the Keystone enclave with a host app:

The use of <iostream> likely introduces internal synchronization mechanisms that are not fully supported within the enclave, which may cause the futex facility error. In contrast, using C-style I/O with <stdio.h> works without issues, indicating that the additional complexity of iostream is the root cause.

Example with <stdio.h> (works fine):

#include <stdio.h>

int main() {
    printf("Testing printf in enclave...\n");
    return 0;
}

Request:

  1. Confirmation if the use of <iostream> is inherently incompatible with the current Keystone enclave environment.
  2. Any potential workarounds or configurations to allow the use of C++ standard I/O streams within an enclave.

Environment:

acaldaya commented 5 months ago

I would enable the internal_strace plugin for Eyrie to check if there is a missing syscall issue

AlfiRam commented 5 months ago

I followed your suggestion and here's what I found:

Verifying archive integrity... MD5 checksums are OK. All good.
Uncompressing Keystone Enclave Package
[runtime] brk (0x0000000000000000) (req pages 0) = 0x0000002040000000
[runtime] brk (0x0000002040000B60) (req pages 1) = 0x0000002040000B60
[runtime] set_tid_address, not setting address (00000020400000D0), IGNORING
[runtime] syscall 99 not implemented
[runtime] syscall 261 not implemented
[runtime] syscall 78 not implemented
[runtime] getrandom IGNORES FLAGS (size 8), PLATFORM DEPENDENT IF SAFE = ret 8
[runtime] brk (0x0000000000000000) (req pages 0) = 0x0000002040001000
[runtime] brk (0x0000002040022000) (req pages 33) = 0x0000002040022000
[runtime] syscall 98 not implemented
[runtime] Simulating writev (cnt 1) with write calls
The futex facility returned an unexpected error code.
[runtime] proxied write to 2 (size: 54) = 54
[runtime] Simulated writev = 54
[runtime] [mmap]: addr: 0x0000000000000000, length 4096, prot 0x3, flags 0x22, fd -1, offset 0 (1 pages d6) = 0x0000002000000000
[runtime] rt_sigprocmask not supported (how 1), IGNORING
[runtime] syscall 178 not implemented
[runtime] Faking getpid with 2
[runtime] syscall 131 not implemented
[runtime] Cannot handle syscall 134, IGNORING = 0
[runtime] syscall 178 not implemented
[runtime] Faking getpid with 2
[runtime] syscall 131 not implemented
[runtime] non-handlable interrupt/exception at 0x10c54 on 0x0 (scause: 0x3)
[runtime] non-handlable interrupt/exception at 0x10c54 on 0x0 (scause: 0x3)
[runtime] non-handlable interrupt/exception at 0x10c54 on 0x0 (scause: 0x3)

It seems that the futex facility error and several unimplemented syscalls (e.g., futex, mmap, rt_sigprocmask) are causing the issue. Would this mean <iostream> is just not supported in the enclave? Are there no workarounds? If I wanted to create an eapp that includes a certain library with <iostream> in its source code, is it not possible to use that library?

grg-haas commented 5 months ago

Hi @AlfiRam ! I've run into this issue before, which I worked around using this:

diff --git a/runtime/call/syscall.c b/runtime/call/syscall.c
index 81eabbef..924ff1d9 100644
--- a/runtime/call/syscall.c
+++ b/runtime/call/syscall.c
@@ -324,6 +324,11 @@ void handle_syscall(struct encl_ctx* ctx)
     ret = linux_set_tid_address(stack, ctx->regs.tp, (int*) arg0);
     break;

+  case(SYS_futex):
+    // lie?
+    ret = 0;
+    break;
+
   case(SYS_brk):
     ret = syscall_brk((void*) arg0);
     break;

This worked well enough for me, for everything I needed to do using iostream ¯\(ツ)

AlfiRam commented 5 months ago

Hello @grg-haas, my issue has been resolved. Thank you so much, you are truly a lifesaver!