From 4747d9d5c8c2890e3d818cdf81edbc5e853fb159 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 22 Jun 2020 15:05:10 +0800 Subject: [PATCH] rune/libenclave: Optimize the way of passing parameters Because there is no re-exec operation, there is no need to use environment variables to pass parameters between bootstrap and runelet, use global variables instead of environment variables. Signed-off-by: Tianjia Zhang --- rune/libenclave/bootstrap.go | 69 +++++++++++------------------------- rune/libenclave/runelet.go | 57 ++++------------------------- rune/libenclave/utils.go | 46 ------------------------ 3 files changed, 27 insertions(+), 145 deletions(-) diff --git a/rune/libenclave/bootstrap.go b/rune/libenclave/bootstrap.go index 46cb62d..6629e29 100644 --- a/rune/libenclave/bootstrap.go +++ b/rune/libenclave/bootstrap.go @@ -5,6 +5,21 @@ import ( "os" ) +type enclaveRuntimeEnv struct { + initPipe *os.File + logPipe *os.File + logLevel string + fifoFd int + agentPipe *os.File + detached string +} + +var enclaveEnv enclaveRuntimeEnv + +func GetEnclaveRunetimeEnv() *enclaveRuntimeEnv { + return &enclaveEnv +} + // `rune init` needs to execute self (/proc/self/exe) in container environment // as `runc init` executes entrypoint. Thus, some internal states in form of // environment variable must be staged and then recovered after re-exec. This @@ -13,54 +28,12 @@ import ( func StartBootstrap(initPipe *os.File, logPipe *os.File, logLevel string, fifoFd int, agentPipe *os.File, detached string) (err error) { logrus.Debug("bootstrapping libenclave ...") - if err = stageFd("_LIBENCLAVE_INITPIPE", initPipe); err != nil { - return err - } - defer func() { - if err != nil { - unstageFd("_LIBENCLAVE_INITPIPE") - } - }() - - if fifoFd != -1 { - if err = stageFd("_LIBENCLAVE_FIFOFD", fifoFd); err != nil { - return err - } - defer func() { - if err != nil { - unstageFd("_LIBENCLAVE_FIFOFD") - } - }() - } - - if err = stageFd("_LIBENCLAVE_LOGPIPE", logPipe); err != nil { - return err - } - defer func() { - if err != nil { - unstageFd("_LIBENCLAVE_LOGPIPE") - } - }() - - if err = os.Setenv("_LIBENCLAVE_LOGLEVEL", logLevel); err != nil { - return err - } - defer func() { - if err != nil { - os.Unsetenv("_LIBENCLAVE_LOGLEVEL") - } - }() - - if err = stageFd("_LIBENCLAVE_AGENTPIPE", agentPipe); err != nil { - return err - } - defer func() { - if err != nil { - unstageFd("_LIBENCLAVE_AGENTPIPE") - } - }() + enclaveEnv.initPipe = initPipe + enclaveEnv.logPipe = logPipe + enclaveEnv.logLevel = logLevel + enclaveEnv.fifoFd = fifoFd + enclaveEnv.agentPipe = agentPipe + enclaveEnv.detached = detached - os.Setenv("_LIBENCLAVE_DETACHED", detached) - return nil } diff --git a/rune/libenclave/runelet.go b/rune/libenclave/runelet.go index 8c28396..71f1410 100644 --- a/rune/libenclave/runelet.go +++ b/rune/libenclave/runelet.go @@ -23,43 +23,16 @@ const signalBufferSize = 2048 var enclaveRuntime *runtime.EnclaveRuntimeWrapper func StartInitialization() (exitCode int32, err error) { - logLevel := os.Getenv("_LIBENCLAVE_LOGLEVEL") + env := GetEnclaveRunetimeEnv() - // Make the unused environment variables invisible to enclave runtime. - os.Unsetenv("_LIBENCLAVE_LOGPIPE") - os.Unsetenv("_LIBENCLAVE_LOGLEVEL") + logLevel := env.logLevel // Determine which type of runelet is initializing. - var fifoFd = -1 - envFifoFd := os.Getenv("_LIBENCLAVE_FIFOFD") - if envFifoFd != "" { - defer func() { - if err != nil { - unstageFd("_LIBENCLAVE_FIFOFD") - } - }() - fifoFd, err = strconv.Atoi(envFifoFd) - if err != nil { - return 1, err - } - } + fifoFd := env.fifoFd // Retrieve the init pipe fd to accomplish the enclave configuration // handshake as soon as possible with parent rune. - envInitPipe := os.Getenv("_LIBENCLAVE_INITPIPE") - if envInitPipe == "" { - return 1, fmt.Errorf("unable to get _LIBENCLAVE_INITPIPE") - } - defer func() { - if err != nil { - unstageFd("_LIBENCLAVE_INITPIPE") - } - }() - pipeFd, err := strconv.Atoi(envInitPipe) - if err != nil { - return 1, err - } - initPipe := os.NewFile(uintptr(pipeFd), "init-pipe") + initPipe := env.initPipe defer func() { if err != nil { initPipe.Close() @@ -98,17 +71,14 @@ func StartInitialization() (exitCode int32, err error) { } // If runelet run as detach mode, close logrus before initpipe closed. - envDetach := os.Getenv("_LIBENCLAVE_DETACHED") - detach, err := strconv.Atoi(envDetach) + detach, err := strconv.Atoi(env.detached) if detach != 0 { logrus.SetOutput(ioutil.Discard) } - os.Unsetenv("_LIBENCLAVE_DETACHED") // Close the init pipe to signal that we have completed our init. // So `rune create` or the upper half part of `rune run` can return. initPipe.Close() - os.Unsetenv("_LIBENCLAVE_INITPIPE") // Take care the execution sequence among components. Closing exec fifo // made by finalizeInitialization() allows the execution of `rune start` @@ -116,22 +86,8 @@ func StartInitialization() (exitCode int32, err error) { // and entrypoint, implying `rune exec` may preempt them too. // Launch agent service for child runelet. - envAgentPipe := os.Getenv("_LIBENCLAVE_AGENTPIPE") - if envAgentPipe == "" { - return 1, fmt.Errorf("unable to get _LIBENCLAVE_AGENTPIPE") - } - defer func() { - if err != nil { - unstageFd("_LIBENCLAVE_AGENTPIPE") - } - }() - agentPipeFd, err := strconv.Atoi(envAgentPipe) - if err != nil { - return 1, err - } - agentPipe := os.NewFile(uintptr(agentPipeFd), "agent-pipe") + agentPipe := env.agentPipe defer agentPipe.Close() - os.Unsetenv("_LIBENCLAVE_AGENTPIPE") notifySignal := make(chan os.Signal, signalBufferSize) @@ -152,7 +108,6 @@ func StartInitialization() (exitCode int32, err error) { if err = finalizeInitialization(fifoFd); err != nil { return 1, err } - os.Unsetenv("_LIBENCLAVE_FIFOFD") // Capture all signals and then forward to enclave runtime. signal.Notify(notifySignal) diff --git a/rune/libenclave/utils.go b/rune/libenclave/utils.go index c133d48..dc2dcb8 100644 --- a/rune/libenclave/utils.go +++ b/rune/libenclave/utils.go @@ -7,11 +7,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/opencontainers/runc/libcontainer/stacktrace" pb "github.com/opencontainers/runc/libenclave/proto" - "golang.org/x/sys/unix" "io" - "os" - "strconv" - "syscall" "time" "unsafe" ) @@ -36,48 +32,6 @@ func (e *genericError) Error() string { return fmt.Sprintf("%s:%d: %s caused %q", frame.File, frame.Line, e.Cause, e.Message) } -func stageFd(env string, f interface{}) (err error) { - var fd int - switch f := f.(type) { - case *os.File: - fd = int(f.Fd()) - case int: - fd = f - default: - return fmt.Errorf("unsupported type of environment variable %s", env) - } - - flags, err := unix.FcntlInt(uintptr(fd), syscall.F_GETFD, 0) - if err != nil { - return err - } - if flags&syscall.FD_CLOEXEC == syscall.FD_CLOEXEC { - flags &^= syscall.FD_CLOEXEC - _, err := unix.FcntlInt(uintptr(fd), syscall.F_SETFD, flags) - if err != nil { - return err - } - } - - err = os.Setenv(env, strconv.Itoa(fd)) - if err != nil { - return err - } - - return nil -} - -func unstageFd(env string) { - f := os.Getenv(env) - os.Unsetenv(env) - if f != "" { - fd, err := strconv.Atoi(f) - if err == nil { - unix.Close(fd) - } - } -} - func protoBufRead(conn io.Reader, unmarshaled interface{}) error { var sz uint32 data := make([]byte, unsafe.Sizeof(sz)) -- GitLab