api_linux_v2.go 2.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
package enclave_runtime_pal // import "github.com/opencontainers/runc/libenclave/internal/runtime/pal"

/*
#include <stdlib.h>

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);
}
*/
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) + 1
	pargs := make([]*C.char, argc)
	if argc > 1 {
		exe = C.CString(cmd[0])
		defer C.free(unsafe.Pointer(exe))

		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
}