api_linux.go 3.5 KB
Newer Older
1 2 3 4 5
package enclave_runtime_pal // import "github.com/opencontainers/runc/libenclave/internal/runtime/pal"

/*
#include <stdlib.h>

6 7 8 9 10
static int palGetVersion(void *sym)
{
	return ((int (*)(void))sym)();
}

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
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"
58 59

	"github.com/opencontainers/runc/libcontainer/nsenter"
60 61 62 63 64 65 66 67 68
)

const (
	palApiVersion = 1
)

type enclaveRuntimePalApiV1 struct {
}

69 70 71 72
func (pal *enclaveRuntimePalApiV1) get_version() uint32 {
	logrus.Debugf("pal get_version() called")
	sym := nsenter.SymAddrPalVersion()
	if sym != nil {
73
		return uint32(C.palGetVersion(sym))
74 75 76 77 78 79
	} else {
		return palApiVersion
	}
}

func (api *enclaveRuntimePalApiV1) init(args string, logLevel string) error {
80 81 82 83 84 85 86 87
	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))

88
	sym := nsenter.SymAddrPalInit()
89 90 91 92 93 94 95
	ret := C.palInitV1(sym, a, l)
	if ret < 0 {
		return fmt.Errorf("pal init() failed with %d", ret)
	}
	return nil
}

96
func (pal *enclaveRuntimePalApiV1) exec(cmd []string, envs []string, stdio [3]*os.File) (int32, error) {
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 125 126 127 128 129
	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()))
130
	sym := nsenter.SymAddrPalExec()
131 132 133 134 135 136 137
	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
}

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

149
func (pal *enclaveRuntimePalApiV1) destroy() error {
150 151
	logrus.Debugf("pal destroy() called")

152
	sym := nsenter.SymAddrPalDestroy()
153 154 155 156 157 158
	ret := C.palDestroyV1(sym)
	if ret < 0 {
		return fmt.Errorf("pal destroy() failed with %d", ret)
	}
	return nil
}