[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:
Dmitrii Kuvaiskii
2019-11-25 12:37:12 -08:00
parent 7eade65b91
commit 816e5eb8a6
29 changed files with 1089 additions and 104 deletions
+1
View File
@@ -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,
+72 -3
View File
@@ -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;
}
+1 -1
View File
@@ -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)
+327 -1
View File
@@ -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;
}
+5
View File
@@ -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;
}
+57 -1
View File
@@ -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);
+26
View File
@@ -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 =
+24 -2
View File
@@ -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
+50
View File
@@ -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
+85
View File
@@ -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);
}
+25 -27
View File
@@ -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)
+6 -2
View File
@@ -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;
}
+11
View File
@@ -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;
+51
View File
@@ -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;
}
+2 -2
View File
@@ -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,
&section_text, &section_rodata, &section_dynamic,
&section_data, &section_bss);
+83
View File
@@ -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;
}
+5
View File
@@ -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);
+14
View File
@@ -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)
+7
View File
@@ -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;
+50 -4
View File
@@ -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)
+17 -25
View File
@@ -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) {
+15
View File
@@ -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;
}
+1
View File
@@ -39,6 +39,7 @@ PAL {
DkStreamChangeName;
DkStreamAttributesSetByHandle;
DkMemoryAvailableQuota;
DkHostExtensionCall;
# Debugging ABIs
pal_printf; DkDebugAttachBinary; DkDebugDetachBinary;
+22
View File
@@ -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")
+8
View File
@@ -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 { \
+42 -36
View File
@@ -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