api_linux.go 3.4 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
package enclave_runtime_pal // import "github.com/opencontainers/runc/libenclave/internal/runtime/pal"

/*
#include <stdlib.h>

static int palInitV1(void *sym, const char *args, const char *log_level)
{
	typedef struct {
		const char*     instance_dir;
		const char*     log_level;
	} pal_attr_t;
	pal_attr_t attr = {
		args,
		log_level,
	};

	return ((int (*)(pal_attr_t *))sym)(&attr);
}

static int palExecV1(void *sym, const char *exe, const char *argv[],
		     const char *envp[], int *exit_code, int stdin,
		     int stdout, int stderr)
{
	typedef struct {
		int stdin, stdout, stderr;
	} pal_stdio_fds;
	pal_stdio_fds fds = {
		stdin, stdout, stderr,
	};

	return ((int (*)(const char *, const char *[], pal_stdio_fds *, int *))sym)
		(exe, argv, &fds, exit_code);
}

static int palKillV1(void *sym, int sig, int pid)
{
	return ((int (*)(int, int))sym)(sig, pid);
}

static int palDestroyV1(void *sym)
{
	return ((int (*)(void))sym)();
}
*/
import "C"

import (
	"fmt"
	"github.com/sirupsen/logrus"
	"os"
	"strings"
	"unsafe"
53 54

	"github.com/opencontainers/runc/libcontainer/nsenter"
55 56 57 58 59 60 61 62 63
)

const (
	palApiVersion = 1
)

type enclaveRuntimePalApiV1 struct {
}

64 65 66 67 68 69 70 71 72 73 74
func (pal *enclaveRuntimePalApiV1) get_version() uint32 {
	logrus.Debugf("pal get_version() called")
	sym := nsenter.SymAddrPalVersion()
	if sym != nil {
		return *(*uint32)(sym)
	} else {
		return palApiVersion
	}
}

func (api *enclaveRuntimePalApiV1) init(args string, logLevel string) error {
75 76 77 78 79 80 81 82
	logrus.Debugf("pal init() called with args %s", args)

	a := C.CString(args)
	defer C.free(unsafe.Pointer(a))

	l := C.CString(logLevel)
	defer C.free(unsafe.Pointer(l))

83
	sym := nsenter.SymAddrPalInit()
84 85 86 87 88 89 90
	ret := C.palInitV1(sym, a, l)
	if ret < 0 {
		return fmt.Errorf("pal init() failed with %d", ret)
	}
	return nil
}

91
func (pal *enclaveRuntimePalApiV1) exec(cmd []string, envs []string, stdio [3]*os.File) (int32, error) {
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 118 119 120 121 122 123 124
	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
	stdin := C.int(int(stdio[0].Fd()))
	stdout := C.int(int(stdio[1].Fd()))
	stderr := C.int(int(stdio[2].Fd()))
125
	sym := nsenter.SymAddrPalExec()
126 127 128 129 130 131 132
	ret := C.palExecV1(sym, exe, argv, envp, (*C.int)(unsafe.Pointer(&exitCode)), stdin, stdout, stderr)
	if ret < 0 {
		return exitCode, fmt.Errorf("pal exec() failed with %d", ret)
	}
	return exitCode, nil
}

133
func (pal *enclaveRuntimePalApiV1) kill(sig int, pid int) error {
134 135
	sigNum := C.int(sig)
	pidNum := C.int(pid)
136
	sym := nsenter.SymAddrPalKill()
137 138 139 140 141 142 143
	ret := C.palKillV1(sym, sigNum, pidNum)
	if ret < 0 {
		return fmt.Errorf("pal kill() failed with %d", ret)
	}
	return nil
}

144
func (pal *enclaveRuntimePalApiV1) destroy() error {
145 146
	logrus.Debugf("pal destroy() called")

147
	sym := nsenter.SymAddrPalDestroy()
148 149 150 151 152 153
	ret := C.palDestroyV1(sym)
	if ret < 0 {
		return fmt.Errorf("pal destroy() failed with %d", ret)
	}
	return nil
}