diff --git a/.travis.yml b/.travis.yml index c71accc4..0c9052a4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,24 @@ language: c -script: make && make install + +before_install: + - sudo apt-get install python-protobuf python-crypto + - sudo apt-get install linux-headers-$(uname -r) + +before_script: + - git clone https://github.com/01org/linux-sgx-driver.git -b sgx_driver_$ISGX_DRIVER_VERSION + +script: + - make + - cd $TRAVIS_BUILD_DIR/Pal/src && make clean && make SGX=1 + - cd $TRAVIS_BUILD_DIR/Pal/src/host/Linux-SGX/sgx-driver && make + - cd $TRAVIS_BUILD_DIR/Pal/regression && make regression + - cd $TRAVIS_BUILD_DIR/LibOS/shim/test/regression && make regression + - cd $TRAVIS_BUILD_DIR/LibOS/shim/test/apps/ltp && make regression matrix: include: - os: linux dist: trusty + env: + - ISGX_DRIVER_PATH=$TRAVIS_BUILD_DIR/linux-sgx-driver + - ISGX_DRIVER_VERSION=1.9 diff --git a/LibOS/glibc-2.19.patch b/LibOS/glibc-2.19.patch index 3aeec384..8fef9306 100644 --- a/LibOS/glibc-2.19.patch +++ b/LibOS/glibc-2.19.patch @@ -1804,19 +1804,17 @@ diff --git a/sysdeps/unix/sysv/linux/x86_64/syscall.S b/sysdeps/unix/sysv/linux/ index 92c2f5b..e32ebb2 100644 --- a/sysdeps/unix/sysv/linux/x86_64/syscall.S +++ b/sysdeps/unix/sysv/linux/x86_64/syscall.S -@@ -31,10 +31,13 @@ ENTRY (syscall) +@@ -31,10 +31,12 @@ movq %rsi, %rdi /* shift arg1 - arg5. */ movq %rdx, %rsi movq %rcx, %rdx -- movq %r8, %r10 -+ /* DEP 1/28/17: This is not the Linux kernel; use user-space calling -+ * convention */ -+ /* movq %r8, %r10 */ -+ movq %r8, %rcx ++ /* DEP 8/17/17: Keep kernel calling ++ * convention and fix in libOS */ + movq %r8, %r10 movq %r9, %r8 movq 8(%rsp),%r9 /* arg6 is on the stack. */ - syscall /* Do the system call. */ -+ SYSCALLDB /* Do the system call. */ ++ SYSCALLDB /* Do the system call. */ cmpq $-4095, %rax /* Check %rax for error. */ jae SYSCALL_ERROR_LABEL /* Jump to error handler if error. */ ret /* Return to caller. */ diff --git a/LibOS/shim/include/shim_fs.h b/LibOS/shim/include/shim_fs.h index fa9fc764..21494e02 100644 --- a/LibOS/shim/include/shim_fs.h +++ b/LibOS/shim/include/shim_fs.h @@ -192,7 +192,10 @@ struct shim_d_ops { int (*rename) (struct shim_dentry * old, struct shim_dentry * new); /* readdir: given the path relative to the mount point, read the childs - into the the buffer */ + into the the buffer. This call always returns everything under + the directory in one big buffer; you do not need to try again + or keep a cursor in the directory. You do need to free the + returned buffer. */ int (*readdir) (struct shim_dentry * dent, struct shim_dirent ** dirent); }; diff --git a/LibOS/shim/include/shim_handle.h b/LibOS/shim/include/shim_handle.h index 54429f2c..e69f8bc3 100644 --- a/LibOS/shim/include/shim_handle.h +++ b/LibOS/shim/include/shim_handle.h @@ -78,6 +78,7 @@ struct shim_file_data { unsigned long atime; unsigned long mtime; unsigned long ctime; + unsigned long nlink; }; struct shim_file_handle { diff --git a/LibOS/shim/include/shim_internal.h b/LibOS/shim/include/shim_internal.h index f19bb9a2..bce2f5d3 100644 --- a/LibOS/shim/include/shim_internal.h +++ b/LibOS/shim/include/shim_internal.h @@ -752,7 +752,8 @@ extern const char ** initial_envp; void get_brk_region (void ** start, void ** end, void ** current); int init_randgen (void); -int init_brk (void); +int reset_brk (void); +int init_brk_region (void * brk_region); int init_heap (void); int init_internal_map (void); int init_loader (void); diff --git a/LibOS/shim/include/shim_ipc.h b/LibOS/shim/include/shim_ipc.h index 7d004719..50441989 100644 --- a/LibOS/shim/include/shim_ipc.h +++ b/LibOS/shim/include/shim_ipc.h @@ -165,12 +165,13 @@ enum { struct shim_ipc_cld_exit { IDTYPE ppid, tid; unsigned int exitcode; + unsigned int term_signal; #ifdef PROFILE unsigned long time; #endif } __attribute__((packed)); -int ipc_cld_exit_send (IDTYPE ppid, IDTYPE tid, unsigned int exitcode); +int ipc_cld_exit_send (IDTYPE ppid, IDTYPE tid, unsigned int exitcode, unsigned int term_signal); int ipc_cld_exit_callback (IPC_CALLBACK_ARGS); /* CLD_JOIN: child join the parent group */ @@ -595,9 +596,9 @@ int do_ipc_duplex (struct shim_ipc_msg_obj * msg, void * private_data); void ipc_parent_exit (struct shim_ipc_port * port, IDTYPE vmid, - unsigned int exitcode); + unsigned int exitcode, unsigned int term_signal); void ipc_child_exit (struct shim_ipc_port * port, IDTYPE vmid, - unsigned int exitcode); + unsigned int exitcode, unsigned int term_signal); int create_ipc_helper (void); int exit_with_ipc_helper (bool handover); diff --git a/LibOS/shim/include/shim_signal.h b/LibOS/shim/include/shim_signal.h index cc514707..7b007c2d 100644 --- a/LibOS/shim/include/shim_signal.h +++ b/LibOS/shim/include/shim_signal.h @@ -13,9 +13,6 @@ struct shim_signal_handle { struct __kernel_sigaction * action; }; -#define NUM_SIGS 64 -#define NUM_KNOWN_SIGS 32 - # define BITS_PER_WORD sizeof(unsigned long) /* The standard def of this macro is dumb */ #undef _SIGSET_NWORDS @@ -146,7 +143,8 @@ void append_signal (struct shim_thread * thread, int sig, siginfo_t * info, void deliver_signal (siginfo_t * info, PAL_CONTEXT * context); __sigset_t * get_sig_mask (struct shim_thread * thread); -__sigset_t * set_sig_mask (struct shim_thread * thread, __sigset_t * new_set); +__sigset_t * set_sig_mask (struct shim_thread * thread, + const __sigset_t * new_set); int do_kill_thread (IDTYPE sender, IDTYPE tgid, IDTYPE tid, int sig, bool use_ipc); diff --git a/LibOS/shim/include/shim_table.h b/LibOS/shim/include/shim_table.h index 507c9207..0e4eab93 100644 --- a/LibOS/shim/include/shim_table.h +++ b/LibOS/shim/include/shim_table.h @@ -27,7 +27,7 @@ long __shim_mmap (long, long, long, long, long, long); long __shim_mprotect (long, long, long); long __shim_munmap (long, long); long __shim_brk (long); -long __shim_rt_sigaction (long, long, long); +long __shim_rt_sigaction (long, long, long, long); long __shim_rt_sigprocmask (long, long, long); long __shim_rt_sigreturn (long); long __shim_ioctl (long, long, long); @@ -343,7 +343,7 @@ int shim_do_mprotect (void * addr, size_t len, int prot); int shim_do_munmap (void * addr, size_t len); void * shim_do_brk (void * brk); int shim_do_sigaction (int signum, const struct __kernel_sigaction * act, - struct __kernel_sigaction * oldact); + struct __kernel_sigaction * oldact, size_t sigsetsize); int shim_do_sigprocmask (int how, const __sigset_t * set, __sigset_t * oldset); int shim_do_sigreturn (int __unused); int shim_do_ioctl (int fd, int cmd, unsigned long arg); @@ -442,6 +442,7 @@ pid_t shim_do_getpgrp (void); int shim_do_setsid (void); int shim_do_getpgid (pid_t pid); int shim_do_getsid (pid_t pid); +int shim_do_sigpending (__sigset_t * set, size_t sigsetsize); int shim_do_sigaltstack (const stack_t * ss, stack_t * oss); int shim_do_sigsuspend (const __sigset_t * mask); void * shim_do_arch_prctl (int code, void * addr); @@ -525,7 +526,7 @@ int shim_mprotect (void * addr, size_t len, int prot); int shim_munmap (void * addr, size_t len); void * shim_brk (void * brk); int shim_rt_sigaction (int signum, const struct __kernel_sigaction * act, - struct __kernel_sigaction * oldact); + struct __kernel_sigaction * oldact, size_t sigsetsize); int shim_rt_sigprocmask (int how, const __sigset_t * set, __sigset_t * oldset); int shim_rt_sigreturn (int __unused); int shim_ioctl (int fd, int cmd, unsigned long arg); diff --git a/LibOS/shim/include/shim_thread.h b/LibOS/shim/include/shim_thread.h index 31521a4b..699c3e44 100644 --- a/LibOS/shim/include/shim_thread.h +++ b/LibOS/shim/include/shim_thread.h @@ -67,6 +67,8 @@ struct shim_thread { PAL_HANDLE exit_event; int exit_code; + int term_signal; // Store the terminating signal, if any; needed for + // wait() and friends bool is_alive; PAL_HANDLE child_exit_event; @@ -103,6 +105,7 @@ struct shim_simple_thread { /* exit event and status */ PAL_HANDLE exit_event; int exit_code; + int term_signal; bool is_alive; /* nodes in global handles */ @@ -292,7 +295,9 @@ void set_handle_map (struct shim_thread * thread, /* shim exit callback */ int thread_exit (struct shim_thread * self, bool send_ipc); -int try_process_exit (int error_code); +/* If the process was killed by a signal, pass it in the second + * argument, else pass zero */ +int try_process_exit (int error_code, int term_signal); /* thread cloning helpers */ struct clone_args { diff --git a/LibOS/shim/include/shim_types.h b/LibOS/shim/include/shim_types.h index 5c66729f..247e543c 100644 --- a/LibOS/shim/include/shim_types.h +++ b/LibOS/shim/include/shim_types.h @@ -156,10 +156,12 @@ struct __kernel_sigaction { /* linux/aio_abi.h (for io_setup which has no glibc wrapper) */ typedef unsigned long aio_context_t; -/* bits/sigset.h */ -# define _SIGSET_NWORDS (1024 / (8 * sizeof (unsigned long int))) +/* asm/signal.h */ +#define NUM_SIGS 64 +#define NUM_KNOWN_SIGS 32 + typedef struct { - unsigned long int __val[_SIGSET_NWORDS]; + unsigned long __val[NUM_SIGS / (8 * sizeof(unsigned long))]; } __sigset_t; /* linux/rlimit.h */ diff --git a/LibOS/shim/src/bookkeep/shim_signal.c b/LibOS/shim/src/bookkeep/shim_signal.c index df7b2bc0..f0caa0dc 100644 --- a/LibOS/shim/src/bookkeep/shim_signal.c +++ b/LibOS/shim/src/bookkeep/shim_signal.c @@ -262,10 +262,23 @@ internal: put_vma(vma); goto internal; } - if (vma->file) { - /* XXX: need more sophisticated judgement */ - signo = SIGBUS; - code = BUS_ADRERR; + if (vma->file && vma->file->type == TYPE_FILE) { + /* DEP 3/3/17: If the mapping exceeds end of a file (but is in the VMA) + * then return a SIGBUS. */ + uint64_t eof_in_vma = (uint64_t) vma->addr + vma->offset + vma->file->info.file.size; + if (arg > eof_in_vma) { + signo = SIGBUS; + code = BUS_ADRERR; + } else if ((context->err & 4) && !(vma->flags & PROT_WRITE)) { + /* DEP 3/3/17: If the page fault gives a write error, and + * the VMA is read-only, return SIGSEGV+SEGV_ACCERR */ + signo = SIGSEGV; + code = SEGV_ACCERR; + } else { + /* XXX: need more sophisticated judgement */ + signo = SIGBUS; + code = BUS_ADRERR; + } } else { code = SEGV_ACCERR; } @@ -379,7 +392,8 @@ __sigset_t * get_sig_mask (struct shim_thread * thread) return &(thread->signal_mask); } -__sigset_t * set_sig_mask (struct shim_thread * thread, __sigset_t * set) +__sigset_t * set_sig_mask (struct shim_thread * thread, + const __sigset_t * set) { if (!thread) thread = get_cur_thread(); @@ -565,17 +579,24 @@ static void sighandler_kill (int sig, siginfo_t * info, void * ucontext) break; } - try_process_exit(0); + try_process_exit(0, sig); DkThreadExit(); } +/* We don't currently implement core dumps, but put a wrapper + * in case we do in the future */ +static void sighandler_core (int sig, siginfo_t * info, void * ucontext) +{ + sighandler_kill(sig, info, ucontext); +} + static void (*default_sighandler[NUM_SIGS]) (int, siginfo_t *, void *) = { /* SIGHUP */ &sighandler_kill, /* SIGINT */ &sighandler_kill, /* SIGQUIT */ &sighandler_kill, /* SIGILL */ &sighandler_kill, - /* SIGTRAP */ NULL, + /* SIGTRAP */ &sighandler_core, /* SIGABRT */ &sighandler_kill, /* SIGBUS */ &sighandler_kill, /* SIGFPE */ &sighandler_kill, @@ -584,7 +605,7 @@ static void (*default_sighandler[NUM_SIGS]) (int, siginfo_t *, void *) = /* SIGSEGV */ &sighandler_kill, /* SIGUSR2 */ NULL, /* SIGPIPE */ &sighandler_kill, - /* SIGALRM */ NULL, + /* SIGALRM */ &sighandler_kill, /* SIGTERM */ &sighandler_kill, /* SIGSTKFLT */ NULL, /* SIGCHLD */ NULL, diff --git a/LibOS/shim/src/bookkeep/shim_vma.c b/LibOS/shim/src/bookkeep/shim_vma.c index 9d3f6e3b..af3ef21b 100644 --- a/LibOS/shim/src/bookkeep/shim_vma.c +++ b/LibOS/shim/src/bookkeep/shim_vma.c @@ -242,6 +242,7 @@ static bool check_vma_flags (const struct shim_vma * vma, const int * flags) return true; if ((vma->flags & VMA_INTERNAL) != ((*flags) & VMA_INTERNAL)) { + debug("Check vma flag failure: vma flags %x, checked flags %x\n", vma->flags, *flags); bug(); return false; } diff --git a/LibOS/shim/src/elf/shim_rtld.c b/LibOS/shim/src/elf/shim_rtld.c index 07f09a54..2e6fc41e 100644 --- a/LibOS/shim/src/elf/shim_rtld.c +++ b/LibOS/shim/src/elf/shim_rtld.c @@ -1481,6 +1481,8 @@ int init_internal_map (void) return 0; } +int init_brk_from_executable (struct shim_handle * exec); + int init_loader (void) { struct shim_thread * cur_thread = get_cur_thread(); @@ -1507,6 +1509,8 @@ int init_loader (void) exec_map = __search_map_by_handle(exec); } + init_brk_from_executable(exec); + if (!interp_map && __need_interp(exec_map) && (ret = __load_interp_object(exec_map)) < 0) @@ -1518,6 +1522,21 @@ out: return ret; } +int init_brk_from_executable (struct shim_handle * exec) +{ + struct link_map * exec_map = __search_map_by_handle(exec); + + if (exec_map) { + /* + * Chia-Che 8/24/2017: + * initialize brk region at the end of the executable data segment. + */ + init_brk_region((void *) ALIGN_UP(exec_map->l_map_end)); + } + + return 0; +} + int register_library (const char * name, unsigned long load_address) { debug("glibc register library %s loaded at %p\n", diff --git a/LibOS/shim/src/fs/chroot/fs.c b/LibOS/shim/src/fs/chroot/fs.c index 3cc43b83..b42c50f3 100644 --- a/LibOS/shim/src/fs/chroot/fs.c +++ b/LibOS/shim/src/fs/chroot/fs.c @@ -212,9 +212,14 @@ static int create_data (struct shim_dentry * dent, const char * uri, int len) return 0; } -static int __query_attr (struct shim_file_data * data, PAL_HANDLE pal_handle) +static int chroot_readdir (struct shim_dentry * dent, + struct shim_dirent ** dirent); + +static int __query_attr (struct shim_dentry * dent, + struct shim_file_data * data, PAL_HANDLE pal_handle) { PAL_STREAM_ATTR pal_attr; + enum shim_file_type old_type = data->type; if (pal_handle ? !DkStreamAttributesQuerybyHandle(pal_handle, &pal_attr) : @@ -234,6 +239,42 @@ static int __query_attr (struct shim_file_data * data, PAL_HANDLE pal_handle) (pal_attr.runnable ? S_IXUSR : 0); atomic_set(&data->size, pal_attr.pending_size); + + if (data->type == FILE_DIR) { + int ret; + /* Move up the uri update; need to convert manifest-level file: + * directives to 'dir:' uris */ + if (old_type != FILE_DIR) { + dent->state |= DENTRY_ISDIRECTORY; + if ((ret = make_uri(dent)) < 0) { + unlock(data->lock); + return ret; + } + } + + /* DEP 3/18/17: If we have a directory, we need to find out how many + * children it has by hand. */ + /* XXX: Keep coherent with rmdir/mkdir/creat, etc */ + struct shim_dirent *d, *dbuf = NULL; + int nlink = 0; + int rv = chroot_readdir(dent, &dbuf); + if (rv != 0) + return rv; + if (dbuf) { + for (d = dbuf; d; d = d->next) + nlink++; + free(dbuf); + debug("Querying a directory; I count %d links.\n", nlink); + } else + nlink = 2; // Educated guess... + data->nlink = nlink; + } else { + /* DEP 3/18/17: Right now, we don't support hard links, + * so just return 1; + */ + data->nlink = 1; + } + data->queried = true; return 0; @@ -287,21 +328,11 @@ static int query_dentry (struct shim_dentry * dent, PAL_HANDLE pal_handle, lock(data->lock); - enum shim_file_type old_type = data->type; - - if (!data->queried && (ret = __query_attr(data, pal_handle)) < 0) { + if (!data->queried && (ret = __query_attr(dent, data, pal_handle)) < 0) { unlock(data->lock); return ret; } - if (data->type == FILE_DIR && old_type != FILE_DIR) { - dent->state |= DENTRY_ISDIRECTORY; - if ((ret = make_uri(dent)) < 0) { - unlock(data->lock); - return ret; - } - } - if (mode) *mode = data->mode; @@ -318,14 +349,23 @@ static int query_dentry (struct shim_dentry * dent, PAL_HANDLE pal_handle, stat->st_atime = (time_t) data->atime; stat->st_mtime = (time_t) data->mtime; stat->st_ctime = (time_t) data->ctime; + stat->st_nlink = data->nlink; + switch (data->type) { - case FILE_REGULAR: stat->st_mode |= S_IFREG; break; - case FILE_DIR: stat->st_mode |= S_IFDIR; break; + case FILE_REGULAR: + stat->st_mode |= S_IFREG; + break; + case FILE_DIR: + stat->st_mode |= S_IFDIR; + break; case FILE_DEV: - case FILE_TTY: stat->st_mode |= S_IFCHR; break; + case FILE_TTY: + stat->st_mode |= S_IFCHR; + break; default: break; } + debug("Stat: Returning link cound %d\n", stat->st_nlink); } unlock(data->lock); @@ -356,7 +396,8 @@ static int chroot_lookup (struct shim_dentry * dent, bool force) return query_dentry(dent, NULL, NULL, NULL); } -static int __chroot_open (const char * uri, int len, int flags, mode_t mode, +static int __chroot_open (struct shim_dentry * dent, + const char * uri, int len, int flags, mode_t mode, struct shim_handle * hdl, struct shim_file_data * data) { @@ -396,7 +437,7 @@ static int __chroot_open (const char * uri, int len, int flags, mode_t mode, if (!data->queried) { lock(data->lock); - ret = __query_attr(data, palhdl); + ret = __query_attr(dent, data, palhdl); unlock(data->lock); } @@ -422,7 +463,7 @@ static int chroot_open (struct shim_handle * hdl, struct shim_dentry * dent, if ((ret = try_create_data(dent, NULL, 0, &data)) < 0) return ret; - if ((ret = __chroot_open(NULL, 0, flags, dent->mode, hdl, data)) < 0) + if ((ret = __chroot_open(dent, NULL, 0, flags, dent->mode, hdl, data)) < 0) return ret; struct shim_file_handle * file = &hdl->info.file; @@ -448,7 +489,7 @@ static int chroot_creat (struct shim_handle * hdl, struct shim_dentry * dir, if ((ret = try_create_data(dent, NULL, 0, &data)) < 0) return ret; - if ((ret = __chroot_open(NULL, 0, flags|O_CREAT|O_EXCL, mode, hdl, + if ((ret = __chroot_open(dent, NULL, 0, flags|O_CREAT|O_EXCL, mode, hdl, data)) < 0) return ret; @@ -467,6 +508,14 @@ static int chroot_creat (struct shim_handle * hdl, struct shim_dentry * dir, hdl->acc_mode = ACC_MODE(flags & O_ACCMODE); qstrcopy(&hdl->uri, &data->host_uri); + /* Increment the parent's link count */ + struct shim_file_data *parent_data = FILE_DENTRY_DATA(dir); + if (parent_data) { + lock(parent_data->lock); + if (parent_data->queried) + parent_data->nlink++; + unlock(parent_data->lock); + } return 0; } @@ -485,7 +534,17 @@ static int chroot_mkdir (struct shim_dentry * dir, struct shim_dentry * dent, return ret; } - return __chroot_open(NULL, 0, O_CREAT|O_EXCL, mode, NULL, data); + ret = __chroot_open(dent, NULL, 0, O_CREAT|O_EXCL, mode, NULL, data); + + /* Increment the parent's link count */ + struct shim_file_data *parent_data = FILE_DENTRY_DATA(dir); + if (parent_data) { + lock(parent_data->lock); + if (parent_data->queried) + parent_data->nlink++; + unlock(parent_data->lock); + } + return ret; } #define NEED_RECREATE(hdl) (!FILE_HANDLE_DATA(hdl)) @@ -512,7 +571,13 @@ static int chroot_recreate (struct shim_handle * hdl) qstrsetstr(&data->host_uri, uri, len); } - return __chroot_open(uri, len, hdl->flags, 0, hdl, data); + /* + * Chia-Che Tsai 8/24/2017: + * when recreating a file handle after migration, the file should + * not be created again. + */ + return __chroot_open(hdl->dentry, uri, len, hdl->flags & ~(O_CREAT|O_EXCL), + 0, hdl, data); } static inline bool check_version (struct shim_handle * hdl) @@ -855,6 +920,9 @@ static int chroot_truncate (struct shim_handle * hdl, uint64_t len) if (NEED_RECREATE(hdl) && (ret = chroot_recreate(hdl)) < 0) return ret; + if (!(hdl->acc_mode & MAY_WRITE)) + return -EINVAL; + struct shim_file_handle * file = &hdl->info.file; lock(hdl->lock); @@ -1017,10 +1085,20 @@ static int chroot_checkout (struct shim_handle * hdl) hdl->info.file.data = NULL; } + if (hdl->pal_handle) { + /* + * Chia-Che 8/24/2017: + * if the file still exists in the host, no need to send + * the handle over RPC; otherwise, send it. + */ + PAL_STREAM_ATTR attr; + if (DkStreamAttributesQuery(qstrgetstr(&hdl->uri), &attr)) + hdl->pal_handle = NULL; + } + hdl->info.file.mapsize = 0; hdl->info.file.mapoffset = 0; hdl->info.file.mapbuf = NULL; - hdl->pal_handle = NULL; return 0; } @@ -1067,6 +1145,15 @@ static int chroot_unlink (struct shim_dentry * dir, struct shim_dentry * dent) atomic_inc(&data->version); atomic_set(&data->size, 0); + /* Drop the parent's link count */ + struct shim_file_data *parent_data = FILE_DENTRY_DATA(dir); + if (parent_data) { + lock(parent_data->lock); + if (parent_data->queried) + parent_data->nlink--; + unlock(parent_data->lock); + } + return 0; } diff --git a/LibOS/shim/src/fs/shim_fs.c b/LibOS/shim/src/fs/shim_fs.c index 274c1b57..4f81a5fb 100644 --- a/LibOS/shim/src/fs/shim_fs.c +++ b/LibOS/shim/src/fs/shim_fs.c @@ -159,7 +159,7 @@ static int __mount_one_other (const char * key, int keylen) debug("mounting as %s filesystem: from %s to %s\n", t, uri, p); if ((ret = mount_fs(t, uri, p)) < 0) { - debug("mounting %s on %s (type=%s) failed (%e)\n", t, uri, p, + debug("mounting %s on %s (type=%s) failed (%e)\n", uri, p, t, -ret); return ret; } diff --git a/LibOS/shim/src/ipc/shim_ipc_child.c b/LibOS/shim/src/ipc/shim_ipc_child.c index a6520c4d..07a501e7 100644 --- a/LibOS/shim/src/ipc/shim_ipc_child.c +++ b/LibOS/shim/src/ipc/shim_ipc_child.c @@ -37,7 +37,7 @@ #include static int ipc_thread_exit (IDTYPE vmid, IDTYPE ppid, IDTYPE tid, - unsigned int exitcode, unsigned long exit_time) + unsigned int exitcode, unsigned int term_signal, unsigned long exit_time) { assert(vmid != cur_process.vmid); @@ -52,6 +52,7 @@ static int ipc_thread_exit (IDTYPE vmid, IDTYPE ppid, IDTYPE tid, int ret = 0; //assert(thread->vmid == vmid && !thread->in_vm); thread->exit_code = -exitcode; + thread->term_signal = term_signal; #ifdef PROFILE thread->exit_time = exit_time; #endif @@ -71,6 +72,7 @@ static int ipc_thread_exit (IDTYPE vmid, IDTYPE ppid, IDTYPE tid, sthread->is_alive = 0; sthread->exit_code = -exitcode; + sthread->term_signal = term_signal; #ifdef PROFILE sthread->exit_time = exit_time; #endif @@ -80,7 +82,7 @@ static int ipc_thread_exit (IDTYPE vmid, IDTYPE ppid, IDTYPE tid, } void ipc_parent_exit (struct shim_ipc_port * port, IDTYPE vmid, - unsigned int exitcode) + unsigned int exitcode, unsigned int term_signal) { debug("ipc port %p of process %u closed suggests parent exiting\n", port, vmid); @@ -103,6 +105,7 @@ void ipc_parent_exit (struct shim_ipc_port * port, IDTYPE vmid, struct thread_info { IDTYPE vmid; unsigned int exitcode; + unsigned int term_signal; }; static int child_sthread_exit (struct shim_simple_thread * thread, void * arg, @@ -112,6 +115,7 @@ static int child_sthread_exit (struct shim_simple_thread * thread, void * arg, if (thread->vmid == info->vmid) { if (thread->is_alive) { thread->exit_code = -info->exitcode; + thread->term_signal = info->term_signal; thread->is_alive = false; DkEventSet(thread->exit_event); } @@ -127,6 +131,7 @@ static int child_thread_exit (struct shim_thread * thread, void * arg, if (thread->vmid == info->vmid) { if (thread->is_alive) { thread->exit_code = -info->exitcode; + thread->term_signal = info->term_signal; thread_exit(thread, false); } return 1; @@ -134,9 +139,9 @@ static int child_thread_exit (struct shim_thread * thread, void * arg, return 0; } -int remove_child_thread (IDTYPE vmid, unsigned int exitcode) +int remove_child_thread (IDTYPE vmid, unsigned int exitcode, unsigned int term_signal) { - struct thread_info info = { .vmid = vmid, .exitcode = exitcode }; + struct thread_info info = { .vmid = vmid, .exitcode = exitcode, .term_signal = term_signal }; int nkilled = 0, ret; assert(vmid != cur_process.vmid); @@ -154,12 +159,12 @@ int remove_child_thread (IDTYPE vmid, unsigned int exitcode) } void ipc_child_exit (struct shim_ipc_port * port, IDTYPE vmid, - unsigned int exitcode) + unsigned int exitcode, unsigned int term_signal) { debug("ipc port %p of process %u closed suggests child exiting\n", port, vmid); - remove_child_thread(vmid, 0); + remove_child_thread(vmid, 0, term_signal); } static struct shim_ipc_port * get_parent_port (IDTYPE * dest) @@ -178,7 +183,7 @@ DEFINE_PROFILE_INTERVAL(ipc_cld_exit_turnaround, ipc); DEFINE_PROFILE_INTERVAL(ipc_cld_exit_send, ipc); DEFINE_PROFILE_INTERVAL(ipc_cld_exit_callback, ipc); -int ipc_cld_exit_send (IDTYPE ppid, IDTYPE tid, unsigned int exitcode) +int ipc_cld_exit_send (IDTYPE ppid, IDTYPE tid, unsigned int exitcode, unsigned int term_signal) { unsigned long send_time = GET_PROFILE_INTERVAL(); BEGIN_PROFILE_INTERVAL_SET(send_time); @@ -192,6 +197,7 @@ int ipc_cld_exit_send (IDTYPE ppid, IDTYPE tid, unsigned int exitcode) msgin->ppid = ppid; msgin->tid = tid; msgin->exitcode = exitcode; + msgin->term_signal = term_signal; #ifdef PROFILE msgin->time = send_time; #endif @@ -220,7 +226,8 @@ int ipc_cld_exit_callback (IPC_CALLBACK_ARGS) msg->src, msgin->ppid, msgin->tid, msgin->exitcode); int ret = ipc_thread_exit(msg->src, msgin->ppid, msgin->tid, - msgin->exitcode, time); + msgin->exitcode, msgin->term_signal, + time); SAVE_PROFILE_INTERVAL(ipc_cld_exit_callback); return ret; } diff --git a/LibOS/shim/src/shim_malloc.c b/LibOS/shim/src/shim_malloc.c index b3868a47..5fb0c49f 100644 --- a/LibOS/shim/src/shim_malloc.c +++ b/LibOS/shim/src/shim_malloc.c @@ -20,7 +20,27 @@ /* * shim_malloc.c * - * This file contains codes for SLAB memory allocator of library OS. + * This file implements page allocation for the library OS-internal SLAB + * memory allocator. The slab allocator is in Pal/lib/slabmgr.h. + * + * When existing slabs are not sufficient, or a large (4k or greater) + * allocation is requested, it ends up here (__system_alloc and __system_free). + * + * There are two modes this file executes in: early initialization (before + * VMAs are available), and post-initialization. + * + * Before VMAs are available, allocations are tracked in the shim_heap_areas + * array. + * + * Once VMAs initialized, the contents of shim_heap_areas are added to the VMA + * list. In order to reduce the risk of virtual address collisions, the VMA + * for the shim_heap_area is never removed, but the pages themselves are + * freed. This approach effectively reserves part of the address space for + * initialization-time bookkeeping. + * + * After initialization, all allocations and frees just call + * DkVirtualMemoryAlloc and DkVirtualMemory Free, and add/remove VMAs for the + * results. */ #include @@ -56,6 +76,8 @@ static SLAB_MGR slab_mgr = NULL; #define INIT_SHIM_HEAP 256 * allocsize +static int vmas_initialized = 0; + static struct shim_heap { void * start; void * current; @@ -126,19 +148,28 @@ static struct shim_heap * __alloc_enough_heap (size_t size) void * __system_malloc (size_t size) { size_t alloc_size = ALIGN_UP(size); - + void *addr; + lock(shim_heap_lock); - struct shim_heap * heap = __alloc_enough_heap(alloc_size); + if (vmas_initialized) { + addr = (void *) DkVirtualMemoryAlloc(NULL, alloc_size, 0, + PAL_PROT_WRITE|PAL_PROT_READ); + bkeep_mmap(addr, alloc_size, PROT_READ|PROT_WRITE, + MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0, NULL); + } else { - if (!heap) { - unlock(shim_heap_lock); - return NULL; + struct shim_heap * heap = __alloc_enough_heap(alloc_size); + + if (!heap) { + unlock(shim_heap_lock); + return NULL; + } + + addr = heap->current; + heap->current += alloc_size; } - void * addr = heap->current; - heap->current += alloc_size; - unlock(shim_heap_lock); return addr; @@ -146,9 +177,22 @@ void * __system_malloc (size_t size) void __system_free (void * addr, size_t size) { + int in_reserved_area = 0; DkVirtualMemoryFree(addr, ALIGN_UP(size)); int flags = VMA_INTERNAL; - bkeep_munmap(addr, ALIGN_UP(size), &flags); + for (int i = 0 ; i < MAX_SHIM_HEAP_AREAS ; i++) + if (shim_heap_areas[i].start) { + /* Here we assume that any allocation from the + * shim_heap_area is a strict inclusion. Allocations + * cannot partially overlap. + */ + if (addr >= shim_heap_areas[i].start + && addr <= shim_heap_areas[i].end) + in_reserved_area = 1; + } + + if (! in_reserved_area) + bkeep_munmap(addr, ALIGN_UP(size), &flags); } int init_heap (void) @@ -172,14 +216,23 @@ int init_heap (void) int bkeep_shim_heap (void) { lock(shim_heap_lock); - + for (int i = 0 ; i < MAX_SHIM_HEAP_AREAS ; i++) - if (shim_heap_areas[i].start) + if (shim_heap_areas[i].start) { + /* Add a VMA for the active region */ bkeep_mmap(shim_heap_areas[i].start, - shim_heap_areas[i].end - shim_heap_areas[i].start, + shim_heap_areas[i].current - shim_heap_areas[i].start, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS|VMA_INTERNAL, NULL, 0, NULL); - + /* Go ahead and free the reserved region */ + if (shim_heap_areas[i].current < shim_heap_areas[i].end) { + DkVirtualMemoryFree(shim_heap_areas[i].current, + ALIGN_UP(((long unsigned int) shim_heap_areas[i].end) - ((long unsigned int) shim_heap_areas[i].current))); + shim_heap_areas[i].end = shim_heap_areas[i].current; + } + } + vmas_initialized = 1; + unlock(shim_heap_lock); return 0; } diff --git a/LibOS/shim/src/shim_syscalls.c b/LibOS/shim/src/shim_syscalls.c index 5b403436..973f0798 100644 --- a/LibOS/shim/src/shim_syscalls.c +++ b/LibOS/shim/src/shim_syscalls.c @@ -197,8 +197,9 @@ void * shim_do_brk (void * brk) #endif /* rt_sigaction: sys/shim_sigaction.c */ -DEFINE_SHIM_SYSCALL (rt_sigaction, 3, shim_do_sigaction, int, int, signum, - const struct __kernel_sigaction *, act, struct __kernel_sigaction *, oldact) +DEFINE_SHIM_SYSCALL (rt_sigaction, 4, shim_do_sigaction, int, int, signum, + const struct __kernel_sigaction *, act, + struct __kernel_sigaction *, oldact, size_t, sigsetsize) /* rt_sigprocmask: sys/shim_sigaction.c */ DEFINE_SHIM_SYSCALL (rt_sigprocmask, 3, shim_do_sigprocmask, int, int, how, @@ -578,8 +579,8 @@ SHIM_SYSCALL_PASSTHROUGH (capget, 2, int, cap_user_header_t, header, SHIM_SYSCALL_PASSTHROUGH (capset, 2, int, cap_user_header_t, header, const cap_user_data_t, data) -SHIM_SYSCALL_PASSTHROUGH (rt_sigpending, 2, int, __sigset_t *, set, size_t, - sigsetsize) +DEFINE_SHIM_SYSCALL (rt_sigpending, 2, shim_do_sigpending, int, + __sigset_t *, set, size_t, sigsetsize) SHIM_SYSCALL_PASSTHROUGH (rt_sigtimedwait, 4, int, const __sigset_t *, uthese, siginfo_t *, uinfo, const struct timespec *, uts, diff --git a/LibOS/shim/src/sys/shim_brk.c b/LibOS/shim/src/sys/shim_brk.c index a3723e93..c76b29cb 100644 --- a/LibOS/shim/src/sys/shim_brk.c +++ b/LibOS/shim/src/sys/shim_brk.c @@ -59,7 +59,7 @@ void get_brk_region (void ** start, void ** end, void ** current) master_unlock(); } -int init_brk_region (void) +int init_brk_region (void * brk_region) { if (region.brk_start) return 0; @@ -73,8 +73,37 @@ int init_brk_region (void) brk_max_size = DEFAULT_BRK_MAX_SIZE; } - void * brk_region = get_unmapped_vma(brk_max_size, - MAP_PRIVATE|MAP_ANONYMOUS); + /* + * Chia-Che 8/24/2017 + * Adding an argument to specify the initial starting + * address of brk region. + * The general assumption of Linux is that the brk region + * should be within [exec-data-end, exec-data-end + 0x2000000) + */ + if (brk_region) { + while (true) { + uint32_t rand; + getrand(&rand, sizeof(rand)); + rand %= 0x2000000; + rand = ALIGN_UP(rand); + + struct shim_vma * vma; + if (lookup_overlap_vma(brk_region + rand, brk_max_size, &vma) + == -ENOENT) { + brk_region += rand; + break; + } + + brk_region = vma->addr + vma->length; + put_vma(vma); + } + } else { + brk_region = get_unmapped_vma(brk_max_size, + MAP_PRIVATE|MAP_ANONYMOUS); + if (!brk_region) + return -ENOMEM; + } + void * end_brk_region = NULL; // brk region assigned @@ -106,7 +135,7 @@ int init_brk_region (void) return 0; } -int init_brk (void) +int reset_brk (void) { master_lock(); @@ -132,7 +161,7 @@ int init_brk (void) void * shim_do_brk (void * brk) { master_lock(); - init_brk_region(); + init_brk_region(NULL); if (!brk) { unchanged: diff --git a/LibOS/shim/src/sys/shim_exec.c b/LibOS/shim/src/sys/shim_exec.c index 00247b5f..7e3d5bc6 100644 --- a/LibOS/shim/src/sys/shim_exec.c +++ b/LibOS/shim/src/sys/shim_exec.c @@ -71,6 +71,8 @@ static elf_auxv_t * new_auxp; #define REQUIRED_ELF_AUXV 6 +int init_brk_from_executable (struct shim_handle * exec); + int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv, const char ** envp) { @@ -127,13 +129,14 @@ int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv, clean_link_map_list(); SAVE_PROFILE_INTERVAL(unmap_loaded_binaries_for_exec); - init_brk(); + reset_brk(); unmap_all_vmas(); SAVE_PROFILE_INTERVAL(unmap_all_vmas_for_exec); if ((ret = load_elf_object(cur_thread->exec, NULL, 0)) < 0) shim_terminate(); + init_brk_from_executable(cur_thread->exec); load_elf_interp(cur_thread->exec); SAVE_PROFILE_INTERVAL(load_new_executable_for_exec); @@ -414,6 +417,6 @@ err: if (cur_thread->dummy) switch_dummy_thread(cur_thread); - try_process_exit(0); + try_process_exit(0, 0); return 0; } diff --git a/LibOS/shim/src/sys/shim_exit.c b/LibOS/shim/src/sys/shim_exit.c index 46eb4bbd..c886cab7 100644 --- a/LibOS/shim/src/sys/shim_exit.c +++ b/LibOS/shim/src/sys/shim_exit.c @@ -50,7 +50,7 @@ int thread_exit(struct shim_thread * self, bool send_ipc) /* Chia-Che: Broadcast exit message as early as possible, so other process can start early on responding. */ if (self->in_vm && send_ipc) - ipc_cld_exit_send(self->ppid, self->tid, self->exit_code); + ipc_cld_exit_send(self->ppid, self->tid, self->exit_code, self->term_signal); lock(self->lock); @@ -103,7 +103,7 @@ out: DkEventSet(parent->child_exit_event); } else { debug("parent not here, need to tell another process\n"); - ipc_cld_exit_send(self->ppid, self->tid, self->exit_code); + ipc_cld_exit_send(self->ppid, self->tid, self->exit_code, self->term_signal); } struct robust_list_head * robust_list = (void *) self->robust_list; @@ -127,11 +127,12 @@ out: return 0; } -int try_process_exit (int error_code) +int try_process_exit (int error_code, int term_signal) { struct shim_thread * cur_thread = get_cur_thread(); cur_thread->exit_code = -error_code; + cur_thread->term_signal = term_signal; if (cur_thread->in_vm) thread_exit(cur_thread, true); @@ -159,6 +160,7 @@ int shim_do_exit_group (int error_code) sysparser_printf("---- shim_exit_group (returning %d)\n", error_code); if (cur_thread->dummy) { + cur_thread->term_signal = 0; thread_exit(cur_thread, true); switch_dummy_thread(cur_thread); } @@ -167,7 +169,7 @@ int shim_do_exit_group (int error_code) do_kill_proc(cur_thread->tgid, cur_thread->tgid, SIGKILL, false); debug("now exit the process\n"); - try_process_exit(error_code); + try_process_exit(error_code, 0); #ifdef PROFILE if (ENTER_TIME) @@ -188,11 +190,12 @@ int shim_do_exit (int error_code) sysparser_printf("---- shim_exit (returning %d)\n", error_code); if (cur_thread->dummy) { + cur_thread->term_signal = 0; thread_exit(cur_thread, true); switch_dummy_thread(cur_thread); } - try_process_exit(error_code); + try_process_exit(error_code, 0); #ifdef PROFILE if (ENTER_TIME) diff --git a/LibOS/shim/src/sys/shim_fs.c b/LibOS/shim/src/sys/shim_fs.c index 284416bb..453dc598 100644 --- a/LibOS/shim/src/sys/shim_fs.c +++ b/LibOS/shim/src/sys/shim_fs.c @@ -58,7 +58,7 @@ int shim_do_unlink (const char * file) if (!dent->parent) return -EACCES; - if (dent->state & DENTRY_ISDIRECTORY) + if (dent->state & DENTRY_ISDIRECTORY) return -EISDIR; if (dent->fs && dent->fs->d_ops && @@ -275,9 +275,7 @@ int shim_do_chown (const char * path, uid_t uid, gid_t gid) if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent)) < 0) return ret; - /* do nothing*/ - -out: + /* XXX: do nothing now */ put_dentry(dent); return ret; } @@ -300,9 +298,7 @@ int shim_do_fchownat (int dfd, const char * filename, uid_t uid, gid_t gid, if ((ret = path_lookupat(dir, filename, LOOKUP_OPEN, &dent)) < 0) goto out; - /* do nothing */ - -out_dent: + /* XXX: do nothing now */ put_dentry(dent); out: put_dentry(dir); @@ -315,14 +311,8 @@ int shim_do_fchown (int fd, uid_t uid, gid_t gid) if (!hdl) return -EBADF; - struct shim_dentry * dent = hdl->dentry; - int ret = 0; - - /* do nothing */ - -out: - put_handle(hdl); - return ret; + /* XXX: do nothing now */ + return 0; } #define MAP_SIZE (allocsize * 4) diff --git a/LibOS/shim/src/sys/shim_getrlimit.c b/LibOS/shim/src/sys/shim_getrlimit.c index 1ae8c406..aa342d46 100644 --- a/LibOS/shim/src/sys/shim_getrlimit.c +++ b/LibOS/shim/src/sys/shim_getrlimit.c @@ -55,6 +55,11 @@ int shim_do_getrlimit (int resource, struct __kernel_rlimit * rlim) rlim->rlim_max = sys_stack_size; return 0; + case RLIMIT_DATA: + rlim->rlim_cur = brk_max_size; + rlim->rlim_max = brk_max_size; + return 0; + default: return -ENOSYS; } diff --git a/LibOS/shim/src/sys/shim_open.c b/LibOS/shim/src/sys/shim_open.c index f7f29bbf..6830c564 100644 --- a/LibOS/shim/src/sys/shim_open.c +++ b/LibOS/shim/src/sys/shim_open.c @@ -321,6 +321,12 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count) goto out; } + /* DEP 3/3/17: Properly handle an unlinked directory */ + if (hdl->dentry->state & DENTRY_NEGATIVE) { + ret = -ENOENT; + goto out; + } + /* we are grabbing the lock because the handle content is actually updated */ lock(hdl->lock); @@ -370,7 +376,9 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count) while (dirhdl->ptr && *dirhdl->ptr) { dent = *dirhdl->ptr; - ASSIGN_DIRENT(dent, dentry_get_name(dent), 0); + /* DEP 3/3/17: We need to filter negative dentries */ + if (!(dent->state & DENTRY_NEGATIVE)) + ASSIGN_DIRENT(dent, dentry_get_name(dent), 0); put_dentry(dent); *(dirhdl->ptr++) = NULL; } @@ -380,6 +388,11 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count) done: ret = bytes; + /* DEP 3/3/17: Properly detect EINVAL case, where buffer is too small to + * hold anything */ + if (bytes == 0 && ((dirhdl->ptr && *dirhdl->ptr) + || dirhdl->dotdot || dirhdl->dot)) + ret = -EINVAL; unlock(hdl->lock); out: put_handle(hdl); @@ -399,6 +412,12 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count) goto out; } + /* DEP 3/3/17: Properly handle an unlinked directory */ + if (hdl->dentry->state & DENTRY_NEGATIVE) { + ret = -ENOENT; + goto out; + } + lock(hdl->lock); struct shim_dir_handle * dirhdl = &hdl->info.dir; @@ -439,7 +458,9 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count) while (dirhdl->ptr && *dirhdl->ptr) { dent = *dirhdl->ptr; - ASSIGN_DIRENT(dent, dentry_get_name(dent), 0); + /* DEP 3/3/17: We need to filter negative dentries */ + if (!(dent->state & DENTRY_NEGATIVE)) + ASSIGN_DIRENT(dent, dentry_get_name(dent), 0); put_dentry(dent); *(dirhdl->ptr++) = NULL; } @@ -449,6 +470,11 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count) done: ret = bytes; + /* DEP 3/3/17: Properly detect EINVAL case, where buffer is too small to + * hold anything */ + if (bytes == 0 && ((dirhdl->ptr && *dirhdl->ptr) + || dirhdl->dotdot || dirhdl->dot)) + ret = -EINVAL; unlock(hdl->lock); out: put_handle(hdl); @@ -537,19 +563,15 @@ int shim_do_ftruncate (int fd, loff_t length) return -EBADF; struct shim_mount * fs = hdl->fs; - int ret = -EACCES; + int ret = -EINVAL; if (!fs || !fs->fs_ops) goto out; - if (hdl->type == TYPE_DIR) + if (hdl->type == TYPE_DIR || + !fs->fs_ops->truncate) goto out; - if (!fs->fs_ops->truncate) { - ret = -EROFS; - goto out; - } - ret = fs->fs_ops->truncate(hdl, length); out: put_handle(hdl); diff --git a/LibOS/shim/src/sys/shim_sigaction.c b/LibOS/shim/src/sys/shim_sigaction.c index aa54e6ff..9cfd8d7a 100644 --- a/LibOS/shim/src/sys/shim_sigaction.c +++ b/LibOS/shim/src/sys/shim_sigaction.c @@ -39,11 +39,12 @@ #include int shim_do_sigaction (int signum, const struct __kernel_sigaction * act, - struct __kernel_sigaction * oldact) + struct __kernel_sigaction * oldact, size_t sigsetsize) { /* SIGKILL and SIGSTOP cannot be caught or ignored */ if (signum == SIGKILL || signum == SIGSTOP || - signum <= 0 || signum > NUM_SIGS) + signum <= 0 || signum > NUM_SIGS || + sigsetsize != sizeof(__sigset_t)) return -EINVAL; struct shim_thread * cur = get_cur_thread(); @@ -145,14 +146,19 @@ int shim_do_sigaltstack (const stack_t * ss, stack_t * oss) return -EINVAL; struct shim_thread * cur = get_cur_thread(); - int err = 0; - lock(cur->lock); if (oss) *oss = cur->signal_altstack; - if (ss) + + if (ss) { + if (ss->ss_size < MINSIGSTKSZ) { + unlock(cur->lock); + return -ENOMEM; + } + cur->signal_altstack = *ss; + } unlock(cur->lock); return 0; @@ -162,7 +168,6 @@ int shim_do_sigsuspend (const __sigset_t * mask) { __sigset_t * old, tmp; struct shim_thread * cur = get_cur_thread(); - int err = 0; lock(cur->lock); @@ -174,12 +179,28 @@ int shim_do_sigsuspend (const __sigset_t * mask) cur->suspend_on_signal = true; thread_setwait(NULL, NULL); thread_sleep(NO_TIMEOUT); -out: + unlock(cur->lock); set_sig_mask(cur, old); + return -EINTR; +} - return err; +int shim_do_sigpending (__sigset_t * set, size_t sigsetsize) +{ + struct shim_thread * cur = get_cur_thread(); + __sigemptyset(set); + + if (!cur->signal_logs) + return 0; + + for (int sig = 1 ; sig <= NUM_SIGS ; sig++) { + if (atomic_read(&cur->signal_logs[sig - 1].head) != + atomic_read(&cur->signal_logs[sig - 1].tail)) + __sigaddset(set, sig); + } + + return 0; } struct walk_arg { @@ -471,7 +492,7 @@ int shim_do_kill (pid_t pid, int sig) specified by pid. */ else if (pid > 0) { ret = do_kill_proc(cur->tid, pid, sig, true); - send_to_self = (pid == cur->pgid); + send_to_self = (pid == cur->tgid); } /* If pid is less than -1, then sig is sent to every process in the diff --git a/LibOS/shim/src/sys/shim_socket.c b/LibOS/shim/src/sys/shim_socket.c index b8afeff4..ffdf8c49 100644 --- a/LibOS/shim/src/sys/shim_socket.c +++ b/LibOS/shim/src/sys/shim_socket.c @@ -951,7 +951,7 @@ int shim_do_accept (int fd, struct sockaddr * addr, socklen_t * addrlen) if (!hdl) return -EBADF; - int ret = __do_accept(hdl, flags & FD_CLOEXEC ? O_CLOEXEC : 0, + int ret = __do_accept(hdl, flags & O_CLOEXEC, addr, addrlen); put_handle(hdl); return ret; @@ -965,7 +965,7 @@ int shim_do_accept4 (int fd, struct sockaddr * addr, socklen_t * addrlen, return -EBADF; int ret = __do_accept(hdl, - (flags & SOCK_CLOEXEC ? FD_CLOEXEC : 0) | + (flags & SOCK_CLOEXEC ? O_CLOEXEC : 0) | (flags & SOCK_NONBLOCK ? O_NONBLOCK : 0), addr, addrlen); put_handle(hdl); @@ -1262,7 +1262,7 @@ int shim_do_recvmmsg (int sockfd, struct mmsghdr * msg, int vlen, int flags, struct msghdr * m = &msg[i].msg_hdr; int bytes = do_recvmsg(sockfd, m->msg_iov, m->msg_iovlen, flags, - m->msg_name, m->msg_namelen); + m->msg_name, &m->msg_namelen); if (bytes < 0) return total ? : bytes; diff --git a/LibOS/shim/src/sys/shim_wait.c b/LibOS/shim/src/sys/shim_wait.c index 49856360..35c51357 100644 --- a/LibOS/shim/src/sys/shim_wait.c +++ b/LibOS/shim/src/sys/shim_wait.c @@ -137,8 +137,12 @@ found_child: unlock(cur->lock); found: - if (status) - *status = (thread->exit_code & 0xff) << 8; + if (status) { + /* Bits 0--7 are for the signal, if any. + * Bits 8--15 are for the exit code */ + *status = thread->term_signal; + *status |= ((thread->exit_code & 0xff) << 8); + } ret = thread->tid; SAVE_PROFILE_INTERVAL_SINCE(child_exit_notification, thread->exit_time); diff --git a/LibOS/shim/test/.gitignore b/LibOS/shim/test/.gitignore new file mode 100644 index 00000000..6e6a284b --- /dev/null +++ b/LibOS/shim/test/.gitignore @@ -0,0 +1,6 @@ +*.manifest +*.manifest.sgx +*.sig +*.token +*.cached +pal_loader diff --git a/LibOS/shim/test/apps/apache/Makefile b/LibOS/shim/test/apps/apache/Makefile index dc67276e..b8dd6393 100644 --- a/LibOS/shim/test/apps/apache/Makefile +++ b/LibOS/shim/test/apps/apache/Makefile @@ -74,7 +74,7 @@ build-modules: $(INSTALL_DIR)/modules/mod_auth_basic_sandbox.so $(INSTALL_DIR)/modules/mod_auth_basic_sandbox.so: mod_auth_basic_sandbox.c $(INSTALL_DIR)/bin/apxs $(INSTALL_DIR)/bin/apxs $(APXS_FLAGS) \ -S CFLAGS="-I$(SHIMDIR)/../include" \ - -S LDFLAGS="-L$(LIBCDIR)/libos -llibos" -c -i -A $< + -S LDFLAGS="-L. -l:$(RUNTIME)/liblibos.so.1" -c -i -A $< build-conf: [ -f $(INSTALL_DIR)/conf/httpd.conf.old ] || \ diff --git a/LibOS/shim/test/apps/apache/benchmark-ab.sh b/LibOS/shim/test/apps/apache/benchmark-ab.sh new file mode 100755 index 00000000..e108bb66 --- /dev/null +++ b/LibOS/shim/test/apps/apache/benchmark-ab.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +declare -A THROUGHPUTS +declare -A LATENCIES +LOOP=5 +DOWNLOAD_HOST=$1 +DOWNLOAD_FILE=random/10K.1.html +REQUESTS=10000 +CONCURRENCY_LIST="1 2 4 8 16 32 64 128 256" +RESULT=result-$(date +%y%m%d-%H%M%S) + +touch $RESULT + +RUN=0 +while [ $RUN -lt $LOOP ] +do + for CONCURRENCY in $CONCURRENCY_LIST + do + rm -f OUTPUT + echo "ab -n $REQUESTS -c $CONCURRENCY http://$DOWNLOAD_HOST/$DOWNLOAD_FILE" + ab -n $REQUESTS -c $CONCURRENCY http://$DOWNLOAD_HOST/$DOWNLOAD_FILE > OUTPUT + + sleep 5 + + THROUGHPUT=$(grep -m1 "Requests per second:" OUTPUT | awk '{ print $4 }') + LATENCY=$(grep -m1 "Time per request:" OUTPUT | awk '{ print $4 }') + THROUGHPUTS[$CONCURRENCY]="${THROUGHPUTS[$CONCURRENCY]} $THROUGHPUT" + LATENCIES[$CONCURRENCY]="${LATENCIES[$CONCURRENCY]} $LATENCY" + echo "concurrency=$CONCURRENCY, throughput=$THROUGHPUT, latency=$LATENCY" + done + RUN=$(expr $RUN + 1) +done + +for CONCURRENCY in $CONCURRENCY_LIST +do + THROUGHPUT=$(echo ${THROUGHPUTS[$CONCURRENCY]} | tr " " "\n" | sort -n | awk '{a[NR]=$0}END{if(NR%2==1)print a[int(NR/2)+1];else print(a[NR/2-1]+a[NR/2])/2}') + LATENCY=$(echo ${LATENCIES[$CONCURRENCY]} | tr " " "\n" | sort -n | awk '{a[NR]=$0}END{if(NR%2==1)print a[int(NR/2)+1];else print(a[NR/2-1]+a[NR/2])/2}') + echo "$THROUGHPUT,$LATENCY" >> $RESULT +done + +echo "Result file: $RESULT" diff --git a/LibOS/shim/test/apps/apache/httpd.manifest.template b/LibOS/shim/test/apps/apache/httpd.manifest.template index 3a990e5f..4d5fec71 100644 --- a/LibOS/shim/test/apps/apache/httpd.manifest.template +++ b/LibOS/shim/test/apps/apache/httpd.manifest.template @@ -44,6 +44,10 @@ sgx.trusted_files.libxml2 = file:/usr/lib/x86_64-linux-gnu/libxml2.so.2 sgx.trusted_files.libz = file:/lib/x86_64-linux-gnu/libz.so.1 sgx.trusted_files.liblzma = file:/lib/x86_64-linux-gnu/liblzma.so.5 sgx.trusted_files.libnsl = file:/lib/x86_64-linux-gnu/libnsl.so.1 +sgx.trusted_files.libicuuc = file:/usr/lib/x86_64-linux-gnu/libicuuc.so.55 +sgx.trusted_files.libicudata = file:/usr/lib/x86_64-linux-gnu/libicudata.so.55 +sgx.trusted_files.libstdcpp = file:/usr/lib/x86_64-linux-gnu/libstdc++.so.6 +sgx.trusted_files.libgcc_c = file:/lib/x86_64-linux-gnu/libgcc_s.so.1 sgx.allowed_files.modules = file:obj/modules sgx.allowed_files.conf = file:obj/conf diff --git a/LibOS/shim/test/apps/gcc/Makefile b/LibOS/shim/test/apps/gcc/Makefile index 2496137c..fa2de1d0 100644 --- a/LibOS/shim/test/apps/gcc/Makefile +++ b/LibOS/shim/test/apps/gcc/Makefile @@ -90,6 +90,33 @@ obj/lib/$(MPC_OBJ): src/$(MPC_SRC) src/$(MPC_SRC): $(MPC_SRC).tar.gz src cd src && tar -xzf ../$< +regression: + @echo "\n\nBuilding GCC..." + @$(MAKE) >> /dev/null 2>&1 + + @echo "\n\nCompile hello.c:" + ./gcc.manifest test_files/helloworld.c -o hello + @chmod 755 hello + ./hello + + @echo "\n\nCompile bzip2.c:" + ./gcc.manifest test_files/bzip2.c -o bzip2 + @chmod 755 bzip2 + @[ ! -f bzip2.tmp ] || rm -f bzip2.tmp + @cp -f bzip2 bzip2.copy + ./bzip2 -z bzip2.copy && ./bzip2 -d bzip2.copy.bz2 + diff -q bzip2 bzip2.copy + @rm -f bzip2.copy + + @echo "\n\nCompile gzip.c:" + ./gcc.manifest test_files/gzip.c -o gzip + @chmod 755 gzip + @cp -f gzip gzip.copy + ./gzip gzip.copy && ./gzip -d gzip.copy.gz + diff -q gzip gzip.copy + @rm -f gzip.copy + + src: mkdir -p src diff --git a/LibOS/shim/test/apps/lmbench/Makefile b/LibOS/shim/test/apps/lmbench/Makefile index c3e08fc5..3a8607ec 100644 --- a/LibOS/shim/test/apps/lmbench/Makefile +++ b/LibOS/shim/test/apps/lmbench/Makefile @@ -66,5 +66,11 @@ test-graphene: all $(lmbench_config) env LOADER=./pal_loader OS=linux RESULTS=results/graphene \ ./results +regression: all + cp -f lmbench-regression $(LMBENCHDIR)/bin/linux + cd $(LMBENCHDIR)/bin/linux && \ + env LOADER=./pal_loader OS=linux \ + ./lmbench-regression + clean-lmbench: $(MAKE) -C $(LMBENCHDIR) clean diff --git a/LibOS/shim/test/apps/lmbench/lmbench-regression b/LibOS/shim/test/apps/lmbench/lmbench-regression new file mode 100755 index 00000000..0c0a76e7 --- /dev/null +++ b/LibOS/shim/test/apps/lmbench/lmbench-regression @@ -0,0 +1,222 @@ +#!/bin/bash + +# lmbench - run the lmbench benchmark suite. +# +# Hacked by Larry McVoy (lm@sun.com, lm@sgi.com, lm@bitmover.com). +# Copyright (c) 1994 Larry McVoy. GPLed software. +# $Id$ + +# Make sure we can find: ./cmd, df, and netstat +PATH=.:../../scripts:$PATH:/etc:/usr/etc:/sbin:/usr/sbin +export PATH + +echo PATH = $PATH +echo lat_syscall = `readlink -f lat_syscall` + +# lat_unix, lat_udp, lat_tcp only do one run!!! +# we loop to repeat the tests +N_RUNS=6 + +if [ -f $1 ] +then . $1 + echo Using config in $1 +else echo Using defaults + ENOUGH=1000000 + TIMING_O=0 + LOOP_O=0 +fi +export ENOUGH TIMING_O LOOP_O + +if [ X$FILE = X ] +then FILE=/tmp/XXX + touch $FILE || echo Can not create $FILE +fi +if [ X$MB = X ] +then MB=8 +fi +AVAILKB=`expr $MB \* 1024` + +# Figure out how big we can go for stuff that wants to use +# all and half of memory. +HALF="512 1k 2k 4k 8k 16k 32k 64k 128k 256k 512k 1m" +ALL="$HALF 2m" +i=4 +while [ $i -le $MB ] +do + ALL="$ALL ${i}m" + h=`expr $i / 2` + HALF="$HALF ${h}m" + i=`expr $i \* 2` +done + + +if [ X$FSDIR = X ] +then FSDIR=/tmp/lat_fs +fi +MP=N + +# Figure out as much stuff as we can about this system. +# Sure would be nice if everyone had SGI's "hinv". +echo \[lmbench2.0 results for `uname -a`] 1>&2 +echo \[ALL: ${ALL}] 1>&2 +echo \[DISKS: ${DISKS}] 1>&2 +echo \[DISK_DESC: ${DISK_DESC}] 1>&2 +echo \[ENOUGH: ${ENOUGH}] 1>&2 +echo \[FAST: ${FAST}] 1>&2 +echo \[FASTMEM: ${FASTMEM}] 1>&2 +echo \[FILE: ${FILE}] 1>&2 +echo \[FSDIR: ${FSDIR}] 1>&2 +echo \[HALF: ${HALF}] 1>&2 +echo \[INFO: ${INFO}] 1>&2 +echo \[LOOP_O: ${LOOP_O}] 1>&2 +echo \[MB: ${MB}] 1>&2 +echo \[MHZ: ${MHZ}] 1>&2 +echo \[MOTHERBOARD: ${MOTHERBOARD}] 1>&2 +echo \[NETrunS: ${NETrunS}] 1>&2 +echo \[PROCESSORS: ${PROCESSORS}] 1>&2 +echo \[REMOTE: ${REMOTE}] 1>&2 +echo \[SLOWFS: ${SLOWFS}] 1>&2 +echo \[OS: ${OS}] 1>&2 +echo \[TIMING_O: ${TIMING_O}] 1>&2 +echo \[LMBENCH VERSION: ${VERSION}] 1>&2 +echo \[USER: $USER] 1>&2 +echo \[HOSTNAME: `hostname`] 1>&2 +echo \[NODENAME: `uname -n`] 1>&2 +echo \[SYSNAME: `uname -s`] 1>&2 +echo \[PROCESSOR: `uname -p`] 1>&2 +echo \[MACHINE: `uname -m`] 1>&2 +echo \[RELEASE: `uname -r`] 1>&2 +echo \[VERSION: `uname -v`] 1>&2 +#if 0 +echo \[`date`] 1>&2 +echo \[`uptime`] 1>&2 +netstat -i | while read i +do echo \[net: "$i"] 1>&2 + set `echo $i` + case $1 in + *ame) ;; + *) ifconfig $1 | while read i + do echo \[if: "$i"] 1>&2 + done + ;; + esac +done + +mount | while read i +do echo \[mount: "$i"] 1>&2 +done + +STAT=$FSDIR/lmbench +mkdir $FSDIR 2>/dev/null +touch $STAT 2>/dev/null +if [ ! -f $STAT ] +then echo "Can't make a file - $STAT - in $FSDIR" + touch $STAT + exit 1 +fi + +function run { + echo "$@" + TMPOUT=/tmp/OUT + rm -rf $TMPOUT + $LOADER "$@" 2>>$TMPOUT | tee -a $TMPOUT + cat $TMPOUT 1>&2 +} + +date +echo Latency measurements +msleep 250 +run lat_syscall null +run lat_syscall read +run lat_syscall write +run lat_syscall stat $STAT +run lat_syscall fstat $STAT +run lat_syscall open $STAT + +#select file (500), select tcp (500) +run lat_select file 500 +run lat_select tcp 500 + +#sig install, sig_overhead, prot. Fault +run lat_sig install +run lat_sig catch +run lat_sig prot lat_sig + +#AF_UNIX +echo AF_UNIX socket latency +for i in $(eval echo "{1..$N_RUNS}") +do run lat_unix +done + +#forks +cp hello /tmp/hello +for i in fork dfork vfork exec dforkexec shell +do run lat_proc $i +done +rm -f /tmp/hello + +for i in $(eval echo "{1..$N_RUNS}") +do rm -f $FILE + run lmdd label="File $FILE write bandwidth:" of=$FILE move=${MB}m fsync=1 print=3 +done + +#0,4,10KB create/delete +date + echo Calculating file system latency + echo '"File system latency' 1>&2 + run lat_fs $FSDIR + echo "" 1>&2 + +date +echo Local netruning + +echo UDP socket latency +run lat_udp -s & +sleep 3 +for i in $(eval echo "{1..$N_RUNS}") +do run lat_udp 127.0.0.1 + sleep 1 +done +run lat_udp -127.0.0.1 +sleep 3 + +echo TCP socket latency +run lat_tcp -s & +sleep 3 +for i in $(eval echo "{1..$N_RUNS}") +do run lat_tcp 127.0.0.1 + sleep 1 +done +run lat_tcp -127.0.0.1 +sleep 3 + +echo TCP connect latency +run lat_connect -s & +sleep 3 +run lat_connect 127.0.0.1 +sleep 1 +run lat_connect -127.0.0.1 +sleep 3 + +echo TCP socket bandwidth +run bw_tcp -s & +sleep 3 +for i in $(eval echo "{1..$N_RUNS}") +do run bw_tcp 127.0.0.1 + sleep 1 +done +run bw_tcp -127.0.0.1 +sleep 3 + +date +echo Bandwidth measurements + +for i in $(eval echo "{1..$N_RUNS}") +do run bw_unix +done + +for i in $(eval echo "{1..$N_RUNS}") +do run bw_pipe +done + +exit 0 diff --git a/LibOS/shim/test/apps/lmbench/manifest.template b/LibOS/shim/test/apps/lmbench/manifest.template index 9b76ac65..d4556146 100644 --- a/LibOS/shim/test/apps/lmbench/manifest.template +++ b/LibOS/shim/test/apps/lmbench/manifest.template @@ -40,11 +40,5 @@ sgx.allowed_files.tmp1 = file:/tmp sgx.allowed_files.tmp2 = file:/var/tmp sgx.allowed_files.inc = file:/usr/include/x86_64-linux-gnu/sys/types.h -sgx.trusted_files.test1 = file:random.64K -sgx.trusted_files.test2 = file:random.256K -sgx.trusted_files.test3 = file:random.1M -sgx.trusted_files.test4 = file:random.4M -sgx.trusted_files.test5 = file:random.16M - sgx.trusted_children.hello = file:hello.sig sgx.trusted_children.sh = file:sh.sig diff --git a/LibOS/shim/test/apps/ltp/Makefile b/LibOS/shim/test/apps/ltp/Makefile index 1799c44a..e979cf47 100644 --- a/LibOS/shim/test/apps/ltp/Makefile +++ b/LibOS/shim/test/apps/ltp/Makefile @@ -1,4 +1,6 @@ -SRCDIR = ltp-master +SRCURL = https://github.com/linux-test-project/ltp/releases/download/ +SRCVERSION = 20170116 +SRCDIR = ltp-full-$(SRCVERSION) BUILDDIR = opt/ltp TESTCASEDIR = $(BUILDDIR)/testcases/bin @@ -10,11 +12,11 @@ clean-extra = clean-build level = ../../ include ../../Makefile -master.zip: - wget https://github.com/linux-test-project/ltp/archive/master.zip +$(SRCDIR).tar.xz: + wget $(SRCURL)/$(SRCVERSION)/$@ -$(SRCDIR)/configure: master.zip - unzip master.zip +$(SRCDIR)/configure: $(SRCDIR).tar.xz + tar -xJf $< cd $(SRCDIR) && make autotools $(BUILDDIR)/runltp: $(SRCDIR)/configure @@ -38,5 +40,12 @@ $(TESTCASEDIR)/manifest.template: manifest.template $(TESTCASEDIR)/Makefile: Makefile.testcases ln -sf ../../../../$< $@ +regression: + @echo "\n\nBuilding LTP..." + @$(MAKE) >> /dev/null 2>&1 + + @echo "\n\nLTP tests for system calls:" + ./syscalls.sh + clean-build: rm -rf $(BUILDDIR) diff --git a/LibOS/shim/test/apps/ltp/Makefile.testcases b/LibOS/shim/test/apps/ltp/Makefile.testcases index 459a2add..5c3c4d09 100644 --- a/LibOS/shim/test/apps/ltp/Makefile.testcases +++ b/LibOS/shim/test/apps/ltp/Makefile.testcases @@ -2,10 +2,18 @@ manifests = $(wildcard ../../../../*.manifest.template) manifest testcases = $(filter-out $(wildcard *.*) $(patsubst %/,%,$(wildcard */)) Makefile manifest pal_loader,$(wildcard *)) exec_target = $(testcases) -target = $(manifests) $(testcases) +target = $(manifests) $(testcases) etc/nsswitch.conf etc/passwd level = ../../../../../../ include ../../../../../../Makefile $(addsuffix .template,$(manifests)): %: ../../../../% ln -sf $< $@ + +etc/nsswitch.conf: + mkdir -p etc + echo "passwd: compat\ngroup: compat\nshadow: compat\nhosts: files" > $@ + +etc/passwd: + mkdir -p etc + echo "root:x:0:0:root:/root:/bin/bash\nnobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin" > $@ diff --git a/LibOS/shim/test/apps/ltp/PASSED b/LibOS/shim/test/apps/ltp/PASSED index 3905db95..5ce5794b 100644 --- a/LibOS/shim/test/apps/ltp/PASSED +++ b/LibOS/shim/test/apps/ltp/PASSED @@ -1,6 +1,10 @@ Test,Subtest number accept01,1 accept01,2 +accept4_01,1 +accept4_01,2 +accept4_01,3 +accept4_01,4 alarm01,1 alarm02,1 alarm02,2 @@ -11,20 +15,46 @@ asyncio02,3 asyncio02,4 asyncio02,5 asyncio02,6 +brk01,1 chmod01,1 +chmod01,2 +chmod01,3 +chmod01,4 +chmod01,5 +chmod01,6 +chmod01,7 +chmod01,8 chmod02,1 +chmod02,2 +chmod02,3 +chmod02,4 +chmod02,5 +chmod02,6 +chmod02,7 +chmod02,8 +chmod03,1 chown01,1 chroot02,1 -close01,1 -close01,2 -close08,1 +clock_getres01,3 +clock_getres01,4 +clock_getres01,5 +clock_getres01,6 +clock_getres01,8 +clock_getres01,9 +clock_getres01,10 +clock_getres01,11 +clock_getres01,12 +clock_getres01,13 +clock_nanosleep01,12 clone01,1 clone03,1 clone04,1 -clone05,1 clone06,1 clone07,1 +close01,1 +close01,2 close02,1 +close08,1 confstr01,1 confstr01,2 confstr01,3 @@ -44,6 +74,13 @@ confstr01,16 confstr01,17 confstr01,18 confstr01,19 +creat01,3 +creat01,4 +creat01,5 +creat01,6 +creat01,7 +creat01,8 +creat03,4 dup01,1 dup02,1 dup02,2 @@ -55,8 +92,23 @@ dup203,1 dup203,2 dup204,1 dup204,2 +epoll_create1_01,3 +epoll_ctl01,3 +epoll_ctl01,5 +epoll_ctl02,3 +epoll_ctl02,4 +epoll_ctl02,7 +epoll_ctl02,8 +epoll_ctl02,9 epoll_wait03,1 epoll_wait03,2 +execl01,1 +execlp01,1 +execv01,1 +execvp01,1 +exit01,1 +exit02,1 +exit_group01,1 faccessat01,1 faccessat01,2 faccessat01,3 @@ -67,6 +119,13 @@ fchdir01,1 fchdir02,1 fchmod01,1 fchmod07,1 +fchmod07,2 +fchmod07,3 +fchmod07,4 +fchmod07,5 +fchmod07,6 +fchmod07,7 +fchmod07,8 fchmodat01,1 fchmodat01,2 fchmodat01,3 @@ -75,13 +134,28 @@ fchmodat01,5 fchmodat01,6 fchown01,1 fchown02,4 +fcntl02,1 +fcntl02_64,1 +fcntl03,1 +fcntl03_64,1 +fcntl04,1 +fcntl04_64,1 fcntl08,1 +fcntl08_64,1 fcntl13,6 +fcntl13_64,6 fcntl27,1 +fcntl27_64,1 fcntl28,1 +fcntl28_64,1 fdatasync01,1 fdatasync02,1 flock06,2 +fmtmsg01,1 +fmtmsg01,2 +fmtmsg01,3 +fmtmsg01,4 +fmtmsg01,5 fork01,1 fork01,2 fork02,1 @@ -100,15 +174,20 @@ fpathconf01,7 fpathconf01,8 fpathconf01,9 fstat01,1 +fstat01_64,1 fstat03,1 -fstat05,1 +fstat03_64,1 fsync01,1 fsync03,1 ftruncate01,1 ftruncate01_64,1 ftruncate02,1 ftruncate02_64,1 +ftruncate03,1 +ftruncate03,2 ftruncate03,3 +ftruncate03_64,1 +ftruncate03_64,2 ftruncate03_64,3 futex_wait01,1 futex_wait01,2 @@ -117,23 +196,27 @@ futex_wait01,4 futex_wait03,1 futex_wait04,1 futex_wait05,1 +futex_wait_bitset01,1 +futex_wait_bitset02,1 futex_wake01,1 futex_wake01,2 futex_wake01,3 futex_wake01,4 futex_wake01,5 futex_wake01,6 -futex_wait_bitset01,1 -futex_wait_bitset02,1 getcontext01,1 getdents02,1 getdents02,2 getdents02,3 +getdents02,4 getdomainname01,1 getdtablesize01,1 getegid01,1 +getegid02,1 geteuid01,1 +geteuid02,1 getgid01,1 +getgid03,1 gethostbyname_r01,1 gethostname01,1 getitimer01,1 @@ -148,6 +231,7 @@ getpgrp01,1 getpid01,1 getpid02,1 getppid01,1 +getrlimit01,3 getrlimit01,4 getrlimit01,6 getrlimit01,8 @@ -157,6 +241,8 @@ getsockopt01,1 getsockopt01,2 gettid01,1 getuid01,1 +getuid03,1 +kill01,1 kill03,1 kill09,1 listen01,1 @@ -183,13 +269,13 @@ mallopt01,3 mallopt01,4 mallopt01,5 mallopt01,6 -memset01,1 -memset01,2 memcmp01,1 memcmp01,2 memcpy01,1 memcpy01,2 memcpy01,3 +memset01,1 +memset01,2 mkdir08,1 mlock03,1 mmap001,1 @@ -203,14 +289,21 @@ mmap08,1 mmap09,1 mmap09,2 mmap09,3 +mmap13,1 +mprotect01,3 mprotect02,1 mprotect02,2 mprotect03,1 mprotect04,1 mprotect04,2 msgrcv01,1 +msgsnd02,2 +msgsnd03,3 +msgsnd03,4 +msgsnd04,1 munmap01,1 munmap02,1 +nanosleep01,1 nanosleep03,1 newuname01,1 open03,1 @@ -224,16 +317,65 @@ pathconf01,5 pathconf01,6 pathconf01,7 personality02,1 +pipe01,3 pipe09,1 pipe10,1 pipe2_01,1 poll01,1 poll01,2 +poll02,1 pread01,1 +pread01_64,1 pread02,1 -ptrace05,1 +pread02_64,1 +preadv01,3 +preadv01,4 +preadv01,5 +preadv01_64,3 +preadv01_64,4 +preadv01_64,5 +preadv02,3 +preadv02_64,3 +process_vm01,2 +process_vm01,4 +process_vm01,6 +process_vm01,8 +process_vm01,11 +process_vm01,13 +process_vm01,15 +process_vm01,17 +process_vm01,19 +process_vm01,21 +pselect01,1 +pselect01,2 +pselect01,3 +pselect01,4 +pselect01,5 +pselect01,6 +pselect01,7 +pselect01,8 +pselect01,9 +pselect01_64,1 +pselect01_64,2 +pselect01_64,3 +pselect01_64,4 +pselect01_64,5 +pselect01_64,6 +pselect01_64,7 +pselect01_64,8 +pselect01_64,9 pwrite01,1 +pwrite01_64,1 pwrite04,2 +pwrite04_64,2 +pwritev01,3 +pwritev01,4 +pwritev01,5 +pwritev01_64,3 +pwritev01_64,4 +pwritev01_64,5 +pwritev02,3 +pwritev02_64,3 read01,1 read04,1 readdir01,1 @@ -396,6 +538,162 @@ rt_sigaction01,152 rt_sigaction01,153 rt_sigaction01,154 rt_sigaction01,155 +rt_sigaction03,1 +rt_sigaction03,2 +rt_sigaction03,3 +rt_sigaction03,4 +rt_sigaction03,5 +rt_sigaction03,6 +rt_sigaction03,7 +rt_sigaction03,8 +rt_sigaction03,9 +rt_sigaction03,10 +rt_sigaction03,11 +rt_sigaction03,12 +rt_sigaction03,13 +rt_sigaction03,14 +rt_sigaction03,15 +rt_sigaction03,16 +rt_sigaction03,17 +rt_sigaction03,18 +rt_sigaction03,19 +rt_sigaction03,20 +rt_sigaction03,21 +rt_sigaction03,22 +rt_sigaction03,23 +rt_sigaction03,24 +rt_sigaction03,25 +rt_sigaction03,26 +rt_sigaction03,27 +rt_sigaction03,28 +rt_sigaction03,29 +rt_sigaction03,30 +rt_sigaction03,31 +rt_sigaction03,32 +rt_sigaction03,33 +rt_sigaction03,34 +rt_sigaction03,35 +rt_sigaction03,36 +rt_sigaction03,37 +rt_sigaction03,38 +rt_sigaction03,39 +rt_sigaction03,40 +rt_sigaction03,41 +rt_sigaction03,42 +rt_sigaction03,43 +rt_sigaction03,44 +rt_sigaction03,45 +rt_sigaction03,46 +rt_sigaction03,47 +rt_sigaction03,48 +rt_sigaction03,49 +rt_sigaction03,50 +rt_sigaction03,51 +rt_sigaction03,52 +rt_sigaction03,53 +rt_sigaction03,54 +rt_sigaction03,55 +rt_sigaction03,56 +rt_sigaction03,57 +rt_sigaction03,58 +rt_sigaction03,59 +rt_sigaction03,60 +rt_sigaction03,61 +rt_sigaction03,62 +rt_sigaction03,63 +rt_sigaction03,64 +rt_sigaction03,65 +rt_sigaction03,66 +rt_sigaction03,67 +rt_sigaction03,68 +rt_sigaction03,69 +rt_sigaction03,70 +rt_sigaction03,71 +rt_sigaction03,72 +rt_sigaction03,73 +rt_sigaction03,74 +rt_sigaction03,75 +rt_sigaction03,76 +rt_sigaction03,77 +rt_sigaction03,78 +rt_sigaction03,79 +rt_sigaction03,80 +rt_sigaction03,81 +rt_sigaction03,82 +rt_sigaction03,83 +rt_sigaction03,84 +rt_sigaction03,85 +rt_sigaction03,86 +rt_sigaction03,87 +rt_sigaction03,88 +rt_sigaction03,89 +rt_sigaction03,90 +rt_sigaction03,91 +rt_sigaction03,92 +rt_sigaction03,93 +rt_sigaction03,94 +rt_sigaction03,95 +rt_sigaction03,96 +rt_sigaction03,97 +rt_sigaction03,98 +rt_sigaction03,99 +rt_sigaction03,100 +rt_sigaction03,101 +rt_sigaction03,102 +rt_sigaction03,103 +rt_sigaction03,104 +rt_sigaction03,105 +rt_sigaction03,106 +rt_sigaction03,107 +rt_sigaction03,108 +rt_sigaction03,109 +rt_sigaction03,110 +rt_sigaction03,111 +rt_sigaction03,112 +rt_sigaction03,113 +rt_sigaction03,114 +rt_sigaction03,115 +rt_sigaction03,116 +rt_sigaction03,117 +rt_sigaction03,118 +rt_sigaction03,119 +rt_sigaction03,120 +rt_sigaction03,121 +rt_sigaction03,122 +rt_sigaction03,123 +rt_sigaction03,124 +rt_sigaction03,125 +rt_sigaction03,126 +rt_sigaction03,127 +rt_sigaction03,128 +rt_sigaction03,129 +rt_sigaction03,130 +rt_sigaction03,131 +rt_sigaction03,132 +rt_sigaction03,133 +rt_sigaction03,134 +rt_sigaction03,135 +rt_sigaction03,136 +rt_sigaction03,137 +rt_sigaction03,138 +rt_sigaction03,139 +rt_sigaction03,140 +rt_sigaction03,141 +rt_sigaction03,142 +rt_sigaction03,143 +rt_sigaction03,144 +rt_sigaction03,145 +rt_sigaction03,146 +rt_sigaction03,147 +rt_sigaction03,148 +rt_sigaction03,149 +rt_sigaction03,150 +rt_sigaction03,151 +rt_sigaction03,152 +rt_sigaction03,153 +rt_sigaction03,154 +rt_sigaction03,155 +rt_sigsuspend01,1 sbrk01,1 sbrk01,2 sbrk02,1 @@ -407,6 +705,7 @@ select02,1 semctl01,2 semctl01,3 semctl07,4 +semget02,2 semget03,1 semop01,1 semop04,1 @@ -419,7 +718,6 @@ sendfile03_64,2 sendfile03_64,3 sendfile05,1 sendfile05_64,1 -set_tid_address01,1 setgid01,1 setitimer01,1 setpgid01,1 @@ -429,6 +727,7 @@ setpgrp02,1 setrlimit01,1 setsockopt01,1 setsockopt01,2 +set_tid_address01,1 settimeofday01,3 setuid01,1 setuid02,1 @@ -436,6 +735,9 @@ sigaction01,4 sigaction02,1 sigaction02,2 sigaction02,3 +sigaltstack01,1 +sigaltstack02,1 +sigaltstack02,2 signal02,1 signal02,2 signal02,3 @@ -534,15 +836,30 @@ signal06,2 signal06,3 signal06,4 signal06,5 +sigprocmask01,1 +sigsuspend01,1 +socket01,10 +socket01,5 +socket01,7 +socket02,3 +socket02,4 +socket02,5 +socket02,6 socketcall02,1 socketcall03,1 socketcall04,1 +socketpair02,3 sockioctl01,1 -splice02,1 +stat02,1 +stat02_64,1 stat05,1 +stat05_64,1 string01,1 sync01,1 sync02,1 +syscall01,3 +syscall01,4 +syscall01,5 sysconf01,1 sysconf01,2 sysconf01,4 @@ -596,8 +913,6 @@ tkill01,1 tkill01,2 truncate01,1 truncate01_64,1 -umask01,1 -umask02,1 uname01,1 uname03,1 unlink05,1 @@ -608,28 +923,42 @@ unlinkat01,4 unlinkat01,6 unlinkat01,7 ustat02,1 +vfork02,1 wait01,1 wait02,1 wait401,1 wait401,2 waitpid01,1 +waitpid01,2 waitpid02,1 +waitpid02,2 waitpid02,3 waitpid03,1 waitpid03,2 waitpid05,1 -waitpid05,11 -waitpid05,14 -waitpid05,18 -waitpid05,22 -waitpid05,26 +waitpid05,2 waitpid05,3 -waitpid05,30 -waitpid05,34 -waitpid05,37 waitpid05,4 -waitpid05,40 +waitpid05,5 waitpid05,7 +waitpid05,8 +waitpid05,10 +waitpid05,11 +waitpid05,13 +waitpid05,14 +waitpid05,16 +waitpid05,17 +waitpid05,19 +waitpid05,20 +waitpid05,21 +waitpid05,22 +waitpid05,24 +waitpid05,25 +waitpid05,26 +waitpid05,27 +waitpid05,28 +waitpid05,29 +waitpid05,30 write01,1 write02,1 write03,1 diff --git a/LibOS/shim/test/apps/ltp/TIMEOUTS b/LibOS/shim/test/apps/ltp/TIMEOUTS index 03c9ab1d..b315bcbd 100644 --- a/LibOS/shim/test/apps/ltp/TIMEOUTS +++ b/LibOS/shim/test/apps/ltp/TIMEOUTS @@ -1,4 +1,5 @@ testcase,timeout clone05,30 alarm01,5 -alarm06,16 +alarm06,16 +waitpid05,160 diff --git a/LibOS/shim/test/apps/ltp/edit_sys_tests.awk b/LibOS/shim/test/apps/ltp/edit_sys_tests.awk index 448f6952..d0cdddbf 100644 --- a/LibOS/shim/test/apps/ltp/edit_sys_tests.awk +++ b/LibOS/shim/test/apps/ltp/edit_sys_tests.awk @@ -4,22 +4,29 @@ BEGIN{ test = $1$2$3 blocked[test] } + + if (SGX) { + pal_str = "./pal_loader SGX" + } else { + pal_str = "./pal_loader" + } } + NF && ! /^#/ { test = $2$3 if($1=="splice02") { - s = "./pal_loader" + s = pal_str for (i=2; i<=NF; i++) { s = s " " $i if($i=="|") { i++ - s = s " ./pal_loader " $i + s = s " " pal_str " " $i } } print s } else if(! (test in blocked)) { - s = "./pal_loader" + s = pal_str for (i=2; i<=NF; i++) { s = s " " $i } diff --git a/LibOS/shim/test/apps/ltp/fetch.py b/LibOS/shim/test/apps/ltp/fetch.py index 53e3d293..fe6afa6e 100644 --- a/LibOS/shim/test/apps/ltp/fetch.py +++ b/LibOS/shim/test/apps/ltp/fetch.py @@ -1,80 +1,92 @@ import subprocess import csv import os -import threading import time import signal import tempfile +import multiprocessing -class RunCmd(threading.Thread): - def __init__(self, cmd, timeout, test): - threading.Thread.__init__(self) - self.cmd = cmd - self.timeout = int(timeout)*100 - self.output = "" - self.test = test - self.test_subtest = test - - def run(self): - name = tempfile.NamedTemporaryFile(mode='w+b') - self.p = subprocess.Popen(self.cmd, shell=True, stdout=name, stderr=subprocess.STDOUT, preexec_fn=os.setsid, close_fds=True) - self.curtime = time.time() - self.endtime = self.curtime + self.timeout - needed_times = self.timeout +def run(cmd, timeout, test): + try: + timeout = timeout * 100 + result = {} + result['test'] = test + outfile = tempfile.NamedTemporaryFile(mode='w+b') + p = subprocess.Popen(cmd, shell=True, stdout=outfile, stderr=subprocess.STDOUT, preexec_fn=os.setsid, close_fds=True) + result['curtime'] = time.time() + result['endtime'] = result['curtime'] + timeout sleep_time = 0 finish = False - while sleep_time < self.timeout: - if self.p.poll() is not None: + while sleep_time < timeout: + if p.poll() is not None: finish = True break sleep_time += 1 time.sleep(.01) - if not finish and self.p.poll() is None: - timed_out = True - print CRED + "[Hanged ] " + self.test_subtest + CEND - current_hanged[self.test_subtest] = 1 - os.killpg(os.getpgid(self.p.pid), signal.SIGKILL) - del self.p + result['finish'] = finish + outfile.seek(0) + result['output'] = outfile.readlines() + return result + except Exception as e: + print str(e) + return None + finally: + if p is not None and p.poll() is None: + os.killpg(os.getpgid(p.pid), signal.SIGKILL) - if (finish): +def finish(result): + try: + test = result['test'] + if not result['finish']: + print CRED + "[Hanged ] " + test + CEND + current_hanged[test] = 1 + else: reported = False - name.seek(0) - for output in name.readlines(): - toks = output.split() - if len(toks)<2 or (toks[0] != self.test and self.test != "memcmp01" and self.test != "memcpy01"): + count = 1 + for output in result['output']: + tokens = output.split() + if len(tokens) < 2: continue - test_subtest = self.test + "," + toks[1] - self.test_subtest = test_subtest - if "TINFO" in output or test_subtest in current_passed or test_subtest in current_failed or self.test in current_hanged or test_subtest in current_broken: + if tokens[1].isdigit(): + test_subtest = test + "," + tokens[1] + count = int(tokens[1]) + 1 + else: + test_subtest = test + "," + str(count) + count = count + 1 + if "TINFO" in output or test_subtest in current_passed or test_subtest in current_failed or test in current_hanged or test_subtest in current_broken: continue + if output: output = output.strip() print >>f1, output + if "TFAIL" in output: print >>failed_tests_fh, test_subtest print CRED + "[Fail ] " + test_subtest + CEND current_failed[test_subtest] = 1 reported = True - elif "TPASS" in output: + + elif "TPASS" in output or "PASS:" in output: print >>passed_tests_fh, test_subtest print CGREEN + "[Pass ] " + test_subtest + CEND current_passed[test_subtest] = 1 reported = True - elif "TCONF" in output or "TBROK" in output or "error" in output: + + elif "TCONF" in output or "TBROK" in output or "BROK" in output or "error" in output: print >>broken_tests_fh, test_subtest - print "[Broken ] " + test_subtest #Syscall not implemented or test preparation failed + # Syscall not implemented or test preparation failed + print "[Broken ] " + test_subtest current_broken[test_subtest] = 1 reported = True - #else: - # print "[Broken ] " + self.test #Syscall not implemented or test preparation failed + if (not reported): - print >>broken_tests_fh, self.test - print CRED + "[Broken ] " + self.test + CEND - current_broken[self.test] = 1 - def Run(self): - self.start() - self.join() + print >>broken_tests_fh, test + print CRED + "[Broken ] " + test + CEND + current_broken[test] = 1 + + except Exception as e: + print str(e) CRED = '\033[91m' CGREEN = '\033[92m' @@ -109,22 +121,30 @@ with open(timeouts, 'rb') as csvfile: for row in test_timeout: test = row[0] timeout = row[1] - timeouts_dict[test] = timeout + timeouts_dict[test] = int(timeout) os.chdir("opt/ltp/testcases/bin") +pool = multiprocessing.Pool() with open('../../../../syscalls.graphene') as testcases: for line in testcases: + line = line.strip('\r\n\t') tokens = line.split( ) - test = tokens[1] + if (tokens[1] == "SGX") : + test = tokens[2] + else : + test = tokens[1] + if test=="seq": test = tokens[6] #splice02 try: timeout = timeouts_dict[test] except KeyError: timeout = DEFAULT_TIMEOUT - RunCmd([line], timeout, test).Run() - time.sleep(.1) + pool.apply_async(run, args=([line], timeout, test), callback=finish) os.chdir("../../../..") + +pool.close() +pool.join() stable_passed = dict() with open(stablePass, 'rb') as csvfile: @@ -136,11 +156,11 @@ with open(stablePass, 'rb') as csvfile: print "\n\nRESULT [Difference] :\n---------------------\n" -for test in stable_passed: +for test in sorted(stable_passed): if not test in current_passed: print CRED + "Test '" + test + "' did not pass in the current run!!" + CEND -for test in current_passed: +for test in sorted(current_passed): if not test in stable_passed: print CGREEN + "Test '" + test + "' passed in the current run!!" + CEND print "\n" diff --git a/LibOS/shim/test/apps/ltp/manifest.template b/LibOS/shim/test/apps/ltp/manifest.template index 226b0a91..eb476db2 100644 --- a/LibOS/shim/test/apps/ltp/manifest.template +++ b/LibOS/shim/test/apps/ltp/manifest.template @@ -1,15 +1,28 @@ loader.preload = file:$(SHIMPATH) -loader.env.LD_LIBRARY_PATH = /lib:/lib64:/usr/lib:/usr/lib64 +loader.env.LD_LIBRARY_PATH = /lib:/lib/x86_64-linux-gnu:/usr/lib:/usr/lib64 +loader.env.PATH = /bin:/usr/bin:. loader.debug_type = none +fs.mount.shm.type = chroot +fs.mount.shm.path = /dev/shm +fs.mount.shm.uri = file:/tmp + fs.mount.lib.type = chroot fs.mount.lib.path = /lib fs.mount.lib.uri = file:$(LIBCDIR) +fs.mount.lib64.type = chroot +fs.mount.lib64.path = /lib/x86_64-linux-gnu +fs.mount.lib64.uri = file:/lib/x86_64-linux-gnu + fs.mount.usr.type = chroot fs.mount.usr.path = /usr fs.mount.usr.uri = file:/usr +fs.mount.tmp.type = chroot +fs.mount.tmp.path = /tmp +fs.mount.tmp.uri = file:/tmp + sys.brk.size = 32M sys.stack.size = 4M @@ -18,3 +31,5 @@ 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.tmp = file:/tmp diff --git a/LibOS/shim/test/apps/ltp/syscalls.sh b/LibOS/shim/test/apps/ltp/syscalls.sh index 659bc655..9527177b 100755 --- a/LibOS/shim/test/apps/ltp/syscalls.sh +++ b/LibOS/shim/test/apps/ltp/syscalls.sh @@ -1,6 +1,6 @@ #!/bin/sh cd `dirname $0` export LTPROOT=$PWD"/opt/ltp" -awk -f edit_sys_tests.awk $LTPROOT/runtest/syscalls > syscalls.graphene +awk -v SGX=$SGX_RUN -f edit_sys_tests.awk $LTPROOT/runtest/syscalls > syscalls.graphene cd $LTPROOT/../.. python fetch.py diff --git a/LibOS/shim/test/regression/90_large-mmap.py b/LibOS/shim/test/regression/90_large-mmap.py index 7e62403b..15d00f50 100644 --- a/LibOS/shim/test/regression/90_large-mmap.py +++ b/LibOS/shim/test/regression/90_large-mmap.py @@ -6,7 +6,7 @@ from regression import Regression loader = sys.argv[1] # Running Bootstrap -regression = Regression(loader, "large-mmap", None, 30000) +regression = Regression(loader, "large-mmap", None, 60000) regression.add_check(name="Ftruncate", check=lambda res: "large-mmap: ftruncate OK" in res[0].out) diff --git a/LibOS/shim/test/regression/Makefile b/LibOS/shim/test/regression/Makefile index 0a0f0027..bbea0339 100644 --- a/LibOS/shim/test/regression/Makefile +++ b/LibOS/shim/test/regression/Makefile @@ -55,8 +55,6 @@ regression: $(target) @for f in $(wildcard 30_*.py); do env $(PYTHONENV) python $$f $(RUNTIME)/pal-$(PAL_HOST); done @echo "\n\nLarge File Support:" @for f in $(wildcard 90_*.py); do env $(PYTHONENV) python $$f $(RUNTIME)/pal-$(PAL_HOST); done - @echo "\n\nLTP tests for system calls:" - ../apps/ltp/syscalls.sh clean-tmp: rm -rf *.tmp ../apps/ltp/*.csv *.cached *.manifest.sgx *~ *.sig *.token diff --git a/Pal/ipc/linux/graphene-ipc.c b/Pal/ipc/linux/graphene-ipc.c index f73159ac..6be23f1e 100644 --- a/Pal/ipc/linux/graphene-ipc.c +++ b/Pal/ipc/linux/graphene-ipc.c @@ -189,7 +189,11 @@ static inline void release_gipc_queue(struct gipc_queue *gq, bool locked) while (gq->next != gq->last) { idx = gq->next; if (gq->pages[idx].page) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) + put_page(gq->pages[idx].page); +#else page_cache_release(gq->pages[idx].page); +#endif gq->pages[idx].page = NULL; } if (gq->pages[idx].file) { @@ -353,10 +357,15 @@ static int get_pages (struct task_struct *task, unsigned long start, DEBUG("GIPC_SEND get_user_pages %ld pages at %lx\n", addr, nr); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0) + rv = get_user_pages(addr, nr, + FOLL_GET|FOLL_FORCE|FOLL_SPLIT, + pages + last, vmas + last); +#else rv = __get_user_pages(task, mm, addr, nr, FOLL_GET|FOLL_FORCE|FOLL_SPLIT, pages + last, vmas + last, NULL); - +#endif if (rv <= 0) { printk(KERN_ERR "Graphene error: " "get_user_pages at 0x%016lx-0x%016lx\n", @@ -702,7 +711,11 @@ static int do_gipc_recv(struct task_struct *task, struct gipc_queue *gq, finish: /* Drop the kernel's reference to this page */ if (page) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0) + put_page(page); +#else page_cache_release(page); +#endif if (file) fput_atomic(file); if (rv) diff --git a/Pal/regression/Process3.c b/Pal/regression/Process3.c index 6658b64d..46140e91 100644 --- a/Pal/regression/Process3.c +++ b/Pal/regression/Process3.c @@ -8,10 +8,14 @@ int main (int argc, char ** argv, char ** envp) { PAL_STR args[1] = { 0 }; - PAL_HANDLE child = DkProcessCreate(NULL, 0, args); - if (child) - pal_printf("Create Process without Executable OK\n"); + // Hack to differentiate parent from child + if (argc == 1) { + PAL_HANDLE child = DkProcessCreate(NULL, 0, args); + + if (child) + pal_printf("Create Process without Executable OK\n"); + } return 0; } diff --git a/Pal/src/db_events.c b/Pal/src/db_events.c index c0ab4ac8..030a4590 100644 --- a/Pal/src/db_events.c +++ b/Pal/src/db_events.c @@ -128,10 +128,10 @@ static int event_close (PAL_HANDLE handle) return _DkEventClear(handle); } -static int event_wait (PAL_HANDLE handle, int timeout) +static int event_wait (PAL_HANDLE handle, uint64_t timeout) { - return timeout >=0 ? _DkEventWaitTimeout(handle, timeout) : - _DkEventWait(handle); + return timeout == NO_TIMEOUT ? _DkEventWait(handle) : + _DkEventWaitTimeout(handle, timeout); } struct handle_ops event_ops = { diff --git a/Pal/src/db_main.c b/Pal/src/db_main.c index 2c066c1e..99ecb7b6 100644 --- a/Pal/src/db_main.c +++ b/Pal/src/db_main.c @@ -346,6 +346,40 @@ has_manifest: } } + /* If we still don't have an exec in the manifest, but we have a manifest + * try implicitly from the manifest name */ + if ((!exec_handle) && manifest_uri) { + size_t manifest_strlen = strlen(manifest_uri); + size_t exec_strlen = manifest_strlen - 9; + int success = 0; + // Try .manifest + if (strcmp_static(&manifest_uri[exec_strlen], ".manifest")) { + success = 1; + } else { + exec_strlen -= 4; + if (strcmp_static(&manifest_uri[exec_strlen], ".manifest.sgx")) { + success = 1; + } + } + + if (success) { + exec_uri = malloc(exec_strlen + 1); + if (!exec_uri) + init_fail(-PAL_ERROR_NOMEM, "Cannot allocate URI buf"); + memcpy (exec_uri, manifest_uri, exec_strlen); + exec_uri[exec_strlen] = '\0'; + ret = _DkStreamOpen(&exec_handle, exec_uri, PAL_ACCESS_RDONLY, + 0, 0, 0); + // DEP 3/20/17: There are cases where we want to let + // the PAL start up without a main executable. Don't + // die here, just free the exec_uri buffer. + if (ret < 0) { + free(exec_uri); + exec_uri = NULL; + } + } + } + /* must be a ELF */ if (exec_handle && check_elf_object(exec_handle) < 0) init_fail(PAL_ERROR_INVAL, "executable is not a ELF binary"); diff --git a/Pal/src/db_process.c b/Pal/src/db_process.c index bd569e17..9293f3f3 100644 --- a/Pal/src/db_process.c +++ b/Pal/src/db_process.c @@ -40,6 +40,13 @@ DkProcessCreate (PAL_STR uri, PAL_FLG flags, PAL_STR * args) { ENTER_PAL_CALL(DkProcessCreate); + /* DEP 3/22/17: There seems to be a default semantics that + * a NULL URI should replicate the parent. I think we may want + * this to become an error in the future, but keep the behavior + * for now, and make it consistent across hosts. */ + if (!uri) + uri = pal_control.executable; + log_stream(uri); PAL_HANDLE handle = NULL; diff --git a/Pal/src/db_semaphore.c b/Pal/src/db_semaphore.c index ca9c0970..53911a0a 100644 --- a/Pal/src/db_semaphore.c +++ b/Pal/src/db_semaphore.c @@ -75,7 +75,7 @@ void DkSemaphoreRelease (PAL_HANDLE handle, PAL_NUM count) LEAVE_PAL_CALL(); } -static int sem_wait (PAL_HANDLE handle, int timeout) +static int sem_wait (PAL_HANDLE handle, uint64_t timeout) { return _DkSemaphoreAcquireTimeout(handle, 1, timeout); } diff --git a/Pal/src/db_streams.c b/Pal/src/db_streams.c index 71e1bcdd..df928cc2 100644 --- a/Pal/src/db_streams.c +++ b/Pal/src/db_streams.c @@ -618,7 +618,7 @@ void DkStreamUnmap (PAL_PTR addr, PAL_NUM size) /* _DkStreamSetLength for internal use. This function truncate the stream to certain length. This call might not be support for certain streams */ -uint64_t _DkStreamSetLength (PAL_HANDLE handle, uint64_t length) +int64_t _DkStreamSetLength (PAL_HANDLE handle, uint64_t length) { if (UNKNOWN_HANDLE(handle)) return -PAL_ERROR_BADHANDLE; @@ -643,7 +643,7 @@ DkStreamSetLength (PAL_HANDLE handle, PAL_NUM length) LEAVE_PAL_CALL_RETURN(0); } - uint64_t ret = _DkStreamSetLength(handle, length); + int64_t ret = _DkStreamSetLength(handle, length); if (ret < 0) { _DkRaiseFailure(-ret); diff --git a/Pal/src/host/Linux-SGX/crypto/aes.c b/Pal/src/host/Linux-SGX/crypto/aes.c index 2c049459..2d91c7e6 100644 --- a/Pal/src/host/Linux-SGX/crypto/aes.c +++ b/Pal/src/host/Linux-SGX/crypto/aes.c @@ -29,6 +29,7 @@ #define XMEMSET memset #define XMEMCPY memcpy +#define XMEMCMP memcmp #ifndef rotlFixed static inline word32 rotlFixed(word32 x, word32 y) @@ -1319,7 +1320,7 @@ int AESCBCDecrypt(AES *aes, byte *out, const byte *in, word32 sz) } /* Increment AES counter */ -static inline void IncrementAESCounter(byte* inOutCTR) +static inline void IncrementAESCounter(byte *inOutCTR) { int i; @@ -1368,4 +1369,336 @@ void AESCTREncrypt(AES *aes, byte *out, const byte *in, word32 sz) } } +enum { + CTR_SZ = 4 +}; +static inline void InitGCMCounter(byte *inOutCtr) +{ + inOutCtr[AES_BLOCK_SIZE - 4] = 0; + inOutCtr[AES_BLOCK_SIZE - 3] = 0; + inOutCtr[AES_BLOCK_SIZE - 2] = 0; + inOutCtr[AES_BLOCK_SIZE - 1] = 1; +} + +static inline void IncrementGCMCounter(byte *inOutCtr) +{ + int i; + + /* in network byte order so start at end and work back */ + for (i = AES_BLOCK_SIZE - 1; i >= AES_BLOCK_SIZE - CTR_SZ; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} + +static inline void FlattenSzInBits(byte *buf, word32 sz) +{ + /* Multiply the sz by 8 */ + word32 szHi = (sz >> (8*sizeof(sz) - 3)); + sz <<= 3; + + /* copy over the words of the sz into the destination buffer */ + buf[0] = (szHi >> 24) & 0xff; + buf[1] = (szHi >> 16) & 0xff; + buf[2] = (szHi >> 8) & 0xff; + buf[3] = szHi & 0xff; + buf[4] = (sz >> 24) & 0xff; + buf[5] = (sz >> 16) & 0xff; + buf[6] = (sz >> 8) & 0xff; + buf[7] = sz & 0xff; +} + +static inline void RIGHTSHIFTX(byte *x) +{ + int i; + int carryOut = 0; + int carryIn = 0; + int borrow = x[15] & 0x01; + + for (i = 0; i < AES_BLOCK_SIZE; i++) { + carryOut = x[i] & 0x01; + x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0); + carryIn = carryOut; + } + if (borrow) x[0] ^= 0xE1; +} + +static void GenerateM0(AES *aes) +{ + int i, j; + byte (*m)[AES_BLOCK_SIZE] = aes->M0; + + XMEMCPY(m[128], aes->H, AES_BLOCK_SIZE); + + for (i = 64; i > 0; i /= 2) { + XMEMCPY(m[i], m[i*2], AES_BLOCK_SIZE); + RIGHTSHIFTX(m[i]); + } + + for (i = 2; i < 256; i *= 2) { + for (j = 1; j < i; j++) { + XMEMCPY(m[i+j], m[i], AES_BLOCK_SIZE); + xorbuf(m[i+j], m[j], AES_BLOCK_SIZE); + } + } + + XMEMSET(m[0], 0, AES_BLOCK_SIZE); +} + +int AESGCMSetKey(AES* aes, const byte* key, word32 len) +{ + int ret; + byte iv[AES_BLOCK_SIZE]; + + if (!((len == 16) || (len == 24) || (len == 32))) + return BAD_FUNC_ARG; + + XMEMSET(iv, 0, AES_BLOCK_SIZE); + ret = AESSetKey(aes, key, len, iv, AES_ENCRYPTION); + + if (ret == 0) { + AESEncrypt(aes, iv, aes->H); + GenerateM0(aes); + } + + return ret; +} + +static const byte R[256][2] = { + {0x00, 0x00}, {0x01, 0xc2}, {0x03, 0x84}, {0x02, 0x46}, + {0x07, 0x08}, {0x06, 0xca}, {0x04, 0x8c}, {0x05, 0x4e}, + {0x0e, 0x10}, {0x0f, 0xd2}, {0x0d, 0x94}, {0x0c, 0x56}, + {0x09, 0x18}, {0x08, 0xda}, {0x0a, 0x9c}, {0x0b, 0x5e}, + {0x1c, 0x20}, {0x1d, 0xe2}, {0x1f, 0xa4}, {0x1e, 0x66}, + {0x1b, 0x28}, {0x1a, 0xea}, {0x18, 0xac}, {0x19, 0x6e}, + {0x12, 0x30}, {0x13, 0xf2}, {0x11, 0xb4}, {0x10, 0x76}, + {0x15, 0x38}, {0x14, 0xfa}, {0x16, 0xbc}, {0x17, 0x7e}, + {0x38, 0x40}, {0x39, 0x82}, {0x3b, 0xc4}, {0x3a, 0x06}, + {0x3f, 0x48}, {0x3e, 0x8a}, {0x3c, 0xcc}, {0x3d, 0x0e}, + {0x36, 0x50}, {0x37, 0x92}, {0x35, 0xd4}, {0x34, 0x16}, + {0x31, 0x58}, {0x30, 0x9a}, {0x32, 0xdc}, {0x33, 0x1e}, + {0x24, 0x60}, {0x25, 0xa2}, {0x27, 0xe4}, {0x26, 0x26}, + {0x23, 0x68}, {0x22, 0xaa}, {0x20, 0xec}, {0x21, 0x2e}, + {0x2a, 0x70}, {0x2b, 0xb2}, {0x29, 0xf4}, {0x28, 0x36}, + {0x2d, 0x78}, {0x2c, 0xba}, {0x2e, 0xfc}, {0x2f, 0x3e}, + {0x70, 0x80}, {0x71, 0x42}, {0x73, 0x04}, {0x72, 0xc6}, + {0x77, 0x88}, {0x76, 0x4a}, {0x74, 0x0c}, {0x75, 0xce}, + {0x7e, 0x90}, {0x7f, 0x52}, {0x7d, 0x14}, {0x7c, 0xd6}, + {0x79, 0x98}, {0x78, 0x5a}, {0x7a, 0x1c}, {0x7b, 0xde}, + {0x6c, 0xa0}, {0x6d, 0x62}, {0x6f, 0x24}, {0x6e, 0xe6}, + {0x6b, 0xa8}, {0x6a, 0x6a}, {0x68, 0x2c}, {0x69, 0xee}, + {0x62, 0xb0}, {0x63, 0x72}, {0x61, 0x34}, {0x60, 0xf6}, + {0x65, 0xb8}, {0x64, 0x7a}, {0x66, 0x3c}, {0x67, 0xfe}, + {0x48, 0xc0}, {0x49, 0x02}, {0x4b, 0x44}, {0x4a, 0x86}, + {0x4f, 0xc8}, {0x4e, 0x0a}, {0x4c, 0x4c}, {0x4d, 0x8e}, + {0x46, 0xd0}, {0x47, 0x12}, {0x45, 0x54}, {0x44, 0x96}, + {0x41, 0xd8}, {0x40, 0x1a}, {0x42, 0x5c}, {0x43, 0x9e}, + {0x54, 0xe0}, {0x55, 0x22}, {0x57, 0x64}, {0x56, 0xa6}, + {0x53, 0xe8}, {0x52, 0x2a}, {0x50, 0x6c}, {0x51, 0xae}, + {0x5a, 0xf0}, {0x5b, 0x32}, {0x59, 0x74}, {0x58, 0xb6}, + {0x5d, 0xf8}, {0x5c, 0x3a}, {0x5e, 0x7c}, {0x5f, 0xbe}, + {0xe1, 0x00}, {0xe0, 0xc2}, {0xe2, 0x84}, {0xe3, 0x46}, + {0xe6, 0x08}, {0xe7, 0xca}, {0xe5, 0x8c}, {0xe4, 0x4e}, + {0xef, 0x10}, {0xee, 0xd2}, {0xec, 0x94}, {0xed, 0x56}, + {0xe8, 0x18}, {0xe9, 0xda}, {0xeb, 0x9c}, {0xea, 0x5e}, + {0xfd, 0x20}, {0xfc, 0xe2}, {0xfe, 0xa4}, {0xff, 0x66}, + {0xfa, 0x28}, {0xfb, 0xea}, {0xf9, 0xac}, {0xf8, 0x6e}, + {0xf3, 0x30}, {0xf2, 0xf2}, {0xf0, 0xb4}, {0xf1, 0x76}, + {0xf4, 0x38}, {0xf5, 0xfa}, {0xf7, 0xbc}, {0xf6, 0x7e}, + {0xd9, 0x40}, {0xd8, 0x82}, {0xda, 0xc4}, {0xdb, 0x06}, + {0xde, 0x48}, {0xdf, 0x8a}, {0xdd, 0xcc}, {0xdc, 0x0e}, + {0xd7, 0x50}, {0xd6, 0x92}, {0xd4, 0xd4}, {0xd5, 0x16}, + {0xd0, 0x58}, {0xd1, 0x9a}, {0xd3, 0xdc}, {0xd2, 0x1e}, + {0xc5, 0x60}, {0xc4, 0xa2}, {0xc6, 0xe4}, {0xc7, 0x26}, + {0xc2, 0x68}, {0xc3, 0xaa}, {0xc1, 0xec}, {0xc0, 0x2e}, + {0xcb, 0x70}, {0xca, 0xb2}, {0xc8, 0xf4}, {0xc9, 0x36}, + {0xcc, 0x78}, {0xcd, 0xba}, {0xcf, 0xfc}, {0xce, 0x3e}, + {0x91, 0x80}, {0x90, 0x42}, {0x92, 0x04}, {0x93, 0xc6}, + {0x96, 0x88}, {0x97, 0x4a}, {0x95, 0x0c}, {0x94, 0xce}, + {0x9f, 0x90}, {0x9e, 0x52}, {0x9c, 0x14}, {0x9d, 0xd6}, + {0x98, 0x98}, {0x99, 0x5a}, {0x9b, 0x1c}, {0x9a, 0xde}, + {0x8d, 0xa0}, {0x8c, 0x62}, {0x8e, 0x24}, {0x8f, 0xe6}, + {0x8a, 0xa8}, {0x8b, 0x6a}, {0x89, 0x2c}, {0x88, 0xee}, + {0x83, 0xb0}, {0x82, 0x72}, {0x80, 0x34}, {0x81, 0xf6}, + {0x84, 0xb8}, {0x85, 0x7a}, {0x87, 0x3c}, {0x86, 0xfe}, + {0xa9, 0xc0}, {0xa8, 0x02}, {0xaa, 0x44}, {0xab, 0x86}, + {0xae, 0xc8}, {0xaf, 0x0a}, {0xad, 0x4c}, {0xac, 0x8e}, + {0xa7, 0xd0}, {0xa6, 0x12}, {0xa4, 0x54}, {0xa5, 0x96}, + {0xa0, 0xd8}, {0xa1, 0x1a}, {0xa3, 0x5c}, {0xa2, 0x9e}, + {0xb5, 0xe0}, {0xb4, 0x22}, {0xb6, 0x64}, {0xb7, 0xa6}, + {0xb2, 0xe8}, {0xb3, 0x2a}, {0xb1, 0x6c}, {0xb0, 0xae}, + {0xbb, 0xf0}, {0xba, 0x32}, {0xb8, 0x74}, {0xb9, 0xb6}, + {0xbc, 0xf8}, {0xbd, 0x3a}, {0xbf, 0x7c}, {0xbe, 0xbe} }; + +static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE]) +{ + int i, j; + byte Z[AES_BLOCK_SIZE]; + byte a; + + XMEMSET(Z, 0, sizeof(Z)); + + for (i = 15; i > 0; i--) { + xorbuf(Z, m[x[i]], AES_BLOCK_SIZE); + a = Z[15]; + + for (j = 15; j > 0; j--) { + Z[j] = Z[j-1]; + } + + Z[0] = R[a][0]; + Z[1] ^= R[a][1]; + } + xorbuf(Z, m[x[0]], AES_BLOCK_SIZE); + + XMEMCPY(x, Z, AES_BLOCK_SIZE); +} + +static void GHASH(AES *aes, const byte *a, word32 aSz, + const byte *c, word32 cSz, byte *s, word32 sSz) +{ + byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; + word32 blocks, partial; + + XMEMSET(x, 0, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, a, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, c, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + } + } + + /* Hash in the lengths of A and C in bits */ + FlattenSzInBits(&scratch[0], aSz); + FlattenSzInBits(&scratch[8], cSz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + + /* Copy the result into s. */ + XMEMCPY(s, x, sSz); +} + +int AESGCMEncrypt(AES *aes, byte *out, const byte *in, word32 sz, + const byte *iv, word32 ivSz, + byte *authTag, word32 authTagSz, + const byte *authIn, word32 authInSz) +{ + word32 blocks = sz / AES_BLOCK_SIZE; + word32 partial = sz % AES_BLOCK_SIZE; + const byte *p = in; + byte *c = out; + byte counter[AES_BLOCK_SIZE]; + byte *ctr; + byte scratch[AES_BLOCK_SIZE]; + + ctr = counter; + + XMEMSET(ctr, 0, AES_BLOCK_SIZE); + XMEMCPY(ctr, iv, ivSz); + InitGCMCounter(ctr); + + while (blocks--) { + IncrementGCMCounter(ctr); + AESEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, AES_BLOCK_SIZE); + XMEMCPY(c, scratch, AES_BLOCK_SIZE); + p += AES_BLOCK_SIZE; + c += AES_BLOCK_SIZE; + } + + if (partial != 0) { + IncrementGCMCounter(ctr); + AESEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, partial); + XMEMCPY(c, scratch, partial); + + } + + GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); + InitGCMCounter(ctr); + AESEncrypt(aes, ctr, scratch); + xorbuf(authTag, scratch, authTagSz); + + return 0; +} + +int AESGCMDecrypt(AES *aes, byte *out, const byte *in, word32 sz, + const byte *iv, word32 ivSz, + const byte *authTag, word32 authTagSz, + const byte *authIn, word32 authInSz) +{ + word32 blocks = sz / AES_BLOCK_SIZE; + word32 partial = sz % AES_BLOCK_SIZE; + const byte *c = in; + byte *p = out; + byte counter[AES_BLOCK_SIZE]; + byte *ctr ; + byte scratch[AES_BLOCK_SIZE]; + + ctr = counter; + + XMEMSET(ctr, 0, AES_BLOCK_SIZE); + XMEMCPY(ctr, iv, ivSz); + InitGCMCounter(ctr); + + /* Calculate the authTag again using the received auth data and the + * cipher text. */ + { + byte Tprime[AES_BLOCK_SIZE]; + byte EKY0[AES_BLOCK_SIZE]; + + GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); + AESEncrypt(aes, ctr, EKY0); + xorbuf(Tprime, EKY0, sizeof(Tprime)); + + if (XMEMCMP(authTag, Tprime, authTagSz) != 0) { + return AES_GCM_AUTH_E; + } + } + + while (blocks--) { + IncrementGCMCounter(ctr); + AESEncrypt(aes, ctr, scratch); + xorbuf(scratch, c, AES_BLOCK_SIZE); + XMEMCPY(p, scratch, AES_BLOCK_SIZE); + p += AES_BLOCK_SIZE; + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + IncrementGCMCounter(ctr); + AESEncrypt(aes, ctr, scratch); + xorbuf(scratch, c, partial); + XMEMCPY(p, scratch, partial); + } + return 0; +} diff --git a/Pal/src/host/Linux-SGX/crypto/aes.h b/Pal/src/host/Linux-SGX/crypto/aes.h index 6e2fbcf6..fec4150c 100644 --- a/Pal/src/host/Linux-SGX/crypto/aes.h +++ b/Pal/src/host/Linux-SGX/crypto/aes.h @@ -61,6 +61,10 @@ typedef struct AES { ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ word32 left; + + ALIGN16 byte H[AES_BLOCK_SIZE]; + /* key-based fast multiplication table. */ + ALIGN16 byte M0[256][AES_BLOCK_SIZE]; } AES; int AESSetKey(AES *aes, const byte *key, word32 len, const byte *iv, @@ -73,5 +77,14 @@ int AESCBCDecrypt(AES *aes, byte *out, const byte *in, word32 sz); int AESCBCDecryptWithKey(byte *out, const byte *in, word32 inSz, const byte *key, word32 keySz, const byte *iv); void AESCTREncrypt(AES *aes, byte *out, const byte *in, word32 sz); +int AESGCMSetKey(AES *aes, const byte *key, word32 len); +int AESGCMEncrypt(AES *aes, byte *out, const byte *in, word32 sz, + const byte *iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte *authIn, word32 authInSz); +int AESGCMDecrypt(AES *aes, byte *out, const byte *in, word32 sz, + const byte *iv, word32 ivSz, + const byte *authTag, word32 authTagSz, + const byte *authIn, word32 authInSz); #endif /* CTAO_CRYPT_AES_H */ diff --git a/Pal/src/host/Linux-SGX/db_events.c b/Pal/src/host/Linux-SGX/db_events.c index 4c70d4e3..2754f6fa 100644 --- a/Pal/src/host/Linux-SGX/db_events.c +++ b/Pal/src/host/Linux-SGX/db_events.c @@ -81,7 +81,7 @@ int _DkEventSet (PAL_HANDLE event, int wakeup) return ret; } -int _DkEventWaitTimeout (PAL_HANDLE event, int timeout) +int _DkEventWaitTimeout (PAL_HANDLE event, uint64_t timeout) { int ret = 0; diff --git a/Pal/src/host/Linux-SGX/db_files.c b/Pal/src/host/Linux-SGX/db_files.c index fa61e66f..ab226c1f 100644 --- a/Pal/src/host/Linux-SGX/db_files.c +++ b/Pal/src/host/Linux-SGX/db_files.c @@ -243,13 +243,13 @@ static int file_map (PAL_HANDLE handle, void ** addr, int prot, } /* 'setlength' operation for file stream. */ -static uint64_t file_setlength (PAL_HANDLE handle, uint64_t length) +static int64_t file_setlength (PAL_HANDLE handle, uint64_t length) { int ret = ocall_ftruncate(handle->file.fd, length); if (ret < 0) return ret; handle->file.total = length; - return length; + return (int64_t) length; } /* 'flush' operation for file stream. */ @@ -330,7 +330,7 @@ static int file_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr) { int fd = HANDLE_HDR(handle)->fds[0]; - int ret = ocall_fchmod(fd, attr->share_flags); + int ret = ocall_fchmod(fd, attr->share_flags | 0600); if (ret < 0) return ret; diff --git a/Pal/src/host/Linux-SGX/db_object.c b/Pal/src/host/Linux-SGX/db_object.c index 56f74195..92dfad34 100644 --- a/Pal/src/host/Linux-SGX/db_object.c +++ b/Pal/src/host/Linux-SGX/db_object.c @@ -42,7 +42,7 @@ /* internally to wait for one object. Also used as a shortcut to wait on events and semaphores */ -static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout) +static int _DkObjectWaitOne (PAL_HANDLE handle, uint64_t timeout) { /* only for all these handle which has a file descriptor, or a eventfd. events and semaphores will skip this part */ @@ -74,7 +74,7 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout) if (!nfds) return -PAL_ERROR_TRYAGAIN; - unsigned long waittime = timeout; + uint64_t waittime = timeout; int ret = ocall_poll(fds, nfds, timeout >= 0 ? &waittime : NULL); if (ret < 0) return ret; @@ -104,7 +104,7 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout) /* _DkObjectsWaitAny for internal use. The function wait for any of the handle in the handle array. timeout can be set for the wait. */ -int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout, +int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, uint64_t timeout, PAL_HANDLE * polled) { if (count <= 0) @@ -180,7 +180,7 @@ int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout, if (!nfds) return -PAL_ERROR_TRYAGAIN; - unsigned long waittime = timeout; + uint64_t waittime = timeout; ret = ocall_poll(fds, nfds, timeout >= 0 ? &waittime : NULL); if (ret < 0) return ret; diff --git a/Pal/src/host/Linux-SGX/db_semaphore.c b/Pal/src/host/Linux-SGX/db_semaphore.c index 85b46e43..d8ea59aa 100644 --- a/Pal/src/host/Linux-SGX/db_semaphore.c +++ b/Pal/src/host/Linux-SGX/db_semaphore.c @@ -146,7 +146,7 @@ int _DkSemaphoreAcquire (PAL_HANDLE sem, int count) return ret; } -int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, int timeout) +int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, uint64_t timeout) { /* Pass it up to the no-timeout version if no timeout requested */ if (timeout == -1) diff --git a/Pal/src/host/Linux-SGX/enclave_framework.c b/Pal/src/host/Linux-SGX/enclave_framework.c index 23e33dbc..6d8a4b73 100644 --- a/Pal/src/host/Linux-SGX/enclave_framework.c +++ b/Pal/src/host/Linux-SGX/enclave_framework.c @@ -125,7 +125,8 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr, { struct trusted_file * tf = NULL, * tmp; char uri[URI_MAX]; - int ret, fd = HANDLE_HDR(file)->fds[0], uri_len; + char normpath[URI_MAX]; + int ret, fd = HANDLE_HDR(file)->fds[0], uri_len, len; if (!(HANDLE_HDR(file)->flags & RFD(0))) return -PAL_ERROR_DENIED; @@ -134,24 +135,38 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr, if (uri_len < 0) return uri_len; + /* Normalize the uri */ + if (!strpartcmp_static(uri, "file:")) { + SGX_DBG(DBG_E, "Invalid URI [%s]: Trusted files must start with 'file:'\n", uri);; + return -PAL_ERROR_INVAL; + } + normpath [0] = 'f'; + normpath [1] = 'i'; + normpath [2] = 'l'; + normpath [3] = 'e'; + normpath [4] = ':'; + len = get_norm_path(uri + 5, normpath + 5, 0, URI_MAX); + uri_len = len + 5; + _DkSpinLock(&trusted_file_lock); - list_for_each_entry(tmp, &trusted_file_list, list) + list_for_each_entry(tmp, &trusted_file_list, list) { if (tmp->stubs) { /* trusted files: must be exactly the same URI */ - if (tmp->uri_len == uri_len && !memcmp(tmp->uri, uri, uri_len + 1)) { + if (tmp->uri_len == uri_len && !memcmp(tmp->uri, normpath, uri_len + 1)) { tf = tmp; break; } } else { /* allowed files: must be a subfolder or file */ if (tmp->uri_len <= uri_len && - !memcmp(tmp->uri, uri, tmp->uri_len) && - (!uri[tmp->uri_len] || uri[tmp->uri_len] == '/')) { + !memcmp(tmp->uri, normpath, tmp->uri_len) && + (!normpath[tmp->uri_len] || normpath[tmp->uri_len] == '/')) { tf = tmp; break; } } + } _DkSpinUnlock(&trusted_file_lock); @@ -172,7 +187,7 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr, if (!tf->index) { *stubptr = NULL; PAL_STREAM_ATTR attr; - ret = _DkStreamAttributesQuery(uri, &attr); + ret = _DkStreamAttributesQuery(normpath, &attr); if (!ret) *sizeptr = attr.pending_size; else @@ -251,7 +266,7 @@ failed: sgx_stub_t * loaded_stub; uint64_t loaded_size; PAL_HANDLE handle = NULL; - if (!_DkStreamOpen(&handle, uri, PAL_ACCESS_RDONLY, 0, 0, 0)) + if (!_DkStreamOpen(&handle, normpath, PAL_ACCESS_RDONLY, 0, 0, 0)) load_trusted_file (handle, &loaded_stub, &loaded_size); } #endif @@ -384,7 +399,8 @@ static int init_trusted_file (const char * key, const char * uri) { char cskey[URI_MAX], * tmp; char checksum[URI_MAX]; - + char normpath[URI_MAX]; + tmp = strcpy_static(cskey, "sgx.trusted_checksum.", URI_MAX); memcpy(tmp, key, strlen(key) + 1); @@ -392,7 +408,19 @@ static int init_trusted_file (const char * key, const char * uri) if (len < 0) return 0; - return register_trusted_file(uri, checksum); + /* Normalize the uri */ + if (!strpartcmp_static(uri, "file:")) { + SGX_DBG(DBG_E, "Invalid URI [%s]: Trusted files must start with 'file:'\n", uri); + return -PAL_ERROR_INVAL; + } + normpath [0] = 'f'; + normpath [1] = 'i'; + normpath [2] = 'l'; + normpath [3] = 'e'; + normpath [4] = ':'; + len = get_norm_path(uri + 5, normpath + 5, 0, URI_MAX); + + return register_trusted_file(normpath, checksum); } int init_trusted_files (void) diff --git a/Pal/src/host/Linux-SGX/enclave_ocalls.c b/Pal/src/host/Linux-SGX/enclave_ocalls.c index e24c90bc..6d2a4708 100644 --- a/Pal/src/host/Linux-SGX/enclave_ocalls.c +++ b/Pal/src/host/Linux-SGX/enclave_ocalls.c @@ -425,7 +425,7 @@ int ocall_create_process (const char * uri, } int ocall_futex (int * futex, int op, int val, - const unsigned long * timeout) + const uint64_t * timeout) { int retval = 0; ms_ocall_futex_t * ms; @@ -439,7 +439,7 @@ int ocall_futex (int * futex, int op, int val, ms->ms_futex = futex; ms->ms_op = op; ms->ms_val = val; - ms->ms_timeout = timeout ? *timeout : (unsigned long) -1; + ms->ms_timeout = timeout ? *timeout : OCALL_NO_TIMEOUT; retval = SGX_OCALL(OCALL_FUTEX, ms); OCALL_EXIT(); @@ -718,7 +718,7 @@ int ocall_sleep (unsigned long * microsec) return retval; } -int ocall_poll (struct pollfd * fds, int nfds, unsigned long * timeout) +int ocall_poll (struct pollfd * fds, int nfds, uint64_t * timeout) { int retval = 0; ms_ocall_poll_t * ms; @@ -726,7 +726,7 @@ int ocall_poll (struct pollfd * fds, int nfds, unsigned long * timeout) ms->ms_fds = COPY_TO_USER(fds, sizeof(struct pollfd) * nfds); ms->ms_nfds = nfds; - ms->ms_timeout = timeout ? *timeout : (unsigned long) -1; + ms->ms_timeout = timeout ? *timeout : OCALL_NO_TIMEOUT; retval = SGX_OCALL(OCALL_POLL, ms); if (retval == -EINTR && timeout) diff --git a/Pal/src/host/Linux-SGX/enclave_ocalls.h b/Pal/src/host/Linux-SGX/enclave_ocalls.h index 7baa7f07..64df71e9 100644 --- a/Pal/src/host/Linux-SGX/enclave_ocalls.h +++ b/Pal/src/host/Linux-SGX/enclave_ocalls.h @@ -88,7 +88,7 @@ int ocall_create_process (const char * uri, int procfds[3], unsigned int * pid); -int ocall_futex (int * uaddr, int op, int val, const unsigned long * timeout); +int ocall_futex (int * uaddr, int op, int val, const uint64_t * timeout); int ocall_gettime (unsigned long * microsec); @@ -96,7 +96,7 @@ int ocall_sleep (unsigned long * microsec); int ocall_socketpair (int domain, int type, int protocol, int sockfds[2]); -int ocall_poll (struct pollfd * fds, int nfds, unsigned long * microsec); +int ocall_poll (struct pollfd * fds, int nfds, uint64_t * timeout); int ocall_rename (const char * oldpath, const char * newpath); diff --git a/Pal/src/host/Linux-SGX/ocall_types.h b/Pal/src/host/Linux-SGX/ocall_types.h index 40d85a0b..150b3f35 100644 --- a/Pal/src/host/Linux-SGX/ocall_types.h +++ b/Pal/src/host/Linux-SGX/ocall_types.h @@ -48,6 +48,8 @@ enum { OCALL_NR, }; +#define OCALL_NO_TIMEOUT ((uint64_t) -1) + typedef struct { const char * ms_str; int ms_length; @@ -154,7 +156,7 @@ typedef struct { typedef struct { int * ms_futex; int ms_op, ms_val; - unsigned long ms_timeout; + uint64_t ms_timeout; } ms_ocall_futex_t; typedef struct { @@ -241,7 +243,7 @@ typedef struct { typedef struct { struct pollfd * ms_fds; int ms_nfds; - unsigned long ms_timeout; + uint64_t ms_timeout; } ms_ocall_poll_t; typedef struct { diff --git a/Pal/src/host/Linux-SGX/sgx-driver/link-intel-driver.py b/Pal/src/host/Linux-SGX/sgx-driver/link-intel-driver.py index 4ad7b060..a151b1d5 100755 --- a/Pal/src/host/Linux-SGX/sgx-driver/link-intel-driver.py +++ b/Pal/src/host/Linux-SGX/sgx-driver/link-intel-driver.py @@ -2,6 +2,10 @@ import sys, os, re + +isgx_path = os.getenv("ISGX_DRIVER_PATH") +isgx_version = os.getenv("ISGX_DRIVER_VERSION") + try: # get the locations of directories print "\n" + \ @@ -12,17 +16,20 @@ try: "\n" while True: - isgx_path = raw_input('Enter the Intel SGX driver derctory: ') + if not isgx_path: + isgx_path = raw_input('Enter the Intel SGX driver derctory: ') if os.path.exists(isgx_path + '/sgx.h'): break if os.path.exists(isgx_path + '/isgx.h'): break print '{0} is not a directory for the Intel SGX driver'.format(isgx_path) + isgx_path = None # get the driver version while True: - isgx_version = raw_input('Enter the driver version (default: 1.8): ') + if not isgx_version: + isgx_version = raw_input('Enter the driver version (default: 1.8): ') if not isgx_version: isgx_version_major = 1 isgx_version_minor = 8 @@ -33,6 +40,7 @@ try: isgx_version_minor = m.group(2) break print '{0} is not a valid version (x.xx)'.format(isgx_version) + isgx_version = None # create a symbolic link called 'linux-sgx-driver' diff --git a/Pal/src/host/Linux-SGX/sgx_enclave.c b/Pal/src/host/Linux-SGX/sgx_enclave.c index 1e6c6c58..859d8629 100644 --- a/Pal/src/host/Linux-SGX/sgx_enclave.c +++ b/Pal/src/host/Linux-SGX/sgx_enclave.c @@ -240,7 +240,7 @@ static int sgx_ocall_futex(void * pms) int ret; ODEBUG(OCALL_FUTEX, ms); struct timespec * ts = NULL; - if (ms->ms_timeout != (unsigned long) -1) { + if (ms->ms_timeout != OCALL_NO_TIMEOUT) { ts = __alloca(sizeof(struct timespec)); ts->tv_sec = ms->ms_timeout / 1000000; ts->tv_nsec = (ms->ms_timeout - ts->tv_sec * 1000000) * 1000; @@ -610,7 +610,7 @@ static int sgx_ocall_poll(void * pms) int ret; ODEBUG(OCALL_POLL, ms); struct timespec * ts = NULL; - if (ms->ms_timeout != (unsigned long) -1) { + if (ms->ms_timeout != OCALL_NO_TIMEOUT) { ts = __alloca(sizeof(struct timespec)); ts->tv_sec = ms->ms_timeout / 1000000; ts->tv_nsec = (ms->ms_timeout - ts->tv_sec * 1000000) * 1000; diff --git a/Pal/src/host/Linux/db_events.c b/Pal/src/host/Linux/db_events.c index b8ca36c9..e61155d9 100644 --- a/Pal/src/host/Linux/db_events.c +++ b/Pal/src/host/Linux/db_events.c @@ -79,7 +79,7 @@ int _DkEventSet (PAL_HANDLE event, int wakeup) return IS_ERR(ret) ? PAL_ERROR_TRYAGAIN : ret; } -int _DkEventWaitTimeout (PAL_HANDLE event, int timeout) +int _DkEventWaitTimeout (PAL_HANDLE event, uint64_t timeout) { int ret = 0; diff --git a/Pal/src/host/Linux/db_files.c b/Pal/src/host/Linux/db_files.c index cbe00fbc..0b2304c4 100644 --- a/Pal/src/host/Linux/db_files.c +++ b/Pal/src/host/Linux/db_files.c @@ -168,7 +168,7 @@ static int file_map (PAL_HANDLE handle, void ** addr, int prot, } /* 'setlength' operation for file stream. */ -static uint64_t file_setlength (PAL_HANDLE handle, uint64_t length) +static int64_t file_setlength (PAL_HANDLE handle, uint64_t length) { int ret = INLINE_SYSCALL(ftruncate, 2, handle->file.fd, length); @@ -176,7 +176,7 @@ static uint64_t file_setlength (PAL_HANDLE handle, uint64_t length) return (ERRNO(ret) == EINVAL || ERRNO(ret) == EBADF) ? -PAL_ERROR_BADHANDLE : -PAL_ERROR_DENIED; - return length; + return (int64_t) length; } /* 'flush' operation for file stream. */ @@ -258,7 +258,7 @@ static int file_attrsetbyhdl (PAL_HANDLE handle, { int fd = HANDLE_HDR(handle)->fds[0], ret; - ret = INLINE_SYSCALL(fchmod, 2, fd, attr->share_flags); + ret = INLINE_SYSCALL(fchmod, 2, fd, attr->share_flags | 0600); if (IS_ERR(ret)) return unix_to_pal_error(ERRNO(ret)); diff --git a/Pal/src/host/Linux/db_mutex.c b/Pal/src/host/Linux/db_mutex.c index 113480f7..4ac1255c 100644 --- a/Pal/src/host/Linux/db_mutex.c +++ b/Pal/src/host/Linux/db_mutex.c @@ -56,7 +56,7 @@ #define MUTEX_SPINLOCK_TIMES 100 -int _DkMutexLockTimeout (struct mutex_handle * m, int timeout) +int _DkMutexLockTimeout (struct mutex_handle * m, uint64_t timeout) { int ret = 0; #ifdef DEBUG_MUTEX diff --git a/Pal/src/host/Linux/db_object.c b/Pal/src/host/Linux/db_object.c index 0a19c74e..c4498a75 100644 --- a/Pal/src/host/Linux/db_object.c +++ b/Pal/src/host/Linux/db_object.c @@ -46,7 +46,7 @@ * * Returns 0 on success, negative value on failure (e.g., -PAL_ERROR_TRYAGAIN) */ -static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout) +static int _DkObjectWaitOne (PAL_HANDLE handle, uint64_t timeout) { /* only for all these handle which has a file descriptor, or a eventfd. events and semaphores will skip this part */ @@ -126,7 +126,7 @@ static int _DkObjectWaitOne (PAL_HANDLE handle, int timeout) /* _DkObjectsWaitAny for internal use. The function wait for any of the handle in the handle array. timeout can be set for the wait. */ -int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout, +int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, uint64_t timeout, PAL_HANDLE * polled) { if (count <= 0) diff --git a/Pal/src/host/Linux/db_semaphore.c b/Pal/src/host/Linux/db_semaphore.c index b6b32edf..25a0005f 100644 --- a/Pal/src/host/Linux/db_semaphore.c +++ b/Pal/src/host/Linux/db_semaphore.c @@ -82,7 +82,7 @@ void _DkSemaphoreDestroy (PAL_HANDLE semaphoreHandle) free(semaphoreHandle); } -int _DkMutexLockTimeout (struct mutex_handle * mut, int timeout); +int _DkMutexLockTimeout (struct mutex_handle * mut, uint64_t timeout); int _DkSemaphoreAcquire (PAL_HANDLE sem, int count) { @@ -151,10 +151,10 @@ int _DkSemaphoreAcquire (PAL_HANDLE sem, int count) return ret; } -int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, int timeout) +int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, uint64_t timeout) { /* Pass it up to the no-timeout version if no timeout requested */ - if (timeout == -1) + if (timeout == NO_TIMEOUT) return _DkSemaphoreAcquire(sem, count); /* optimization: use it as a mutex */ diff --git a/Pal/src/host/Linux/pal_linux.h b/Pal/src/host/Linux/pal_linux.h index 6527343a..848078fd 100644 --- a/Pal/src/host/Linux/pal_linux.h +++ b/Pal/src/host/Linux/pal_linux.h @@ -156,7 +156,7 @@ bool stataccess (struct stat * stats, int acc); /* Locking and unlocking of Mutexes */ int _DkMutexLock (struct mutex_handle * mut); -int _DkMutexLockTimeout (struct mutex_handle * mut, int timeout); +int _DkMutexLockTimeout (struct mutex_handle * mut, uint64_t timeout); int _DkMutexUnlock (struct mutex_handle * mut); void init_child_process (PAL_HANDLE * parent, PAL_HANDLE * exec, diff --git a/Pal/src/pal.h b/Pal/src/pal.h index 3adf71af..fc1bd3b4 100644 --- a/Pal/src/pal.h +++ b/Pal/src/pal.h @@ -466,7 +466,9 @@ DkEventClear (PAL_HANDLE eventHandle); #define NO_TIMEOUT ((PAL_NUM) -1) -/* assuming timeout to be in microseconds */ +/* assuming timeout to be in microseconds + * NO_TIMEOUT means no timeout, as the name implies. + */ /* Returns: NULL if the call times out, the ready handle on success */ PAL_HANDLE DkObjectsWaitAny (PAL_NUM count, PAL_HANDLE * handleArray, PAL_NUM timeout); diff --git a/Pal/src/pal_internal.h b/Pal/src/pal_internal.h index 7e083933..4d6d7e0a 100644 --- a/Pal/src/pal_internal.h +++ b/Pal/src/pal_internal.h @@ -81,7 +81,7 @@ struct handle_ops { /* 'setlength' is used by DkStreamFlush. It truncate the stream to certain size. */ - uint64_t (*setlength) (PAL_HANDLE handle, uint64_t length); + int64_t (*setlength) (PAL_HANDLE handle, uint64_t length); /* 'flush' is used by DkStreamFlush. It syncs the stream to the device */ int (*flush) (PAL_HANDLE handle); @@ -104,11 +104,12 @@ struct handle_ops { int (*attrsetbyhdl) (PAL_HANDLE handle, PAL_STREAM_ATTR * attr); /* 'wait' is used for synchronous wait. + * Time is in microseconds, NO_TIMEOUT means no timeout. * Returns 0 on success, a negative value on failure. * Timeout: -PAL_ERROR_TRYAGAIN * Positive return values are undefined. */ - int (*wait) (PAL_HANDLE handle, int time); + int (*wait) (PAL_HANDLE handle, uint64_t time); /* 'rename' is used to change name of a stream, or reset its share option */ @@ -302,7 +303,7 @@ int _DkStreamAttributesQuerybyHandle (PAL_HANDLE hdl, PAL_STREAM_ATTR * attr); int _DkStreamMap (PAL_HANDLE handle, void ** addr, int prot, uint64_t offset, uint64_t size); int _DkStreamUnmap (void * addr, uint64_t size); -uint64_t _DkStreamSetLength (PAL_HANDLE handle, uint64_t length); +int64_t _DkStreamSetLength (PAL_HANDLE handle, uint64_t length); int _DkStreamFlush (PAL_HANDLE handle); int _DkStreamGetName (PAL_HANDLE handle, char * buf, int size); const char * _DkStreamRealpath (PAL_HANDLE hdl); @@ -327,7 +328,7 @@ int _DkProcessSandboxCreate (const char * manifest, int flags); int _DkSemaphoreCreate (PAL_HANDLE handle, int initialCount, int maxCount); void _DkSemaphoreDestroy (PAL_HANDLE semaphoreHandle); int _DkSemaphoreAcquire (PAL_HANDLE sem, int count); -int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, int timeout); +int _DkSemaphoreAcquireTimeout (PAL_HANDLE sem, int count, uint64_t timeout); void _DkSemaphoreRelease (PAL_HANDLE sem, int count); int _DkSemaphoreGetCurrentCount (PAL_HANDLE sem); @@ -336,7 +337,7 @@ int _DkEventCreate (PAL_HANDLE * event, bool initialState, bool isnotification); void _DkEventDestroy (PAL_HANDLE handle); int _DkEventSet (PAL_HANDLE event, int wakeup); -int _DkEventWaitTimeout (PAL_HANDLE event, int timeout); +int _DkEventWaitTimeout (PAL_HANDLE event, uint64_t timeout); int _DkEventWait (PAL_HANDLE event); int _DkEventClear (PAL_HANDLE event); @@ -348,7 +349,7 @@ int _DkVirtualMemoryProtect (void * addr, uint64_t size, int prot); /* DkObject calls */ int _DkObjectReference (PAL_HANDLE objectHandle); int _DkObjectClose (PAL_HANDLE objectHandle); -int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, int timeout, +int _DkObjectsWaitAny (int count, PAL_HANDLE * handleArray, uint64_t timeout, PAL_HANDLE * polled); /* DkException calls & structures */ diff --git a/Runtime/pal_loader b/Runtime/pal_loader index 4d359040..9be911c4 100755 --- a/Runtime/pal_loader +++ b/Runtime/pal_loader @@ -2,7 +2,15 @@ if [ "$1" == "SGX" ]; then if [ "$SGX" != "0" ]; then - export SGX=1 + export SGX=1 + # Sometimes, we end up with a stray SGX_RUN in the environment, + # which makes the Makefile.Host unhappy + unset SGX_RUN + # The interaction of SGX and SGX_RUN is getting pretty unwieldly. + # We should kill off SGX_RUN. Here, we can get in trouble + # if the make invocation below gets SGX_RUN via an MAKEFLAGS + # from a wrapper makefile (e.g., the regression tests) + unset MAKEFLAGS fi shift fi