mirror of
https://github.com/clearlinux/graphene.git
synced 2026-10-03 23:48:19 +00:00
[LibOS,Pal/Linux-SGX] Aggregated commit for OpenVINO and FPGA demo
NOTE: This commit misses the update to the graphene-tests (apps/) submodule. We first need to add the changeset to that submodule and then add another commit here that updates the hash of the submodule.
This commit is contained in:
@@ -500,6 +500,7 @@ int shim_do_pipe2 (int * fildes, int flags);
|
||||
ssize_t shim_do_recvmmsg (int sockfd, struct mmsghdr * msg, size_t vlen, int flags,
|
||||
struct __kernel_timespec * timeout);
|
||||
ssize_t shim_do_sendmmsg (int sockfd, struct mmsghdr * msg, size_t vlen, int flags);
|
||||
int shim_do_eventfd2(int count, int flags);
|
||||
|
||||
/* libos call implementation */
|
||||
long shim_do_sandbox_create (int flags, const char * fs_sb,
|
||||
|
||||
@@ -48,8 +48,68 @@ extern const struct proc_dir dir_ipc_thread;
|
||||
extern const struct proc_fs_ops fs_meminfo;
|
||||
extern const struct proc_fs_ops fs_cpuinfo;
|
||||
|
||||
/* minimal /proc/sys/vm/overcommit_memory emulation (always returns 0) */
|
||||
static int proc_dummy_open(struct shim_handle * hdl, const char * name, int flags) {
|
||||
__UNUSED(name);
|
||||
|
||||
if (flags & (O_WRONLY|O_RDWR))
|
||||
return -EACCES;
|
||||
|
||||
char* str = malloc(128);
|
||||
if (!str)
|
||||
return -ENOMEM;
|
||||
|
||||
int len = snprintf(str, 128, "0"); /* always return "0" text */
|
||||
|
||||
struct shim_str_data * data = malloc(sizeof(struct shim_str_data));
|
||||
if (!data) {
|
||||
free(str);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(data, 0, sizeof(struct shim_str_data));
|
||||
data->str = str;
|
||||
data->len = len;
|
||||
hdl->type = TYPE_STR;
|
||||
hdl->flags = flags & ~O_RDONLY;
|
||||
hdl->acc_mode = MAY_READ;
|
||||
hdl->info.str.data = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_dummy_mode(const char * name, mode_t * mode) {
|
||||
__UNUSED(name);
|
||||
*mode = 0444;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int proc_dummy_stat(const char * name, struct stat * buf) {
|
||||
__UNUSED(name);
|
||||
memset(buf, 0, sizeof(struct stat));
|
||||
buf->st_dev = buf->st_ino = 1;
|
||||
buf->st_mode = 0444|S_IFREG;
|
||||
buf->st_uid = buf->st_gid = 0;
|
||||
buf->st_size = 128;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct proc_fs_ops fs_dummy = {
|
||||
.open = &proc_dummy_open,
|
||||
.mode = &proc_dummy_mode,
|
||||
.stat = &proc_dummy_stat,
|
||||
};
|
||||
|
||||
const struct proc_dir dir_sys_vm = { .size = 1, .ent = {
|
||||
{ .name = "overcommit_memory", .fs_ops = &fs_dummy },
|
||||
}, };
|
||||
|
||||
const struct proc_dir dir_sys = { .size = 1, .ent = {
|
||||
{ .name = "vm", .fs_ops = &fs_dummy, .dir = &dir_sys_vm, },
|
||||
}, };
|
||||
/* END minimal /proc/sys/vm/overcommit_memory emulation (always returns 0) */
|
||||
|
||||
const struct proc_dir proc_root = {
|
||||
.size = 5,
|
||||
.size = 6,
|
||||
.ent = {
|
||||
{ .name = "self", .fs_ops = &fs_thread, .dir = &dir_thread, },
|
||||
{ .nm_ops = &nm_thread, .fs_ops = &fs_thread, .dir = &dir_thread, },
|
||||
@@ -57,6 +117,7 @@ const struct proc_dir proc_root = {
|
||||
.dir = &dir_ipc_thread, },
|
||||
{ .name = "meminfo", .fs_ops = &fs_meminfo, },
|
||||
{ .name = "cpuinfo", .fs_ops = &fs_cpuinfo, },
|
||||
{ .name = "sys", .fs_ops = &fs_dummy, .dir = &dir_sys, },
|
||||
}, };
|
||||
|
||||
#define PROC_INO_BASE 1
|
||||
@@ -132,6 +193,7 @@ static int proc_match_name (const char * trim_name,
|
||||
|
||||
const char * token = trim_name, * next_token;
|
||||
const struct proc_ent * tmp = proc_root.ent;
|
||||
const struct proc_ent * end = tmp + proc_root.size;
|
||||
const struct proc_ent * last = NULL;
|
||||
|
||||
if (*token == '/')
|
||||
@@ -140,7 +202,7 @@ static int proc_match_name (const char * trim_name,
|
||||
while (token) {
|
||||
int tlen = token_len(token, &next_token);
|
||||
|
||||
for ( ; tmp->name || tmp->nm_ops ; tmp++) {
|
||||
for ( ; tmp < end ; tmp++) {
|
||||
if (tmp->name && !memcmp(tmp->name, token, tlen))
|
||||
goto found;
|
||||
|
||||
@@ -152,10 +214,17 @@ static int proc_match_name (const char * trim_name,
|
||||
return -ENOENT;
|
||||
|
||||
found:
|
||||
if (!tmp->dir && next_token)
|
||||
if (!next_token) {
|
||||
/* found the entry, break out of the while loop */
|
||||
last = tmp;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tmp->dir)
|
||||
return -ENOENT;
|
||||
|
||||
last = tmp;
|
||||
end = tmp->dir->ent + tmp->dir->size;
|
||||
tmp = tmp->dir->ent;
|
||||
token = next_token;
|
||||
}
|
||||
|
||||
@@ -1101,7 +1101,7 @@ DEFINE_SHIM_SYSCALL (accept4, 4, shim_do_accept4, int, int, sockfd,
|
||||
SHIM_SYSCALL_PASSTHROUGH (signalfd4, 4, int, int, ufd, __sigset_t *, user_mask,
|
||||
size_t, sizemask, int, flags)
|
||||
|
||||
SHIM_SYSCALL_PASSTHROUGH (eventfd2, 2, int, int, count, int, flags)
|
||||
DEFINE_SHIM_SYSCALL (eventfd2, 2, shim_do_eventfd2, int, int, init, int, flags)
|
||||
|
||||
/* epoll_create1: sys/shim_epoll.c */
|
||||
DEFINE_SHIM_SYSCALL (epoll_create1, 1, shim_do_epoll_create1, int, int, flags)
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <asm/ioctls.h>
|
||||
#include <asm/termios.h>
|
||||
#include <asm/termbits.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/fd.h>
|
||||
#include <linux/sockios.h>
|
||||
|
||||
@@ -43,6 +44,8 @@
|
||||
#define TERM_DEFAULT_CFLAG (B38400|CS8|CREAD)
|
||||
#define TERM_DEFAULT_LFLAG (ICANON|ECHO|ECHOE|ECHOK|ECHOCTL|ECHOKE|IEXTEN)
|
||||
|
||||
static int ioctl_passthru (struct shim_handle * hdl, unsigned int cmd, unsigned long arg);
|
||||
|
||||
static int ioctl_termios (struct shim_handle * hdl, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
@@ -500,10 +503,333 @@ done_fioread:
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOSYS;
|
||||
ret = ioctl_passthru(hdl, cmd, arg);
|
||||
break;
|
||||
}
|
||||
|
||||
put_handle(hdl);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define DUMMY_IOCTL_PRINT _IOR('p', 0x01, struct dummy_print)
|
||||
struct dummy_print {
|
||||
const char * str;
|
||||
unsigned long size;
|
||||
};
|
||||
|
||||
/* Dmitrii Kuvaiskii: list of ioctls for North Cove FPGA driver */
|
||||
#define FPGA_MAGIC 0xB5
|
||||
#define FPGA_BASE 0x00
|
||||
#define PORT_BASE 0x40
|
||||
#define FME_BASE 0x80
|
||||
|
||||
#define FPGA_GET_API_VERSION _IO(FPGA_MAGIC, FPGA_BASE + 0)
|
||||
#define FPGA_CHECK_EXTENSION _IO(FPGA_MAGIC, FPGA_BASE + 1)
|
||||
#define FPGA_PORT_RESET _IO(FPGA_MAGIC, PORT_BASE + 0)
|
||||
#define FPGA_PORT_GET_INFO _IO(FPGA_MAGIC, PORT_BASE + 1)
|
||||
#define FPGA_PORT_GET_REGION_INFO _IO(FPGA_MAGIC, PORT_BASE + 2)
|
||||
#define FPGA_PORT_DMA_MAP _IO(FPGA_MAGIC, PORT_BASE + 3)
|
||||
#define FPGA_PORT_DMA_UNMAP _IO(FPGA_MAGIC, PORT_BASE + 4)
|
||||
#define FPGA_PORT_UMSG_ENABLE _IO(FPGA_MAGIC, PORT_BASE + 5)
|
||||
#define FPGA_PORT_UMSG_DISABLE _IO(FPGA_MAGIC, PORT_BASE + 6)
|
||||
#define FPGA_PORT_UMSG_SET_MODE _IO(FPGA_MAGIC, PORT_BASE + 7)
|
||||
#define FPGA_PORT_UMSG_SET_BASE_ADDR _IO(FPGA_MAGIC, PORT_BASE + 8)
|
||||
#define FPGA_PORT_ERR_SET_IRQ _IO(FPGA_MAGIC, PORT_BASE + 9)
|
||||
#define FPGA_PORT_UAFU_SET_IRQ _IO(FPGA_MAGIC, PORT_BASE + 10)
|
||||
#define FPGA_PORT_UAFU_MMAP _IO(FPGA_MAGIC, PORT_BASE + 11)
|
||||
#define FPGA_PORT_UAFU_UNMAP _IO(FPGA_MAGIC, PORT_BASE + 12)
|
||||
#define FPGA_FME_PORT_PR _IO(FPGA_MAGIC, FME_BASE + 0)
|
||||
#define FPGA_FME_PORT_RELEASE _IO(FPGA_MAGIC, FME_BASE + 1)
|
||||
#define FPGA_FME_PORT_ASSIGN _IO(FPGA_MAGIC, FME_BASE + 2)
|
||||
#define FPGA_FME_GET_INFO _IO(FPGA_MAGIC, FME_BASE + 3)
|
||||
#define FPGA_FME_ERR_SET_IRQ _IO(FPGA_MAGIC, FME_BASE + 4)
|
||||
|
||||
struct fpga_port_info {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u32 capability; /* The capability of port device */
|
||||
__u32 num_regions; /* The number of supported regions */
|
||||
__u32 num_umsgs; /* The number of allocated umsgs */
|
||||
__u32 num_uafu_irqs; /* The number of uafu interrupts */
|
||||
};
|
||||
|
||||
struct fpga_port_region_info {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Access permission */
|
||||
__u32 index; /* Region index */
|
||||
__u32 padding;
|
||||
__u64 size; /* Region size (bytes) */
|
||||
__u64 offset; /* Region offset from start of device fd */
|
||||
};
|
||||
|
||||
struct fpga_port_dma_map {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u64 user_addr; /* Process virtual address */
|
||||
__u64 length; /* Length of mapping (bytes)*/
|
||||
__u64 iova; /* IO virtual address */
|
||||
};
|
||||
|
||||
struct fpga_port_dma_unmap {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u64 iova; /* IO virtual address */
|
||||
};
|
||||
|
||||
struct fpga_port_umsg_cfg {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u32 hint_bitmap; /* UMSG Hint Mode Bitmap */
|
||||
};
|
||||
|
||||
struct fpga_port_umsg_base_addr {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u64 iova; /* IO virtual address */
|
||||
};
|
||||
|
||||
struct fpga_port_err_irq_set {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__s32 evtfd; /* Eventfd handler */
|
||||
};
|
||||
|
||||
struct fpga_port_uafu_irq_set {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u32 start; /* First irq number */
|
||||
__u32 count; /* The number of eventfd handler */
|
||||
__s32 evtfd[8]; /* Eventfd handler; assume no more than 8 for simplicity */
|
||||
};
|
||||
|
||||
struct fpga_port_uafu_mmap {
|
||||
__u32 argsz; /* Structure length, ignored */
|
||||
__u32 flags; /* MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_HUGETLB | MAP_1G_HUGEPAGE */
|
||||
__u64 addr; /* Always zero, ignored */
|
||||
__u64 len; /* Length of DMA region to allocate in untrusted memory */
|
||||
__u64 local_addr; /* Output address of the allocated DMA region in untrusted memory */
|
||||
};
|
||||
|
||||
struct fpga_port_uafu_unmap {
|
||||
__u32 argsz; /* Structure length, ignored */
|
||||
__u32 flags; /* Flags, ignored */
|
||||
__u64 addr; /* Base address of DMA region allocated in untrusted memory */
|
||||
__u64 len; /* Length of DMA region allocated in untrusted memory */
|
||||
};
|
||||
|
||||
struct fpga_fme_port_pr {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u32 port_id;
|
||||
__u32 buffer_size;
|
||||
__u64 buffer_address; /* Userspace address to the buffer for PR */
|
||||
__u64 status; /* HW error code if ioctl returns -EIO */
|
||||
};
|
||||
|
||||
struct fpga_fme_port_release {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u32 port_id;
|
||||
};
|
||||
|
||||
struct fpga_fme_port_assign {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u32 port_id;
|
||||
};
|
||||
|
||||
struct fpga_fme_info {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__u32 capability; /* The capability of FME device */
|
||||
};
|
||||
|
||||
struct fpga_fme_err_irq_set {
|
||||
__u32 argsz; /* Structure length */
|
||||
__u32 flags; /* Zero for now */
|
||||
__s32 evtfd; /* Eventfd handler */
|
||||
};
|
||||
|
||||
|
||||
static int ioctl_passthru (struct shim_handle * hdl, unsigned int cmd, unsigned long arg) {
|
||||
PAL_ARG* pal_arg = NULL;
|
||||
PAL_NUM ninputs = 0, noutputs = 0;
|
||||
PAL_ARG* inputs = NULL;
|
||||
PAL_ARG* outputs = NULL;
|
||||
|
||||
// Don't change these macros
|
||||
|
||||
#define SET_ARG_TYPE(type) \
|
||||
do { \
|
||||
pal_arg = __alloca(sizeof(PAL_ARG)); \
|
||||
pal_arg->val = (PAL_PTR) arg; \
|
||||
pal_arg->size = sizeof(type); \
|
||||
pal_arg->off = 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define SET_NOUTPUTS(num) \
|
||||
do { \
|
||||
outputs = __alloca(sizeof(PAL_ARG) * (num)); \
|
||||
} while (0)
|
||||
|
||||
#define ADD_OUTPUT_SIZE(type, field, fsize) \
|
||||
do { \
|
||||
type* __a = (void *) arg; \
|
||||
outputs[noutputs].val = (PAL_PTR) __a->field; \
|
||||
outputs[noutputs].size = (fsize); \
|
||||
outputs[noutputs].off = offsetof(type, field); \
|
||||
noutputs++; \
|
||||
} while (0)
|
||||
|
||||
#define SET_NINPUTS(num) \
|
||||
do { \
|
||||
inputs = __alloca(sizeof(PAL_ARG) * (num)); \
|
||||
} while (0)
|
||||
|
||||
#define ADD_INPUT_SIZE(type, field, fsize) \
|
||||
do { \
|
||||
type* __a = (void *) arg; \
|
||||
inputs[ninputs].val = (PAL_PTR) __a->field; \
|
||||
inputs[ninputs].size = (fsize); \
|
||||
inputs[ninputs].off = offsetof(type, field); \
|
||||
ninputs++; \
|
||||
} while (0)
|
||||
|
||||
|
||||
// List the all ioctl opcodes allowed for passthrough
|
||||
switch(cmd) {
|
||||
// This is an example: DUMMY_IOCTL_PRINT will print out the string
|
||||
// in the argument to the kernel log.
|
||||
case DUMMY_IOCTL_PRINT: {
|
||||
struct dummy_print* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct dummy_print);
|
||||
SET_NOUTPUTS(1);
|
||||
ADD_OUTPUT_SIZE(struct dummy_print, str, __arg->size);
|
||||
// Specify input size if necessary
|
||||
break;
|
||||
}
|
||||
|
||||
// Dmitrii Kuvaiskii: list of ioctls for North Cove FPGA driver
|
||||
case FPGA_GET_API_VERSION:
|
||||
case FPGA_CHECK_EXTENSION:
|
||||
case FPGA_PORT_RESET:
|
||||
case FPGA_PORT_UMSG_ENABLE:
|
||||
case FPGA_PORT_UMSG_DISABLE:
|
||||
break;
|
||||
|
||||
case FPGA_PORT_GET_INFO: {
|
||||
struct fpga_port_info* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_port_info);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_PORT_GET_REGION_INFO: {
|
||||
struct fpga_port_region_info* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_port_region_info);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_PORT_DMA_MAP: {
|
||||
struct fpga_port_dma_map* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_port_dma_map);
|
||||
/* TODO: This ioctl fails because user_addr is in enclave space
|
||||
* not available for the kernel driver! */
|
||||
debug("ioctl(FPGA_PORT_DMA_MAP): user_addr=%p length=%lu\n",
|
||||
__arg->user_addr, __arg->length);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_PORT_DMA_UNMAP: {
|
||||
struct fpga_port_dma_unmap* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_port_dma_unmap);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_PORT_UMSG_SET_MODE: {
|
||||
struct fpga_port_umsg_cfg* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_port_umsg_cfg);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_PORT_UMSG_SET_BASE_ADDR: {
|
||||
struct fpga_port_umsg_base_addr* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_port_umsg_base_addr);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_PORT_ERR_SET_IRQ: {
|
||||
struct fpga_port_err_irq_set* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_port_err_irq_set);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_PORT_UAFU_SET_IRQ: {
|
||||
struct fpga_port_uafu_irq_set* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_port_uafu_irq_set);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_PORT_UAFU_MMAP: {
|
||||
/* special case: instead of ioctl, allocate untrusted memory */
|
||||
#define PAL_ALLOC_DMAREGION 0x4000
|
||||
struct fpga_port_uafu_mmap* __arg = (void *) arg;
|
||||
__arg->addr = 0x0UL;
|
||||
void* ret = (void *) DkVirtualMemoryAlloc(/* addr */ (void*)__arg->addr,
|
||||
/* size */ __arg->len,
|
||||
/* alloc_type */ PAL_ALLOC_DMAREGION,
|
||||
/* prot abused as flags */ __arg->flags);
|
||||
if (!ret) {
|
||||
__arg->local_addr = 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
__arg->local_addr = (uint64_t) ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
case FPGA_PORT_UAFU_UNMAP: {
|
||||
/* special case: instead of ioctl, deallocate untrusted memory */
|
||||
struct fpga_port_uafu_unmap* __arg = (void *) arg;
|
||||
DkVirtualMemoryFree((void*)__arg->addr, __arg->len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case FPGA_FME_PORT_PR: {
|
||||
struct fpga_fme_port_pr* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_fme_port_pr);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_FME_PORT_RELEASE: {
|
||||
struct fpga_fme_port_release* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_fme_port_release);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_FME_PORT_ASSIGN: {
|
||||
struct fpga_fme_port_assign* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_fme_port_assign);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_FME_GET_INFO: {
|
||||
struct fpga_fme_info* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_fme_info);
|
||||
break;
|
||||
}
|
||||
|
||||
case FPGA_FME_ERR_SET_IRQ: {
|
||||
struct fpga_fme_err_irq_set* __arg = (void *) arg;
|
||||
SET_ARG_TYPE(struct fpga_fme_err_irq_set);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
PAL_NATIVE_ERRNO = 0;
|
||||
PAL_NUM retval = DkHostExtensionCall(hdl->pal_handle, cmd, pal_arg, noutputs, outputs,
|
||||
ninputs, inputs);
|
||||
return (PAL_NATIVE_ERRNO == 0) ? (int) retval : -PAL_ERRNO;
|
||||
}
|
||||
|
||||
@@ -134,6 +134,11 @@ void * shim_do_mmap (void * addr, size_t length, int prot, int flags, int fd,
|
||||
return (void *) ret;
|
||||
}
|
||||
|
||||
if (ret_addr != addr) {
|
||||
bkeep_munmap(addr, length, flags);
|
||||
bkeep_mmap(ret_addr, length, prot, flags, hdl, offset, NULL);
|
||||
}
|
||||
|
||||
ADD_PROFILE_OCCURENCE(mmap, length);
|
||||
return ret_addr;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,20 @@
|
||||
#include <linux/stat.h>
|
||||
#include <linux/fcntl.h>
|
||||
|
||||
int eventfds[128] = {0};
|
||||
int eventfds_cnt = 0;
|
||||
|
||||
int shim_do_eventfd2(int init, int flags) {
|
||||
PAL_NATIVE_ERRNO = 0;
|
||||
PAL_NUM retval = DkEventfdPassthrough(init, flags);
|
||||
if (PAL_NATIVE_ERRNO == 0) {
|
||||
/* TODO: need some lock here but don't care for now */
|
||||
assert(eventfds_cnt < 128);
|
||||
eventfds[eventfds_cnt++] = (int) retval;
|
||||
}
|
||||
return (PAL_NATIVE_ERRNO == 0) ? (int) retval : -PAL_ERRNO;
|
||||
}
|
||||
|
||||
int do_handle_read (struct shim_handle * hdl, void * buf, int count)
|
||||
{
|
||||
if (!(hdl->acc_mode & MAY_READ))
|
||||
@@ -58,6 +72,14 @@ int do_handle_read (struct shim_handle * hdl, void * buf, int count)
|
||||
|
||||
size_t shim_do_read (int fd, void * buf, size_t count)
|
||||
{
|
||||
/* if this fd is eventfd, then do pass-through read */
|
||||
for (int i = 0; i < eventfds_cnt; i++) {
|
||||
if (fd == eventfds[i]) {
|
||||
int ret = DkReadPassthrough((PAL_NUM)fd, (PAL_PTR)buf, (PAL_NUM)count);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!buf || test_user_memory(buf, count, true))
|
||||
return -EFAULT;
|
||||
|
||||
@@ -89,6 +111,14 @@ int do_handle_write (struct shim_handle * hdl, const void * buf, int count)
|
||||
|
||||
size_t shim_do_write (int fd, const void * buf, size_t count)
|
||||
{
|
||||
/* if this fd is eventfd, then do pass-through write */
|
||||
for (int i = 0; i < eventfds_cnt; i++) {
|
||||
if (fd == eventfds[i]) {
|
||||
int ret = DkWritePassthrough((PAL_NUM)fd, (PAL_PTR)buf, (PAL_NUM)count);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!buf || test_user_memory((void *) buf, count, false))
|
||||
return -EFAULT;
|
||||
|
||||
@@ -103,6 +133,14 @@ size_t shim_do_write (int fd, const void * buf, size_t count)
|
||||
|
||||
int shim_do_open (const char * file, int flags, mode_t mode)
|
||||
{
|
||||
if (strlen(file) >= 15 && strpartcmp_static(file, "/sys/class/fpga")) {
|
||||
char hardlink[128] = {'\0'};
|
||||
strcpy_static(hardlink, "/sys/devices/pci0000:00/0000:00:01.1/0000:02:00.0/fpga/", sizeof(hardlink));
|
||||
memcpy(hardlink + strlen(hardlink), file + 15, strlen(file) - 15);
|
||||
file = hardlink;
|
||||
debug("[FPGA DEMO] opening hardlink file: %s\n", file);
|
||||
}
|
||||
|
||||
if (!file || test_user_string(file))
|
||||
return -EFAULT;
|
||||
|
||||
@@ -112,7 +150,6 @@ int shim_do_open (const char * file, int flags, mode_t mode)
|
||||
struct shim_handle * hdl = get_new_handle();
|
||||
if (!hdl)
|
||||
return -ENOMEM;
|
||||
|
||||
int ret = 0;
|
||||
ret = open_namei(hdl, NULL, file, flags, mode, NULL);
|
||||
if (ret < 0)
|
||||
@@ -164,6 +201,18 @@ out:
|
||||
|
||||
int shim_do_close (int fd)
|
||||
{
|
||||
/* if this fd is eventfd, then do pass-through close */
|
||||
for (int i = 0; i < eventfds_cnt; i++) {
|
||||
if (fd == eventfds[i]) {
|
||||
/* TODO: need some lock here but don't care for now */
|
||||
int ret = DkClosePassthrough((PAL_NUM)fd);
|
||||
for (int j = i; j < eventfds_cnt-1; j++)
|
||||
eventfds[j] = eventfds[j+1];
|
||||
eventfds_cnt--;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
struct shim_handle * handle = detach_fd_handle(fd, NULL, NULL);
|
||||
if (!handle)
|
||||
return -EBADF;
|
||||
@@ -197,6 +246,13 @@ off_t shim_do_lseek (int fd, off_t offset, int origin)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Dmitrii Kuvaiskii: special case of lseek(0, SEEK_SET) on pseudo-device */
|
||||
if ((origin == SEEK_SET) && (offset == 0) &&
|
||||
(hdl->info.file.type == FILE_TTY)) {
|
||||
put_handle(hdl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = fs->fs_ops->seek(hdl, offset, origin);
|
||||
out:
|
||||
put_handle(hdl);
|
||||
|
||||
@@ -385,8 +385,34 @@ done_polling:
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int eventfds[128];
|
||||
extern int eventfds_cnt;
|
||||
|
||||
int shim_do_poll (struct pollfd * fds, nfds_t nfds, int timeout)
|
||||
{
|
||||
/* if the first fd in fds is eventfd, then do pass-through poll
|
||||
* (this assumes that _all_ other fds are also eventfds) */
|
||||
if (nfds > 0 && fds) {
|
||||
for (int i = 0; i < eventfds_cnt; i++) {
|
||||
if (fds[0].fd == eventfds[i]) {
|
||||
PAL_POLLFD dkfds[nfds];
|
||||
|
||||
for (nfds_t j = 0; j < nfds; j++) {
|
||||
dkfds[j].fd = (PAL_NUM)fds[j].fd;
|
||||
dkfds[j].events = (PAL_NUM)fds[j].events;
|
||||
dkfds[j].revents = (PAL_NUM)fds[j].revents;
|
||||
}
|
||||
|
||||
int ret = DkPollPassthrough((PAL_POLLFD*) &dkfds, (PAL_NUM)nfds, (PAL_NUM)timeout);
|
||||
|
||||
for (nfds_t j = 0; j < nfds; j++)
|
||||
fds[j].revents = (short)dkfds[j].revents;
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct shim_thread * cur = get_cur_thread();
|
||||
|
||||
struct poll_handle * polls =
|
||||
|
||||
@@ -28,11 +28,18 @@
|
||||
|
||||
#include <pal.h>
|
||||
#include <pal_error.h>
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
int shim_do_stat (const char * file, struct stat * stat)
|
||||
{
|
||||
if (strlen(file) >= 15 && strpartcmp_static(file, "/sys/class/fpga")) {
|
||||
char hardlink[128] = {'\0'};
|
||||
strcpy_static(hardlink, "/sys/devices/pci0000:00/0000:00:01.1/0000:02:00.0/fpga/", sizeof(hardlink));
|
||||
memcpy(hardlink + strlen(hardlink), file + 15, strlen(file) - 15);
|
||||
file = hardlink;
|
||||
debug("[FPGA DEMO] stating hardlink file: %s\n", file);
|
||||
}
|
||||
|
||||
if (!file || test_user_string(file))
|
||||
return -EFAULT;
|
||||
|
||||
@@ -61,6 +68,14 @@ out:
|
||||
|
||||
int shim_do_lstat (const char * file, struct stat * stat)
|
||||
{
|
||||
if (strlen(file) >= 15 && strpartcmp_static(file, "/sys/class/fpga")) {
|
||||
char hardlink[128] = {'\0'};
|
||||
strcpy_static(hardlink, "/sys/devices/pci0000:00/0000:00:01.1/0000:02:00.0/fpga/", sizeof(hardlink));
|
||||
memcpy(hardlink + strlen(hardlink), file + 15, strlen(file) - 15);
|
||||
file = hardlink;
|
||||
debug("[FPGA DEMO] stating hardlink file: %s\n", file);
|
||||
}
|
||||
|
||||
if (!file || test_user_string(file))
|
||||
return -EFAULT;
|
||||
|
||||
@@ -119,13 +134,20 @@ int shim_do_readlink (const char * file, char * buf, size_t bufsize)
|
||||
if (bufsize <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (strlen(file) >= 15 && strpartcmp_static(file, "/sys/class/fpga")) {
|
||||
char hardlink[128] = {'\0'};
|
||||
strcpy_static(hardlink, "/sys/devices/pci0000:00/0000:00:01.1/0000:02:00.0/fpga/", sizeof(hardlink));
|
||||
memcpy(hardlink + strlen(hardlink), file + 15, strlen(file) - 15);
|
||||
memcpy(buf, hardlink, strlen(hardlink));
|
||||
return strlen(hardlink);
|
||||
}
|
||||
|
||||
int ret;
|
||||
struct shim_dentry * dent = NULL;
|
||||
struct shim_qstr qstr = QSTR_INIT;
|
||||
|
||||
if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS, &dent, NULL)) < 0)
|
||||
return ret;
|
||||
|
||||
ret = -EINVAL;
|
||||
/* The correct behavior is to return -EINVAL if file is not a
|
||||
symbolic link */
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int fd = open("/sys/devices/pci0000:00/0000:00:01.1/0000:02:00.0/fpga/intel-fpga-dev.0/device/device", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void* mem = mmap(NULL, 4096, PROT_READ, MAP_SHARED|MAP_FILE,
|
||||
fd, 0);
|
||||
|
||||
if (mem != (void*)-1) {
|
||||
fprintf(stderr, "mapped /dev/host-random at %p\n", mem);
|
||||
} else {
|
||||
perror("mmap");
|
||||
}
|
||||
|
||||
char data[16] = {'\0'};
|
||||
if (read(fd, data, 16) < 0) {
|
||||
perror("file read");
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr, "data = %s\n", data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.env.LD_LIBRARY_PATH = /lib
|
||||
loader.debug_type = inline
|
||||
|
||||
fs.mount.lib.type = chroot
|
||||
fs.mount.lib.path = /lib
|
||||
fs.mount.lib.uri = file:$(LIBCDIR)
|
||||
|
||||
fs.mount.bin.type = chroot
|
||||
fs.mount.bin.path = /bin
|
||||
fs.mount.bin.uri = file:/bin
|
||||
|
||||
fs.mount.random.type = chroot
|
||||
fs.mount.random.path = /sys/devices/pci0000:00/0000:00:01.1/0000:02:00.0/fpga/intel-fpga-dev.0/device/device
|
||||
fs.mount.random.uri = dev:tty,/sys/devices/pci0000:00/0000:00:01.1/0000:02:00.0/fpga/intel-fpga-dev.0/device/device
|
||||
|
||||
# sgx-related
|
||||
sgx.trusted_files.ld = file:$(LIBCDIR)/ld-linux-x86-64.so.2
|
||||
sgx.trusted_files.libc = file:$(LIBCDIR)/libc.so.6
|
||||
sgx.trusted_files.libdl = file:$(LIBCDIR)/libdl.so.2
|
||||
sgx.trusted_files.libm = file:$(LIBCDIR)/libm.so.6
|
||||
sgx.trusted_files.libpthread = file:$(LIBCDIR)/libpthread.so.0
|
||||
@@ -0,0 +1,50 @@
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "ioctl-dummy-driver/dummy.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd = open("/dev/dummy", O_RDWR);
|
||||
if (fd < 0) {
|
||||
perror("open");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
struct dummy_print arg;
|
||||
arg.str = argv[i];
|
||||
arg.size = strlen(argv[i]);
|
||||
|
||||
if (ioctl(fd, DUMMY_IOCTL_PRINT, &arg)) {
|
||||
perror("ioctl");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "wrote %s to kernel\n", argv[i]);
|
||||
}
|
||||
|
||||
void *mem = mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE,
|
||||
fd, 0);
|
||||
|
||||
if (!mem) {
|
||||
perror("mmap");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "mapped /dev/dummy at %p\n", mem);
|
||||
for (int i = 0; i < 4096; i++)
|
||||
if (((unsigned char *) mem)[i]) {
|
||||
perror("memory read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
loader.preload = file:$(SHIMPATH)
|
||||
loader.env.LD_LIBRARY_PATH = /lib
|
||||
loader.debug_type = inline
|
||||
|
||||
fs.mount.lib.type = chroot
|
||||
fs.mount.lib.path = /lib
|
||||
fs.mount.lib.uri = file:$(LIBCDIR)
|
||||
|
||||
fs.mount.bin.type = chroot
|
||||
fs.mount.bin.path = /bin
|
||||
fs.mount.bin.uri = file:/bin
|
||||
|
||||
fs.mount.ioctl.type = chroot
|
||||
fs.mount.ioctl.path = /dev/dummy
|
||||
fs.mount.ioctl.uri = file:/dev/dummy
|
||||
|
||||
# sgx-related
|
||||
sgx.trusted_files.ld = file:$(LIBCDIR)/ld-linux-x86-64.so.2
|
||||
sgx.trusted_files.libc = file:$(LIBCDIR)/libc.so.6
|
||||
sgx.trusted_files.libdl = file:$(LIBCDIR)/libdl.so.2
|
||||
sgx.trusted_files.libm = file:$(LIBCDIR)/libm.so.6
|
||||
sgx.trusted_files.libpthread = file:$(LIBCDIR)/libpthread.so.0
|
||||
sgx.allowed_files.ioctl = file:/dev/dummy
|
||||
@@ -150,3 +150,88 @@ DkCpuIdRetrieve (PAL_IDX leaf, PAL_IDX subleaf, PAL_IDX values[4])
|
||||
|
||||
LEAVE_PAL_CALL_RETURN(PAL_TRUE);
|
||||
}
|
||||
|
||||
PAL_NUM DkHostExtensionCall (PAL_HANDLE handle, PAL_NUM op, PAL_ARG* arg, PAL_NUM noutputs, PAL_ARG* outputs,
|
||||
PAL_NUM ninputs, PAL_ARG* inputs)
|
||||
{
|
||||
ENTER_PAL_CALL(DkHostExtensionCall);
|
||||
|
||||
if (!handle) {
|
||||
_DkRaiseFailure(PAL_ERROR_INVAL);
|
||||
LEAVE_PAL_CALL_RETURN(0);
|
||||
}
|
||||
|
||||
if (UNKNOWN_HANDLE(handle)) {
|
||||
_DkRaiseFailure(PAL_ERROR_BADHANDLE);
|
||||
LEAVE_PAL_CALL_RETURN(0);
|
||||
}
|
||||
|
||||
int64_t status = _DkHostExtensionCall(handle, op, arg, noutputs, outputs, ninputs, inputs);
|
||||
|
||||
if (status < 0) {
|
||||
_DkRaiseFailure(-status);
|
||||
status = 0;
|
||||
}
|
||||
|
||||
LEAVE_PAL_CALL_RETURN(status);
|
||||
}
|
||||
|
||||
PAL_NUM DkEventfdPassthrough(PAL_NUM initval, PAL_NUM flags) {
|
||||
ENTER_PAL_CALL(DkEventfdPassthrough);
|
||||
|
||||
int ret = _DkEventfdPassthrough(initval, flags);
|
||||
if (ret < 0) {
|
||||
_DkRaiseFailure(-ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
LEAVE_PAL_CALL_RETURN(ret);
|
||||
}
|
||||
|
||||
PAL_NUM DkPollPassthrough(PAL_POLLFD* fds, PAL_NUM nfds, PAL_NUM timeout) {
|
||||
ENTER_PAL_CALL(DkPollPassthrough);
|
||||
|
||||
int ret = _DkPollPassthrough(fds, nfds, timeout);
|
||||
if (ret < 0) {
|
||||
_DkRaiseFailure(-ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
LEAVE_PAL_CALL_RETURN(ret);
|
||||
}
|
||||
|
||||
PAL_NUM DkReadPassthrough(PAL_NUM fd, PAL_PTR buf, PAL_NUM count) {
|
||||
ENTER_PAL_CALL(DkReadPassthrough);
|
||||
|
||||
int ret = _DkReadPassthrough(fd, buf, count);
|
||||
if (ret < 0) {
|
||||
_DkRaiseFailure(-ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
LEAVE_PAL_CALL_RETURN(ret);
|
||||
}
|
||||
|
||||
PAL_NUM DkWritePassthrough(PAL_NUM fd, PAL_PTR buf, PAL_NUM count) {
|
||||
ENTER_PAL_CALL(DkWritePassthrough);
|
||||
|
||||
int ret = _DkWritePassthrough(fd, buf, count);
|
||||
if (ret < 0) {
|
||||
_DkRaiseFailure(-ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
LEAVE_PAL_CALL_RETURN(ret);
|
||||
}
|
||||
|
||||
PAL_NUM DkClosePassthrough(PAL_NUM fd) {
|
||||
ENTER_PAL_CALL(DkClosePassthrough);
|
||||
|
||||
int ret = _DkClosePassthrough(fd);
|
||||
if (ret < 0) {
|
||||
_DkRaiseFailure(-ret);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
LEAVE_PAL_CALL_RETURN(ret);
|
||||
}
|
||||
|
||||
@@ -65,13 +65,18 @@ static int parse_device_uri(const char ** uri, char ** type, struct handle_ops *
|
||||
|
||||
for (p = u ; (*p) && (*p) != ',' && (*p) != '/' ; p++);
|
||||
|
||||
if (strpartcmp_static(u, "tty"))
|
||||
/*
|
||||
* For terminal devices, Graphene supports two types of URIs:
|
||||
* dev:tty => Standard terminal
|
||||
* dev:tty,<host-level path> => Local terminal devices (e.g., virtual TTY)
|
||||
*/
|
||||
if (strpartcmp_static(u, "tty") && (!(*p) || *p == ','))
|
||||
dops = &term_ops;
|
||||
|
||||
if (!dops)
|
||||
return -PAL_ERROR_NOTSUPPORT;
|
||||
|
||||
*uri = (*p) ? p + 1 : p;
|
||||
*uri = (*p) ? p + 1 : NULL;
|
||||
if (type) {
|
||||
*type = malloc_copy(u, p - u + 1);
|
||||
if (!*type)
|
||||
@@ -96,11 +101,21 @@ static int term_attrquerybyhdl (PAL_HANDLE hdl,
|
||||
PAL_STREAM_ATTR * attr);
|
||||
|
||||
/* Method to open standard terminal */
|
||||
static int open_standard_term (PAL_HANDLE * handle, const char * param,
|
||||
int access)
|
||||
{
|
||||
if (param)
|
||||
return -PAL_ERROR_NOTIMPLEMENTED;
|
||||
static int open_standard_term(PAL_HANDLE* handle, const char* path, int access) {
|
||||
/* remove the "file:" prefix */
|
||||
if (path) {
|
||||
const char *p;
|
||||
for (p = path; (*p) && (*p) != ':'; p++);
|
||||
if ((*p) == ':' && (p - path == 4) && strpartcmp_static(path, "file:"))
|
||||
path = path + 5;
|
||||
}
|
||||
|
||||
int dev_fd = -1;
|
||||
if (path) {
|
||||
dev_fd = ocall_open(path, access, 0);
|
||||
if (IS_ERR(dev_fd))
|
||||
return unix_to_pal_error(ERRNO(dev_fd));
|
||||
}
|
||||
|
||||
PAL_HANDLE hdl = malloc(HANDLE_SIZE(dev));
|
||||
SET_HANDLE_TYPE(hdl, dev);
|
||||
@@ -108,12 +123,12 @@ static int open_standard_term (PAL_HANDLE * handle, const char * param,
|
||||
|
||||
if (!(access & PAL_ACCESS_WRONLY)) {
|
||||
HANDLE_HDR(hdl)->flags |= RFD(0);
|
||||
hdl->dev.fd_in = 0;
|
||||
hdl->dev.fd_in = dev_fd != -1 ? dev_fd : 0;
|
||||
}
|
||||
|
||||
if (access & (PAL_ACCESS_WRONLY|PAL_ACCESS_RDWR)) {
|
||||
HANDLE_HDR(hdl)->flags |= WFD(1);
|
||||
hdl->dev.fd_out = 1;
|
||||
hdl->dev.fd_out = dev_fd != -1 ? dev_fd : 1;
|
||||
}
|
||||
|
||||
*handle = hdl;
|
||||
@@ -132,24 +147,7 @@ static int term_open (PAL_HANDLE *handle, const char * type, const char * uri,
|
||||
!WITHIN_MASK(options, PAL_OPTION_MASK))
|
||||
return -PAL_ERROR_INVAL;
|
||||
|
||||
const char * term = NULL;
|
||||
const char * param = NULL;
|
||||
|
||||
const char * tmp = uri;
|
||||
while (*tmp) {
|
||||
if (!term && *tmp == '/')
|
||||
term = tmp + 1;
|
||||
if (*tmp == ',') {
|
||||
param = param + 1;
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if (term)
|
||||
return -PAL_ERROR_NOTIMPLEMENTED;
|
||||
|
||||
return open_standard_term(handle, param, access);
|
||||
return open_standard_term(handle, uri, access);
|
||||
}
|
||||
|
||||
static int term_close (PAL_HANDLE handle)
|
||||
|
||||
@@ -196,11 +196,15 @@ static int file_map (PAL_HANDLE handle, void ** addr, int prot,
|
||||
* we allow mapping the file outside the enclave, if the library OS
|
||||
* does not request a specific address.
|
||||
*/
|
||||
if (!mem && !stubs && !(prot & PAL_PROT_WRITECOPY)) {
|
||||
if (!stubs && !(prot & PAL_PROT_WRITECOPY)) {
|
||||
mem = NULL;
|
||||
ret = ocall_map_untrusted(handle->file.fd, offset, size,
|
||||
HOST_PROT(prot), &mem);
|
||||
if (!IS_ERR(ret))
|
||||
if (!IS_ERR(ret)) {
|
||||
SGX_DBG(DBG_I, "file:%s is mapped outside the enclave\n",
|
||||
handle->file.realpath);
|
||||
*addr = mem;
|
||||
}
|
||||
return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,11 +65,22 @@ bool _DkCheckMemoryMappable (const void * addr, size_t size)
|
||||
|
||||
int _DkVirtualMemoryAlloc (void ** paddr, uint64_t size, int alloc_type, int prot)
|
||||
{
|
||||
#if 0
|
||||
if (!WITHIN_MASK(prot, PAL_PROT_MASK))
|
||||
return -PAL_ERROR_INVAL;
|
||||
#endif
|
||||
|
||||
void * addr = *paddr, * mem;
|
||||
|
||||
/* special case: alloc in untrusted memory for DMA with FPGA;
|
||||
* note that we abuse prot argument as flags and also abuse offset */
|
||||
if (alloc_type & PAL_ALLOC_DMAREGION) {
|
||||
int ret = ocall_map_untrusted(/*fd=*/-1, /*offset=*/prot, size, PROT_READ|PROT_WRITE, paddr);
|
||||
if (IS_ERR(ret))
|
||||
return -PAL_ERROR_INVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((alloc_type & PAL_ALLOC_INTERNAL) && addr)
|
||||
return -PAL_ERROR_INVAL;
|
||||
|
||||
|
||||
@@ -180,3 +180,54 @@ int _DkCpuIdRetrieve (unsigned int leaf, unsigned int subleaf,
|
||||
add_cpuid_to_cache(leaf, subleaf, values);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t _DkHostExtensionCall (PAL_HANDLE handle, PAL_NUM op, PAL_ARG* arg, int noutputs, PAL_ARG* outputs,
|
||||
int ninputs, PAL_ARG* inputs) {
|
||||
// The handle needs to have at least one fd
|
||||
if (!(HANDLE_HDR(handle)->flags & (RFD(0)|WFD(0))))
|
||||
return -PAL_ERROR_BADHANDLE;
|
||||
|
||||
uint64_t retval = 0;
|
||||
int ret = ocall_ioctl(handle->generic.fds[0], op, arg, noutputs, outputs,
|
||||
ninputs, inputs, &retval);
|
||||
return (ret < 0) ? ret : retval;
|
||||
}
|
||||
|
||||
|
||||
int _DkEventfdPassthrough(PAL_NUM initval, PAL_NUM flags) {
|
||||
int ret = ocall_eventfd_passthrough(initval, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _DkPollPassthrough(PAL_POLLFD* fds, PAL_NUM nfds, PAL_NUM timeout) {
|
||||
int64_t ocalltimeout = (int64_t)timeout;
|
||||
struct pollfd ocallfds[nfds];
|
||||
|
||||
for (PAL_NUM i = 0; i < nfds; i++) {
|
||||
ocallfds[i].fd = (int)fds[i].fd;
|
||||
ocallfds[i].events = (short)fds[i].events;
|
||||
ocallfds[i].revents = (short)fds[i].revents;
|
||||
}
|
||||
|
||||
int ret = ocall_poll((struct pollfd*) &ocallfds, (int)nfds, &ocalltimeout);
|
||||
|
||||
for (PAL_NUM i = 0; i < nfds; i++)
|
||||
fds[i].revents = (PAL_NUM)ocallfds[i].revents;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _DkReadPassthrough(PAL_NUM fd, PAL_PTR buf, PAL_NUM count) {
|
||||
int ret = ocall_read((int)fd, (void*)buf, (unsigned int)count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _DkWritePassthrough(PAL_NUM fd, PAL_PTR buf, PAL_NUM count) {
|
||||
int ret = ocall_write((int)fd, (const void*)buf, (unsigned int)count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int _DkClosePassthrough(PAL_NUM fd) {
|
||||
int ret = ocall_close((int)fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -158,8 +158,8 @@ void setup_pal_map (struct link_map * pal_map)
|
||||
|
||||
char buffer[BUFFER_LENGTH];
|
||||
snprintf(buffer, BUFFER_LENGTH,
|
||||
"add-symbol-file %s 0x%p -readnow -s .rodata 0x%p "
|
||||
"-s .dynamic 0x%p -s .data 0x%p -s .bss 0x%p",
|
||||
"add-symbol-file %s %p -readnow -s .rodata %p "
|
||||
"-s .dynamic %p -s .data %p -s .bss %p",
|
||||
pal_map->l_name,
|
||||
§ion_text, §ion_rodata, §ion_dynamic,
|
||||
§ion_data, §ion_bss);
|
||||
|
||||
@@ -1104,3 +1104,86 @@ int ocall_load_debug(const char * command)
|
||||
sgx_reset_ustack();
|
||||
return retval;
|
||||
}
|
||||
|
||||
int ocall_ioctl (int fd, uint64_t op, PAL_ARG* arg, int noutputs, PAL_ARG* outputs,
|
||||
int ninputs, PAL_ARG* inputs, uint64_t* retval) {
|
||||
int status = 0;
|
||||
|
||||
ms_ocall_ioctl_t* ms;
|
||||
ms = sgx_alloc_on_ustack(sizeof(*ms));
|
||||
if (!ms) {
|
||||
sgx_reset_ustack();
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ms->ms_fd = fd;
|
||||
ms->ms_op = op;
|
||||
ms->ms_arg = NULL;
|
||||
if (arg) {
|
||||
/* some ioctls have the third argument arg, perform deep copy to ustack */
|
||||
ms->ms_arg = sgx_copy_to_ustack(arg->val, arg->size);
|
||||
if (!ms->ms_arg) {
|
||||
sgx_reset_ustack();
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
for (int i = 0; i < noutputs; i++) {
|
||||
void* newptr = sgx_copy_to_ustack(outputs[i].val, outputs[i].size);
|
||||
if (!newptr) {
|
||||
sgx_reset_ustack();
|
||||
return -EPERM;
|
||||
}
|
||||
*(void**) (((uintptr_t) ms->ms_arg) + outputs[i].off) = newptr;
|
||||
}
|
||||
}
|
||||
|
||||
status = sgx_ocall(OCALL_IOCTL, ms);
|
||||
if (!status) {
|
||||
*retval = ms->ms_retval;
|
||||
|
||||
if (arg) {
|
||||
/* some ioctls have the third argument arg, perform deep copy from ustack */
|
||||
if (!sgx_copy_to_enclave(arg->val, arg->size, ms->ms_arg, arg->size)) {
|
||||
sgx_reset_ustack();
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
for (int i = 0; i < noutputs; i++) {
|
||||
*(void**) (((uintptr_t) arg->val) + outputs[i].off) = outputs[i].val;
|
||||
}
|
||||
|
||||
for (int i = 0; i < ninputs; i++) {
|
||||
void* newptr = *(void**) (((uintptr_t) ms->ms_arg) + inputs[i].off);
|
||||
if (!sgx_copy_to_enclave(inputs[i].val, inputs[i].size, newptr, inputs[i].size)) {
|
||||
sgx_reset_ustack();
|
||||
return -EPERM;
|
||||
}
|
||||
assert(*(void**) (((uintptr_t) arg->val) + inputs[i].off) == inputs[i].val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sgx_reset_ustack();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int ocall_eventfd_passthrough (unsigned int initval, int flags)
|
||||
{
|
||||
int retval = 0;
|
||||
ms_ocall_eventfd_passthrough_t * ms;
|
||||
|
||||
ms = sgx_alloc_on_ustack(sizeof(*ms));
|
||||
if (!ms) {
|
||||
sgx_reset_ustack();
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
ms->ms_initval = initval;
|
||||
ms->ms_flags = flags;
|
||||
|
||||
retval = sgx_ocall(OCALL_EVENTFD_PASSTHROUGH, ms);
|
||||
|
||||
sgx_reset_ustack();
|
||||
return retval;
|
||||
}
|
||||
|
||||
@@ -100,3 +100,8 @@ int ocall_rename (const char * oldpath, const char * newpath);
|
||||
int ocall_delete (const char * pathname);
|
||||
|
||||
int ocall_load_debug (const char * command);
|
||||
|
||||
int ocall_ioctl (int fd, uint64_t op, PAL_ARG* arg, int noutputs, PAL_ARG* outputs,
|
||||
int ninputs, PAL_ARG* inputs, uint64_t* retval);
|
||||
|
||||
int ocall_eventfd_passthrough (unsigned int initval, int flags);
|
||||
|
||||
@@ -53,6 +53,8 @@ enum {
|
||||
OCALL_RENAME,
|
||||
OCALL_DELETE,
|
||||
OCALL_LOAD_DEBUG,
|
||||
OCALL_IOCTL,
|
||||
OCALL_EVENTFD_PASSTHROUGH,
|
||||
OCALL_NR,
|
||||
};
|
||||
|
||||
@@ -262,4 +264,16 @@ typedef struct {
|
||||
unsigned int ms_tid;
|
||||
} ms_ocall_schedule_t;
|
||||
|
||||
typedef struct {
|
||||
int ms_fd;
|
||||
uint64_t ms_op;
|
||||
void* ms_arg;
|
||||
uint64_t ms_retval;
|
||||
} ms_ocall_ioctl_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int ms_initval;
|
||||
int ms_flags;
|
||||
} ms_ocall_eventfd_passthrough_t;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
@@ -42,6 +42,13 @@ PAL {
|
||||
DkSegmentRegister; # set segment register
|
||||
DkMemoryAvailableQuota;
|
||||
DkCpuIdRetrieve; # retrieve CPUID
|
||||
DkHostExtensionCall;
|
||||
|
||||
DkEventfdPassthrough;
|
||||
DkPollPassthrough;
|
||||
DkReadPassthrough;
|
||||
DkWritePassthrough;
|
||||
DkClosePassthrough;
|
||||
|
||||
# Debugging ABIs
|
||||
pal_printf; pal_snprintf; DkDebugAttachBinary; DkDebugDetachBinary;
|
||||
|
||||
@@ -58,10 +58,23 @@ static int sgx_ocall_map_untrusted(void * pms)
|
||||
ms_ocall_map_untrusted_t * ms = (ms_ocall_map_untrusted_t *) pms;
|
||||
void * addr;
|
||||
ODEBUG(OCALL_MAP_UNTRUSTED, ms);
|
||||
addr = (void *) INLINE_SYSCALL(mmap, 6, NULL, ms->ms_size,
|
||||
ms->ms_prot,
|
||||
MAP_FILE|MAP_SHARED,
|
||||
ms->ms_fd, ms->ms_offset);
|
||||
|
||||
if (ms->ms_fd == -1) {
|
||||
/* special case: alloc in untrusted memory for DMA with FPGA;
|
||||
* note that we abuse ms_offset as flags */
|
||||
addr = (void *) INLINE_SYSCALL(mmap, 6, NULL, ms->ms_size,
|
||||
ms->ms_prot,
|
||||
/* flags */ (int)ms->ms_offset,
|
||||
/* fd is ignored*/ -1,
|
||||
/* offset is ignored */ 0);
|
||||
|
||||
} else {
|
||||
addr = (void *) INLINE_SYSCALL(mmap, 6, NULL, ms->ms_size,
|
||||
ms->ms_prot,
|
||||
MAP_FILE|MAP_SHARED,
|
||||
ms->ms_fd, ms->ms_offset);
|
||||
}
|
||||
|
||||
if (IS_ERR_P(addr))
|
||||
return -ERRNO_P(addr);
|
||||
|
||||
@@ -657,6 +670,36 @@ static int sgx_ocall_load_debug(void * pms)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sgx_ocall_ioctl (void * pms)
|
||||
{
|
||||
ms_ocall_ioctl_t * ms = (ms_ocall_ioctl_t *) pms;
|
||||
int64_t retval;
|
||||
ODEBUG(OCALL_IOCTL, ms);
|
||||
|
||||
retval = INLINE_SYSCALL(ioctl, 3, ms->ms_fd, ms->ms_op, ms->ms_arg);
|
||||
|
||||
if (IS_ERR(retval)) {
|
||||
return unix_to_pal_error(ERRNO(retval));
|
||||
} else {
|
||||
ms->ms_retval = retval;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int sgx_ocall_eventfd_passthrough (void * pms)
|
||||
{
|
||||
ms_ocall_eventfd_passthrough_t * ms = (ms_ocall_eventfd_passthrough_t *) pms;
|
||||
int64_t retval;
|
||||
ODEBUG(OCALL_EVENTFD_PASSTHROUGH, ms);
|
||||
|
||||
retval = INLINE_SYSCALL(eventfd2, 2, ms->ms_initval, ms->ms_flags);
|
||||
|
||||
if (IS_ERR(retval))
|
||||
return unix_to_pal_error(ERRNO(retval));
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
sgx_ocall_fn_t ocall_table[OCALL_NR] = {
|
||||
[OCALL_EXIT] = sgx_ocall_exit,
|
||||
[OCALL_PRINT_STRING] = sgx_ocall_print_string,
|
||||
@@ -695,6 +738,9 @@ sgx_ocall_fn_t ocall_table[OCALL_NR] = {
|
||||
[OCALL_RENAME] = sgx_ocall_rename,
|
||||
[OCALL_DELETE] = sgx_ocall_delete,
|
||||
[OCALL_LOAD_DEBUG] = sgx_ocall_load_debug,
|
||||
[OCALL_IOCTL] = sgx_ocall_ioctl,
|
||||
|
||||
[OCALL_EVENTFD_PASSTHROUGH] = sgx_ocall_eventfd_passthrough
|
||||
};
|
||||
|
||||
#define EDEBUG(code, ms) do {} while (0)
|
||||
|
||||
@@ -65,13 +65,18 @@ static int parse_device_uri(const char** uri, char** type, struct handle_ops** o
|
||||
for (p = u; (*p) && (*p) != ',' && (*p) != '/'; p++)
|
||||
;
|
||||
|
||||
if (strpartcmp_static(u, "tty"))
|
||||
/*
|
||||
* For terminal devices, Graphene supports two types of URIs:
|
||||
* dev:tty => Standard terminal
|
||||
* dev:tty,<host-level path> => Local terminal devices (e.g., virtual TTY)
|
||||
*/
|
||||
if (strpartcmp_static(u, "tty") && (!(*p) || *p == ','))
|
||||
dops = &term_ops;
|
||||
|
||||
if (!dops)
|
||||
return -PAL_ERROR_NOTSUPPORT;
|
||||
|
||||
*uri = (*p) ? p + 1 : p;
|
||||
*uri = (*p) ? p + 1 : NULL;
|
||||
if (type) {
|
||||
*type = malloc_copy(u, p - u + 1);
|
||||
if (!*type)
|
||||
@@ -91,9 +96,13 @@ static int term_attrquery(const char* type, const char* uri, PAL_STREAM_ATTR* at
|
||||
static int term_attrquerybyhdl(PAL_HANDLE hdl, PAL_STREAM_ATTR* attr);
|
||||
|
||||
/* Method to open standard terminal */
|
||||
static int open_standard_term(PAL_HANDLE* handle, const char* param, int access) {
|
||||
if (param)
|
||||
return -PAL_ERROR_NOTIMPLEMENTED;
|
||||
static int open_standard_term(PAL_HANDLE* handle, const char* path, int access) {
|
||||
int dev_fd = -1;
|
||||
if (path) {
|
||||
dev_fd = INLINE_SYSCALL(open, 3, path, access, 0);
|
||||
if (IS_ERR(dev_fd))
|
||||
return unix_to_pal_error(ERRNO(dev_fd));
|
||||
}
|
||||
|
||||
PAL_HANDLE hdl = malloc(HANDLE_SIZE(dev));
|
||||
SET_HANDLE_TYPE(hdl, dev);
|
||||
@@ -101,12 +110,12 @@ static int open_standard_term(PAL_HANDLE* handle, const char* param, int access)
|
||||
|
||||
if (!(access & PAL_ACCESS_WRONLY)) {
|
||||
HANDLE_HDR(hdl)->flags |= RFD(0);
|
||||
hdl->dev.fd_in = 0;
|
||||
hdl->dev.fd_in = dev_fd != -1 ? dev_fd : 0;
|
||||
}
|
||||
|
||||
if (access & (PAL_ACCESS_WRONLY | PAL_ACCESS_RDWR)) {
|
||||
HANDLE_HDR(hdl)->flags |= WFD(1);
|
||||
hdl->dev.fd_out = 1;
|
||||
hdl->dev.fd_out = dev_fd != -1 ? dev_fd : 1;
|
||||
}
|
||||
|
||||
*handle = hdl;
|
||||
@@ -124,24 +133,7 @@ static int term_open(PAL_HANDLE* handle, const char* type, const char* uri, int
|
||||
!WITHIN_MASK(options, PAL_OPTION_MASK))
|
||||
return -PAL_ERROR_INVAL;
|
||||
|
||||
const char* term = NULL;
|
||||
const char* param = NULL;
|
||||
|
||||
const char* tmp = uri;
|
||||
while (*tmp) {
|
||||
if (!term && *tmp == '/')
|
||||
term = tmp + 1;
|
||||
if (*tmp == ',') {
|
||||
param = param + 1;
|
||||
break;
|
||||
}
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if (term)
|
||||
return -PAL_ERROR_NOTIMPLEMENTED;
|
||||
|
||||
return open_standard_term(handle, param, access);
|
||||
return open_standard_term(handle, uri, access);
|
||||
}
|
||||
|
||||
static int term_close(PAL_HANDLE handle) {
|
||||
|
||||
@@ -241,3 +241,18 @@ int _DkCpuIdRetrieve (unsigned int leaf, unsigned int subleaf,
|
||||
cpuid(leaf, subleaf, values);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t _DkHostExtensionCall (PAL_HANDLE handle, PAL_NUM op, PAL_ARG* arg, int noutputs, PAL_ARG* outputs,
|
||||
int ninputs, PAL_ARG* inputs)
|
||||
{
|
||||
// The handle needs to have at least one fd
|
||||
if (!(HANDLE_HDR(handle)->flags & (RFD(0)|WFD(0))))
|
||||
return -PAL_ERROR_BADHANDLE;
|
||||
|
||||
int64_t ret = INLINE_SYSCALL(ioctl, 3, handle->generic.fds[0], op, arg->val);
|
||||
|
||||
if (IS_ERR(ret))
|
||||
return -PAL_ERROR_DENIED;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@ PAL {
|
||||
DkStreamChangeName;
|
||||
DkStreamAttributesSetByHandle;
|
||||
DkMemoryAvailableQuota;
|
||||
DkHostExtensionCall;
|
||||
|
||||
# Debugging ABIs
|
||||
pal_printf; DkDebugAttachBinary; DkDebugDetachBinary;
|
||||
|
||||
@@ -205,6 +205,7 @@ PAL_CONTROL * pal_control_addr (void);
|
||||
|
||||
#ifdef IN_PAL
|
||||
#define PAL_ALLOC_INTERNAL 0x8000
|
||||
#define PAL_ALLOC_DMAREGION 0x4000 /* alloc in untrusted memory for DMA with FPGA */
|
||||
#endif
|
||||
|
||||
/* Memory Protection Flags */
|
||||
@@ -522,6 +523,27 @@ PAL_NUM DkMemoryAvailableQuota (void);
|
||||
PAL_BOL
|
||||
DkCpuIdRetrieve (PAL_IDX leaf, PAL_IDX subleaf, PAL_IDX values[4]);
|
||||
|
||||
typedef struct {
|
||||
PAL_PTR val;
|
||||
PAL_NUM size, off;
|
||||
} PAL_ARG;
|
||||
|
||||
PAL_NUM
|
||||
DkHostExtensionCall (PAL_HANDLE handle, PAL_NUM op, PAL_ARG* arg, PAL_NUM noutputs, PAL_ARG* outputs,
|
||||
PAL_NUM ninputs, PAL_ARG* inputs);
|
||||
|
||||
typedef struct {
|
||||
PAL_NUM fd;
|
||||
PAL_NUM events;
|
||||
PAL_NUM revents;
|
||||
} PAL_POLLFD;
|
||||
|
||||
PAL_NUM DkEventfdPassthrough(PAL_NUM initval, PAL_NUM flags);
|
||||
PAL_NUM DkPollPassthrough(PAL_POLLFD* fds, PAL_NUM nfds, PAL_NUM timeout);
|
||||
PAL_NUM DkReadPassthrough(PAL_NUM fd, PAL_PTR buf, PAL_NUM count);
|
||||
PAL_NUM DkWritePassthrough(PAL_NUM fd, PAL_PTR buf, PAL_NUM count);
|
||||
PAL_NUM DkClosePassthrough(PAL_NUM fd);
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define symbol_version_default(real, name, version) \
|
||||
__asm__ (".symver " #real "," #name "@@" #version "\n")
|
||||
|
||||
@@ -356,6 +356,14 @@ int _DkPhysicalMemoryCommit (PAL_HANDLE channel, int entries,
|
||||
int _DkPhysicalMemoryMap (PAL_HANDLE channel, int entries,
|
||||
PAL_PTR * addrs, PAL_NUM * sizes, PAL_FLG * prots);
|
||||
int _DkCpuIdRetrieve (unsigned int leaf, unsigned int subleaf, unsigned int values[4]);
|
||||
int64_t _DkHostExtensionCall (PAL_HANDLE handle, PAL_NUM op, PAL_ARG* arg, int noutputs, PAL_ARG* outputs,
|
||||
int ninputs, PAL_ARG* inputs);
|
||||
|
||||
int _DkEventfdPassthrough(PAL_NUM initval, PAL_NUM flags);
|
||||
int _DkPollPassthrough(PAL_POLLFD* fds, PAL_NUM nfds, PAL_NUM timeout);
|
||||
int _DkReadPassthrough(PAL_NUM fd, PAL_PTR buf, PAL_NUM count);
|
||||
int _DkWritePassthrough(PAL_NUM fd, PAL_PTR buf, PAL_NUM count);
|
||||
int _DkClosePassthrough(PAL_NUM fd);
|
||||
|
||||
#define INIT_FAIL(exitcode, reason) \
|
||||
do { \
|
||||
|
||||
@@ -71,39 +71,6 @@ To build Graphene library OS with debug symbols, run "make DEBUG=1" instead of
|
||||
|
||||
To build with "-Werror", run "make WERROR=1".
|
||||
|
||||
### 2.1. BUILD WITH KERNEL-LEVEL SANDBOXING (OPTIONAL)
|
||||
|
||||
__** Note: this step is optional. **__
|
||||
|
||||
__** Note: for building with Intel:registered: SGX support, skip this step, go to section 2.2 **__
|
||||
|
||||
__** Disclaimer: this feature is experimental and may contain bugs. Please do
|
||||
no use in production system before further assessment.__
|
||||
|
||||
To enable sandboxing, a customized Linux kernel is needed. Note that
|
||||
this feature is optional and completely unnecessary for running on SGX.
|
||||
To build the Graphene Linux kernel, do the following steps:
|
||||
|
||||
cd Pal/linux-3.19
|
||||
make menuconfig
|
||||
make
|
||||
make install
|
||||
(Add Graphene kernel as a boot option by commands like "update-grub")
|
||||
(reboot and choose the Graphene kernel)
|
||||
|
||||
Please note that the building process may pause before building the Linux
|
||||
kernel, because it requires you to provide a sensible configuration file
|
||||
(.config). The Graphene kernel requires the following options to be enabled
|
||||
in the configuration:
|
||||
|
||||
- CONFIG_GRAPHENE=y
|
||||
- CONFIG_GRAPHENE_BULK_IPC=y
|
||||
- CONFIG_GRAPHENE_ISOLATE=y
|
||||
|
||||
For more details about the building and installation, see the Graphene github
|
||||
Wiki page: <https://github.com/oscarlab/graphene/wiki>.
|
||||
|
||||
|
||||
### 2.2 BUILD WITH INTEL:registered: SGX SUPPORT
|
||||
|
||||
#### 2.1.1 Prerequisites
|
||||
@@ -126,8 +93,14 @@ files) and the signatures, to the SGX-enabled hosts.
|
||||
The Intel SGX Linux SDK is required for running Graphene Library OS. Download and install
|
||||
from the official Intel github repositories:
|
||||
|
||||
- <https://github.com/01org/linux-sgx>
|
||||
- <https://github.com/01org/linux-sgx-driver>
|
||||
- <https://github.com/01org/linux-sgx> (SGX SDK)
|
||||
- <https://github.com/01org/linux-sgx-driver> (SGX Driver)
|
||||
* Order of steps would be: (Important: Select branch sgx2. Master branch is deprecated)
|
||||
1. Build & Install SGX driver (Follow instructions in : https://github.com/intel/linux-sgx-driver)
|
||||
2. Build & Install SGX SDK & SGX PSW Package
|
||||
3. Test the Intel(R) SGX SDK Package with the Code Samples
|
||||
Note: This section "Test the Intel(R) SGX SDK Package with the Code Samples" actually is written in middle, but requires the PSW, SGX SDK, SGX driver to be installed before running'
|
||||
|
||||
|
||||
A Linux driver must be installed before running Graphene Library OS in enclaves.
|
||||
Simply run the following command to build the driver:
|
||||
@@ -151,10 +124,28 @@ To build with debug symbols, run the command:
|
||||
|
||||
Using "make SGX=1" in the test or regression directory will automatically generate the enclave signatures (.sig files).
|
||||
|
||||
Note:
|
||||
1. Before running make SGX=1. LD_LIBRARY_PATH must be unset.
|
||||
$ unset LD_LIBRARY_PATH
|
||||
2. For the very first time: Make will ask for Install directory of SGX driver. Provide the path to the SGX driver checked out and build earlier in 2.2
|
||||
|
||||
|
||||
#### 2.1.3 Run Built-in Examples in Graphene-SGX
|
||||
|
||||
Following items need to be run again everytime when the system is re-booted. An init script can be created if required.
|
||||
|
||||
1. Load Graphene-SGX driver
|
||||
In <graphene_root>/Pal/src/host/Linux-SGX/sgx-driver
|
||||
$ ./load.sh
|
||||
2. Start SGX AESMD service
|
||||
sudo service aesmd start
|
||||
3. Set Minimum V.A mmap to 0
|
||||
sudo sysctl vm.mmap_min_addr=0
|
||||
|
||||
|
||||
There are a few built-in examples under LibOS/shim/test/. The "native" folder includes a rich set of C programs and "apps" folder includes a few tested applications, such as GCC, Python, and Apache.
|
||||
|
||||
|
||||
(1) Build and run a Hello World program with Graphene on SGX
|
||||
- go to LibOS/shim/test/native, build the enclaves via command:
|
||||
|
||||
@@ -182,13 +173,28 @@ There are a few built-in examples under LibOS/shim/test/. The "native" folder in
|
||||
|
||||
SGX=1 ./python.manifest.sgx scripts/helloworld.py
|
||||
|
||||
#### 2.1.3 Including Application Test Cases
|
||||
#### 2.1.4 Including Application Test Cases
|
||||
|
||||
To add the application test cases, issue the following command from the root
|
||||
of the source tree:
|
||||
|
||||
git submodule update --init -- LibOS/shim/test/apps/
|
||||
|
||||
#### 2.1.5 OpenVINO FPGA
|
||||
|
||||
|
||||
Note: The Apps folder contains an example of OpenVINO-FPGA
|
||||
Follow the Readme in the OpenVINO-FPGA to build and run the App.
|
||||
|
||||
Following are the list of changes to support OpenVINO-FPGA in the Graphene source code:
|
||||
1. IOCTL support for Graphene-SGX
|
||||
2. Eventfd/poll support for Graphene-SGX
|
||||
3. DMA memory allocation outside SGX memory
|
||||
4. Additional workarounds for symlinks, lseek etc.
|
||||
5. Mapping device file objects
|
||||
|
||||
This features were added relative to Graphene source code in Aug '18. New commits might already fix the missing features mentioned above
|
||||
|
||||
## 3. HOW TO RUN AN APPLICATION IN GRAPHENE?
|
||||
|
||||
Graphene library OS uses PAL (libpal.so) as a loader to bootstrap an
|
||||
|
||||
Reference in New Issue
Block a user