Skip to content

GO

SCONE supports cross-compiling GO programs to run these inside of SGX enclaves. The GO cross-compiler is part of image sconecuratedimages/crosscompilers.

Example

Start the SCONE crosscompiler container:

docker run --device=/dev/isgx -it -p 8080:8080 sconecuratedimages/crosscompilers

Please drop argument --device=/dev/isgx in case you do not have an SGX driver installed.

Lets consider a simple GO program (take from a GO tutorial):

cat > web-srv.go << EOF
package main

import (
    "os"
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!\n", r.URL.Path[1:])
    if r.URL.Path[1:] == "EXIT" {
        os.Exit(0)
    }
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}
EOF

You can cross-compile this program as follows:

SCONE_HEAP=1G scone-gccgo web-srv.go -O3 -o web-srv-go -g

You can start the compiled program (and enable some debug messages) as follows:

SCONE_VERSION=1 ./web-srv-go &

The output should look as follows:

export SCONE_QUEUES=4
export SCONE_SLOTS=256
export SCONE_SIGPIPE=0
export SCONE_MMAP32BIT=0
export SCONE_SSPINS=100
export SCONE_SSLEEP=4000
export SCONE_KERNEL=0
export SCONE_HEAP=1073741824
export SCONE_STACK=81920
export SCONE_CONFIG=/etc/sgx-musl.conf
export SCONE_MODE=hw
export SCONE_SGXBOUNDS=no
export SCONE_VARYS=no
export SCONE_ALLOW_DLOPEN=no
export SCONE_MPROTECT=no
Revision: b1e014e64b4d332a51802580ec3252370ffe44bb (Wed May 30 15:17:05 2018 +0200)
Branch: master
Configure options: --enable-shared --enable-debug --prefix=/mnt/ssd/franz/subtree-scone2/built/cross-compiler/x86_64-linux-musl

Enclave hash: dea1dadce2884bbfd642c10f436c1d02db7ac0f4e4f3abe5d2fde031056405dd

You can now connect to port 8080, for example, with curl:

curl localhost:8080/SCONE

The output should be as follows:

Hi there, I love SCONE!

You can terminate the server with

curl localhost:8080/EXIT

This will output the following text:

curl: (52) Empty reply from server

Building Dependencies

Building larger applications that include external dependencies can be difficult when using scone-gccgo alone. To simplify the building of complex applications, we recommend the use of the go command.

First, install go inside a sconecuratedimages/crosscompilers container as follows:

$ apk update
$ apk add go

You can then build your dependencies with the help of go and the SCONE go crosscompiler:

$ go build -compiler gccgo -buildmode=exe

Note

you need to specify gccgo not scone-gccgo: gccgo is an alias of scone-gccgo.

For a more detailed example, please read how we compile groupcache.

Debugging

SCONE supports debugging of programs running inside of an enclave with the help of gdb.

Debugging inside of a container

Standard containers have not sufficient rights to use the debugger. Hence, you must start a container with SYS_PTRACE capability. For example:

docker run --cap-add SYS_PTRACE -it -p 8080:8080 -v "$PWD"/EXAMPLE:/usr/src/myapp -w /usr/src/myapp  sconecuratedimages/crosscompilers

Handling Illegal instructions

Some instructions, like CPUID, are not permitted inside of enclaves. For some of these instructions, like CPUID, we provide an automatic emulation. However, we recommend not to use any illegal instructions inside of enclaves despite having an automatic emulation of these instructions. For example, we provide static replacements of the CPUID instruction.

scone-gdb ./web-srv-go

This will produce the following output:

GNU gdb (Ubuntu 7.12.50.20170314-0ubuntu1.1) 7.12.50.20170314-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Source directories searched: /opt/scone/scone-gdb/gdb-sgxmusl-plugin:$cdir:$cwd
Setting environment variable "LD_PRELOAD" to null value.
Reading symbols from ./web-srv-go...done.
[SCONE] Initializing...

If your program contains some illegal instructions, you need to ask the debugger to forward the signals, that these illegal instructions cause, to the program via handle SIGILL nostop pass:

# (gdb) 
handle SIGILL nostop pass

This will produce the following output:

Signal        Stop  Print   Pass to program Description
SIGILL        No    Yes     Yes             Illegal instruction
(gdb)

Since we do not patch the CPUID instructions in this run,

run

you will see something like this:

Starting program: /usr/src/myapp/web-srv-go 
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[SCONE] Enclave base: 1000000000
[SCONE] Loaded debug symbols
[New Thread 0x7f1786d26700 (LWP 105)]
[New Thread 0x7f1786525700 (LWP 106)]
[New Thread 0x7f1785d24700 (LWP 107)]
[New Thread 0x7f1785523700 (LWP 108)]
[New Thread 0x7f1787502700 (LWP 109)]
[New Thread 0x7f17874fa700 (LWP 110)]
[New Thread 0x7f17874f2700 (LWP 111)]
[New Thread 0x7f17874ea700 (LWP 112)]

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 8 "web-srv-go" received signal SIGILL, Illegal instruction.

You could interrupt this execution via control c:

^C
Thread 1 "web-srv-go" received signal SIGINT, Interrupt.
0x00007f17870f69dd in pthread_join (threadid=139739022911232, thread_return=0x7ffe1c807928) at pthread_join.c:90
90  pthread_join.c: No such file or directory.
(gdb) where
#0  0x00007f17870f69dd in pthread_join (threadid=139739022911232, thread_return=0x7ffe1c807928) at pthread_join.c:90
#1  0x0000002000004053 in main (argc=1, argv=0x7ffe1c807c18, envp=0x7ffe1c807c28) at ./tools/starter-exec.c:764
(gdb) cont
Continuing.

Breakpoints

scone-gdb support breakpoints. Say, we want to get control in the debugger whenever a request is being processed by the handler. We would set a breakpoint at function main.handler as follows:

scone-gdb ./web-srv-go
...
[SCONE] Initializing...
(gdb) handle SIGILL nostop pass
Signal        Stop      Print   Pass to program Description
SIGILL        No        Yes     Yes             Illegal instruction
(gdb) break main.handler
Function "main.handler" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (main.handler) pending.
(gdb) run
Starting program: /usr/src/myapp/web-srv-go 
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[SCONE] Enclave base: 1000000000
[SCONE] Loaded debug symbols
[New Thread 0x7fb6cad32700 (LWP 243)]
[New Thread 0x7fb6ca531700 (LWP 244)]
[New Thread 0x7fb6c9d30700 (LWP 245)]
[New Thread 0x7fb6c952f700 (LWP 246)]
[New Thread 0x7fb6cb50e700 (LWP 247)]
[New Thread 0x7fb6cb506700 (LWP 248)]
[New Thread 0x7fb6cb4fe700 (LWP 249)]
[New Thread 0x7fb6cb4f6700 (LWP 250)]

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Thread 6 "web-srv-go" received signal SIGILL, Illegal instruction.

Note that at the time when we are setting the breakpoint, the symbols of the code running inside of the enclave are not yet known. Hence, we just let gdb know that the symbol will be defined later on.

We are now sending a request with the help of curl from a different window. This triggers the breakpoint:

[Switching to Thread 0x7fb6cb506700 (LWP 248)]

Thread 7 "web-srv-go" hit Breakpoint 1, main.handler (w=..., r=0x100909e300) at web-srv.go:8
8       func handler(w http.ResponseWriter, r *http.Request) {
(gdb) n
9           fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
(gdb) n
8       func handler(w http.ResponseWriter, r *http.Request) {
(gdb) c
Continuing.

© scontain.com, July 2019. Questions or Suggestions?