package enclave_runtime_pal // import "github.com/opencontainers/runc/libenclave/internal/runtime/pal" /* #include static int palCreateProcessV2(void *sym, const char *exe, const char *argv[], const char *envp[], int stdin, int stdout, int stderr, int *pid) { typedef struct { int stdin, stdout, stderr; } pal_stdio_fds; typedef struct { const char *path; const char **argv; const char **env; pal_stdio_fds *fds; int *pid; } pal_create_process_args; pal_stdio_fds fds = { stdin, stdout, stderr, }; pal_create_process_args create_process_args = { exe, argv, envp, &fds, pid, }; return ((int (*)(pal_create_process_args *))sym) (&create_process_args); } static int palExecV2(void *sym, int pid, int *exit_code) { typedef struct { int pid; int *exit_value; } pal_exec_args; pal_exec_args args = { pid, exit_code, }; return ((int (*)(pal_exec_args *))sym) (&args); } static int palKillV2(void *sym, int pid, int sig) { return ((int (*)(int, int))sym)(pid, sig); } */ import "C" import ( "fmt" "github.com/sirupsen/logrus" "os" "strings" "unsafe" "github.com/opencontainers/runc/libcontainer/nsenter" ) type enclaveRuntimePalApiV2 struct { } func (pal *enclaveRuntimePalApiV2) exec(cmd []string, envs []string, stdio [3]*os.File) (int32, error) { logrus.Debugf("pal exec() called with args %s", strings.Join(cmd, " ")) // Skip cmd[0] as used as the executable. var exe *C.char argc := len(cmd) pargs := make([]*C.char, argc) if argc > 1 { exe = C.CString(cmd[0]) defer C.free(unsafe.Pointer(exe)) cmd = cmd[1:] for i, arg := range cmd { logrus.Debugf("arg[%d]: %s", i, arg) pargs[i] = C.CString(arg) defer C.free(unsafe.Pointer(pargs[i])) } } var argv **C.char = (**C.char)(unsafe.Pointer(&pargs[0])) envc := len(envs) + 1 penvs := make([]*C.char, envc) if envc > 1 { for i, e := range envs { logrus.Debugf("env[%d]: %s", i, e) penvs[i] = C.CString(e) defer C.free(unsafe.Pointer(penvs[i])) } } var envp **C.char = (**C.char)(unsafe.Pointer(&penvs[0])) var exitCode int32 var pid int32 stdin := C.int(int(stdio[0].Fd())) stdout := C.int(int(stdio[1].Fd())) stderr := C.int(int(stdio[2].Fd())) sym := nsenter.SymAddrPalCreateProcess() ret := C.palCreateProcessV2(sym, exe, argv, envp, stdin, stdout, stderr, (*C.int)(unsafe.Pointer(&pid))) if ret < 0 { return exitCode, fmt.Errorf("pal create process() failed with %d", ret) } sym = nsenter.SymAddrPalExec() ret = C.palExecV2(sym, C.int(pid), (*C.int)(unsafe.Pointer(&exitCode))) if ret < 0 { return exitCode, fmt.Errorf("pal exec() failed with %d", ret) } return exitCode, nil } func (pal *enclaveRuntimePalApiV2) kill(pid int, sig int) error { pidNum := C.int(pid) sigNum := C.int(sig) sym := nsenter.SymAddrPalKill() if sym == nil { return fmt.Errorf("pal kill() not implemented") } ret := C.palKillV2(sym, pidNum, sigNum) if ret < 0 { return fmt.Errorf("pal kill() failed with %d", ret) } return nil }