Browse Source

Merge branch 'master' into sha256

Don Porter 6 years ago
parent
commit
ca981b3bcd
100 changed files with 2406 additions and 2752 deletions
  1. 18 1
      .travis.yml
  2. 18 0
      LICENSE.addendum.txt
  3. 5 7
      LibOS/glibc-2.19.patch
  4. 0 113
      LibOS/shim/include/bitop.h
  5. 4 1
      LibOS/shim/include/shim_fs.h
  6. 1 0
      LibOS/shim/include/shim_handle.h
  7. 2 1
      LibOS/shim/include/shim_internal.h
  8. 4 3
      LibOS/shim/include/shim_ipc.h
  9. 2 4
      LibOS/shim/include/shim_signal.h
  10. 4 3
      LibOS/shim/include/shim_table.h
  11. 6 1
      LibOS/shim/include/shim_thread.h
  12. 5 3
      LibOS/shim/include/shim_types.h
  13. 29 8
      LibOS/shim/src/bookkeep/shim_signal.c
  14. 1 0
      LibOS/shim/src/bookkeep/shim_vma.c
  15. 19 0
      LibOS/shim/src/elf/shim_rtld.c
  16. 109 22
      LibOS/shim/src/fs/chroot/fs.c
  17. 1 1
      LibOS/shim/src/fs/shim_fs.c
  18. 15 8
      LibOS/shim/src/ipc/shim_ipc_child.c
  19. 67 14
      LibOS/shim/src/shim_malloc.c
  20. 5 4
      LibOS/shim/src/shim_syscalls.c
  21. 34 5
      LibOS/shim/src/sys/shim_brk.c
  22. 5 2
      LibOS/shim/src/sys/shim_exec.c
  23. 8 5
      LibOS/shim/src/sys/shim_exit.c
  24. 5 15
      LibOS/shim/src/sys/shim_fs.c
  25. 5 0
      LibOS/shim/src/sys/shim_getrlimit.c
  26. 31 9
      LibOS/shim/src/sys/shim_open.c
  27. 30 9
      LibOS/shim/src/sys/shim_sigaction.c
  28. 3 3
      LibOS/shim/src/sys/shim_socket.c
  29. 6 2
      LibOS/shim/src/sys/shim_wait.c
  30. 6 0
      LibOS/shim/test/.gitignore
  31. 1 1
      LibOS/shim/test/apps/apache/Makefile
  32. 41 0
      LibOS/shim/test/apps/apache/benchmark-ab.sh
  33. 4 0
      LibOS/shim/test/apps/apache/httpd.manifest.template
  34. 27 0
      LibOS/shim/test/apps/gcc/Makefile
  35. 6 0
      LibOS/shim/test/apps/lmbench/Makefile
  36. 222 0
      LibOS/shim/test/apps/lmbench/lmbench-regression
  37. 0 6
      LibOS/shim/test/apps/lmbench/manifest.template
  38. 14 5
      LibOS/shim/test/apps/ltp/Makefile
  39. 9 1
      LibOS/shim/test/apps/ltp/Makefile.testcases
  40. 350 21
      LibOS/shim/test/apps/ltp/PASSED
  41. 2 1
      LibOS/shim/test/apps/ltp/TIMEOUTS
  42. 10 3
      LibOS/shim/test/apps/ltp/edit_sys_tests.awk
  43. 69 49
      LibOS/shim/test/apps/ltp/fetch.py
  44. 16 1
      LibOS/shim/test/apps/ltp/manifest.template
  45. 1 1
      LibOS/shim/test/apps/ltp/syscalls.sh
  46. 0 1
      LibOS/shim/test/pal_loader
  47. 0 2
      LibOS/shim/test/regression/Makefile
  48. 0 66
      Pal/include/bits/dlfcn.h
  49. 0 70
      Pal/include/bits/libc-tsd.h
  50. 0 141
      Pal/include/bp-asm.h
  51. 0 16
      Pal/include/sysdeps/generic/linkmap.h
  52. 0 106
      Pal/include/sysdeps/unix/i386/sysdep.S
  53. 0 90
      Pal/include/sysdeps/unix/x86_64/sysdep.S
  54. 14 1
      Pal/ipc/linux/graphene-ipc.c
  55. 1 1
      Pal/lib/Makefile
  56. 0 1495
      Pal/lib/asm-errlist.h
  57. 334 1
      Pal/lib/crypto/aes.c
  58. 13 0
      Pal/lib/crypto/aes.h
  59. 7 3
      Pal/regression/Process3.c
  60. 3 3
      Pal/src/db_events.c
  61. 34 1
      Pal/src/db_main.c
  62. 7 0
      Pal/src/db_process.c
  63. 0 1
      Pal/src/db_rtld.c
  64. 1 1
      Pal/src/db_semaphore.c
  65. 2 2
      Pal/src/db_streams.c
  66. 6 2
      Pal/src/host/Linux-SGX/Makefile
  67. 1 1
      Pal/src/host/Linux-SGX/db_events.c
  68. 3 3
      Pal/src/host/Linux-SGX/db_files.c
  69. 4 4
      Pal/src/host/Linux-SGX/db_object.c
  70. 0 1
      Pal/src/host/Linux-SGX/db_rtld.c
  71. 1 1
      Pal/src/host/Linux-SGX/db_semaphore.c
  72. 46 8
      Pal/src/host/Linux-SGX/enclave_framework.c
  73. 4 4
      Pal/src/host/Linux-SGX/enclave_ocalls.c
  74. 2 2
      Pal/src/host/Linux-SGX/enclave_ocalls.h
  75. 4 2
      Pal/src/host/Linux-SGX/ocall_types.h
  76. 1 0
      Pal/src/host/Linux-SGX/sgx-driver/.gitignore
  77. 10 3
      Pal/src/host/Linux-SGX/sgx-driver/Makefile
  78. 46 0
      Pal/src/host/Linux-SGX/sgx-driver/graphene-sgx.h
  79. 35 25
      Pal/src/host/Linux-SGX/sgx-driver/gsgx.h
  80. 37 0
      Pal/src/host/Linux-SGX/sgx-driver/gsgx_fsgsbase.c
  81. 177 0
      Pal/src/host/Linux-SGX/sgx-driver/gsgx_ioctl_1_6.c
  82. 173 0
      Pal/src/host/Linux-SGX/sgx-driver/gsgx_ioctl_1_7.c
  83. 21 208
      Pal/src/host/Linux-SGX/sgx-driver/gsgx_main.c
  84. 7 0
      Pal/src/host/Linux-SGX/sgx-driver/isgx_ksyms.h
  85. 53 12
      Pal/src/host/Linux-SGX/sgx-driver/link-intel-driver.py
  86. 0 2
      Pal/src/host/Linux-SGX/sgx_arch.h
  87. 2 2
      Pal/src/host/Linux-SGX/sgx_enclave.c
  88. 96 54
      Pal/src/host/Linux-SGX/sgx_framework.c
  89. 20 1
      Pal/src/host/Linux-SGX/signer/pal-sgx-get-token
  90. 1 1
      Pal/src/host/Linux/db_events.c
  91. 3 3
      Pal/src/host/Linux/db_files.c
  92. 1 1
      Pal/src/host/Linux/db_mutex.c
  93. 2 2
      Pal/src/host/Linux/db_object.c
  94. 0 1
      Pal/src/host/Linux/db_rtld.c
  95. 3 3
      Pal/src/host/Linux/db_semaphore.c
  96. 1 1
      Pal/src/host/Linux/pal_linux.h
  97. 3 1
      Pal/src/pal.h
  98. 7 6
      Pal/src/pal_internal.h
  99. 0 1
      Pal/src/pal_rtld.h
  100. 0 63
      Pal/test/test.c

+ 18 - 1
.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

+ 18 - 0
LICENSE.addendum.txt

@@ -1,4 +1,22 @@
 Graphene also includes the following third party sources (and licenses):
 mbedtls - Apache 2.0
 wolfssl - GPL v2
+
+RSA's MD5 algorithm (LibOS/shim/src/utils/md5.c) - RSA custom attribution license
+
+Linux kernel - GPL v2
+ - dcache implementation
+ - linked list implementation
+ - atomic_add, cmpxchg and friends implementation
+
+Internet Software Consortium (permissive license): Pal/lib/network/inet_pton.c
+
+MIT JOS (mix of MIT and BSD licenses:
+* Pal/lib/stdlib/printfmt.c
+
+A number of files taken from other C libraries:
+* glibc - LGPL
+* musl - MIT
+
 [incomplete: more to come]
+

+ 5 - 7
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.  */

+ 0 - 113
LibOS/shim/include/bitop.h

@@ -1,113 +0,0 @@
-/* Copyright (C) 2014 OSCAR lab, Stony Brook University
-   This file is part of Graphene Library OS.
-
-   Graphene Library OS is free software: you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   as published by the Free Software Foundation, either version 3 of the
-   License, or (at your option) any later version.
-
-   Graphene Library OS is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-/*
- * bitop.h
- */
-
-#ifndef _BITOP_H
-#define _BITOP_H
-
-#define ADDR (*(volatile long *) addr)
-
-#define LOCK_PREFIX ""
-
-/**
- * set_bit - Atomically set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * This function is atomic and may not be reordered.  See __set_bit()
- * if you do not require the atomic guarantees.
- * Note that @nr may be almost arbitrarily large; this function is not
- * restricted to acting on a single-word quantity.
- */
-static __inline__ void set_bit(int nr, volatile void * addr)
-{
-        __asm__ __volatile__( LOCK_PREFIX
-                "btsl %1,%0"
-                :"=m" (ADDR)
-                :"dIr" (nr) : "memory");
-}
-
-/**
- * __set_bit - Set a bit in memory
- * @nr: the bit to set
- * @addr: the address to start counting from
- *
- * Unlike set_bit(), this function is non-atomic and may be reordered.
- * If it's called on the same region of memory simultaneously, the effect
- * may be that only one operation succeeds.
- */
-static __inline__ void __set_bit(int nr, volatile void * addr)
-{
-        __asm__ volatile(
-                "btsl %1,%0"
-                :"=m" (ADDR)
-                :"dIr" (nr) : "memory");
-}
-
-/**
- * clear_bit - Clears a bit in memory
- * @nr: Bit to clear
- * @addr: Address to start counting from
- *
- * clear_bit() is atomic and may not be reordered.  However, it does
- * not contain a memory barrier, so if it is used for locking purposes,
- * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
- * in order to ensure changes are visible on other processors.
- */
-static __inline__ void clear_bit(int nr, volatile void * addr)
-{
-        __asm__ __volatile__( LOCK_PREFIX
-                "btrl %1,%0"
-                :"=m" (ADDR)
-                :"dIr" (nr));
-}
-
-static __inline__ void __clear_bit(int nr, volatile void * addr)
-{
-        __asm__ __volatile__(
-                "btrl %1,%0"
-                :"=m" (ADDR)
-                :"dIr" (nr));
-}
-
-static __inline__ int constant_test_bit(int nr, const volatile void * addr)
-{
-        return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
-}
-
-static __inline__ int variable_test_bit(int nr, volatile const void * addr)
-{
-        int oldbit;
-
-        __asm__ __volatile__(
-                "btl %2,%1\n\tsbbl %0,%0"
-                :"=r" (oldbit)
-                :"m" (ADDR),"dIr" (nr));
-        return oldbit;
-}
-
-#define test_bit(nr,addr) \
-(__builtin_constant_p(nr) ? \
- constant_test_bit((nr),(addr)) : \
- variable_test_bit((nr),(addr)))
-
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-#endif

+ 4 - 1
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);
 };
 

+ 1 - 0
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 {

+ 2 - 1
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);

+ 4 - 3
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);

+ 2 - 4
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);

+ 4 - 3
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);

+ 6 - 1
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 {

+ 5 - 3
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 */

+ 29 - 8
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,

+ 1 - 0
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;
     }

+ 19 - 0
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",

+ 109 - 22
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;
 }
 

+ 1 - 1
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;
     }

+ 15 - 8
LibOS/shim/src/ipc/shim_ipc_child.c

@@ -37,7 +37,7 @@
 #include <errno.h>
 
 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;
 }

+ 67 - 14
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 <shim_internal.h>
@@ -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,18 +148,27 @@ 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;
+        }
 
-    void * addr = heap->current;
-    heap->current += alloc_size;
+        addr = heap->current;
+        heap->current += alloc_size;
+    }
 
     unlock(shim_heap_lock);
 
@@ -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;
 }

+ 5 - 4
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,

+ 34 - 5
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:

+ 5 - 2
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;
 }

+ 8 - 5
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)

+ 5 - 15
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)

+ 5 - 0
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;
     }

+ 31 - 9
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);

+ 30 - 9
LibOS/shim/src/sys/shim_sigaction.c

@@ -39,11 +39,12 @@
 #include <linux/signal.h>
 
 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

+ 3 - 3
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;
 

+ 6 - 2
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);

+ 6 - 0
LibOS/shim/test/.gitignore

@@ -0,0 +1,6 @@
+*.manifest
+*.manifest.sgx
+*.sig
+*.token
+*.cached
+pal_loader

+ 1 - 1
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 ] || \

+ 41 - 0
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"

+ 4 - 0
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

+ 27 - 0
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
 

+ 6 - 0
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

+ 222 - 0
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

+ 0 - 6
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

+ 14 - 5
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)

+ 9 - 1
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" > $@

+ 350 - 21
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,2
+waitpid05,3
+waitpid05,4
+waitpid05,5
+waitpid05,7
+waitpid05,8
+waitpid05,10
 waitpid05,11
+waitpid05,13
 waitpid05,14
-waitpid05,18
+waitpid05,16
+waitpid05,17
+waitpid05,19
+waitpid05,20
+waitpid05,21
 waitpid05,22
+waitpid05,24
+waitpid05,25
 waitpid05,26
-waitpid05,3
+waitpid05,27
+waitpid05,28
+waitpid05,29
 waitpid05,30
-waitpid05,34
-waitpid05,37
-waitpid05,4
-waitpid05,40
-waitpid05,7
 write01,1
 write02,1
 write03,1

+ 2 - 1
LibOS/shim/test/apps/ltp/TIMEOUTS

@@ -1,4 +1,5 @@
 testcase,timeout
 clone05,30
 alarm01,5
-alarm06,16 
+alarm06,16
+waitpid05,160

+ 10 - 3
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
 		}

+ 69 - 49
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"

+ 16 - 1
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

+ 1 - 1
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

+ 0 - 1
LibOS/shim/test/pal_loader

@@ -1 +0,0 @@
-../../../Runtime/pal_loader

+ 0 - 2
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

+ 0 - 66
Pal/include/bits/dlfcn.h

@@ -1,66 +0,0 @@
-/* System dependent definitions for run-time dynamic loading.
-   Copyright (C) 1996-2001, 2004 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#ifndef _DLFCN_H
-#define _DLFCN_H
-
-/* The MODE argument to `dlopen' contains one of the following: */
-#define RTLD_LAZY	0x00001	/* Lazy function call binding.  */
-#define RTLD_NOW	0x00002	/* Immediate function call binding.  */
-#define	RTLD_BINDING_MASK   0x3	/* Mask of binding time value.  */
-#define RTLD_NOLOAD	0x00004	/* Do not load the object.  */
-#define RTLD_DEEPBIND	0x00008	/* Use deep binding.  */
-
-/* If the following bit is set in the MODE argument to `dlopen',
-   the symbols of the loaded object and its dependencies are made
-   visible as if the object were linked directly into the program.  */
-#define RTLD_GLOBAL	0x00100
-
-/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL.
-   The implementation does this by default and so we can define the
-   value to zero.  */
-#define RTLD_LOCAL	0
-
-/* Do not delete object when closed.  */
-#define RTLD_NODELETE	0x01000
-
-#ifdef __USE_GNU
-/* To support profiling of shared objects it is a good idea to call
-   the function found using `dlsym' using the following macro since
-   these calls do not use the PLT.  But this would mean the dynamic
-   loader has no chance to find out when the function is called.  The
-   macro applies the necessary magic so that profiling is possible.
-   Rewrite
-	foo = (*fctp) (arg1, arg2);
-   into
-        foo = DL_CALL_FCT (fctp, (arg1, arg2));
-*/
-# define DL_CALL_FCT(fctp, args) \
-  (_dl_mcount_wrapper_check ((void *) (fctp)), (*(fctp)) args)
-
-__BEGIN_DECLS
-
-/* This function calls the profiling functions.  */
-extern void _dl_mcount_wrapper_check (void *__selfpc) __THROW;
-
-__END_DECLS
-
-#endif
-
-#endif

+ 0 - 70
Pal/include/bits/libc-tsd.h

@@ -1,70 +0,0 @@
-/* libc-internal interface for thread-specific data.  Stub or TLS version.
-   Copyright (C) 1998,2001,2002,2008 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#ifndef _GENERIC_BITS_LIBC_TSD_H
-#define _GENERIC_BITS_LIBC_TSD_H 1
-
-/* This file defines the following macros for accessing a small fixed
-   set of thread-specific `void *' data used only internally by libc.
-
-   __libc_tsd_define(CLASS, TYPE, KEY)	-- Define or declare a datum with TYPE
-   					   for KEY.  CLASS can be `static' for
-					   keys used in only one source file,
-					   empty for global definitions, or
-					   `extern' for global declarations.
-   __libc_tsd_address(TYPE, KEY)	-- Return the `TYPE *' pointing to
-   					   the current thread's datum for KEY.
-   __libc_tsd_get(TYPE, KEY)		-- Return the `TYPE' datum for KEY.
-   __libc_tsd_set(TYPE, KEY, VALUE)	-- Set the datum for KEY to VALUE.
-
-   The set of available KEY's will usually be provided as an enum,
-   and contains (at least):
-		_LIBC_TSD_KEY_MALLOC
-		_LIBC_TSD_KEY_DL_ERROR
-		_LIBC_TSD_KEY_RPC_VARS
-   All uses must be the literal _LIBC_TSD_* name in the __libc_tsd_* macros.
-   Some implementations may not provide any enum at all and instead
-   using string pasting in the macros.  */
-
-//#include <tls.h>
-
-/* When full support for __thread variables is available, this interface is
-   just a trivial wrapper for it.  Without TLS, this is the generic/stub
-   implementation for wholly single-threaded systems.
-
-   We don't define an enum for the possible key values, because the KEYs
-   translate directly into variables by macro magic.  */
-
-#if USE___THREAD
-# define __libc_tsd_define(CLASS, TYPE, KEY)	\
-  CLASS __thread TYPE __libc_tsd_##KEY attribute_tls_model_ie;
-
-# define __libc_tsd_address(TYPE, KEY)		(&__libc_tsd_##KEY)
-# define __libc_tsd_get(TYPE, KEY)		(__libc_tsd_##KEY)
-# define __libc_tsd_set(TYPE, KEY, VALUE)	(__libc_tsd_##KEY = (VALUE))
-#else
-# define __libc_tsd_define(CLASS, TYPE, KEY)	\
-  CLASS TYPE __libc_tsd_##KEY##_data;
-
-# define __libc_tsd_address(TYPE, KEY)		(&__libc_tsd_##KEY##_data)
-# define __libc_tsd_get(TYPE, KEY)		(__libc_tsd_##KEY##_data)
-# define __libc_tsd_set(TYPE, KEY, VALUE)	(__libc_tsd_##KEY##_data = (VALUE))
-#endif
-
-#endif	/* bits/libc-tsd.h */

+ 0 - 141
Pal/include/bp-asm.h

@@ -1,141 +0,0 @@
-/* Bounded-pointer definitions for x86-64 assembler.
-   Copyright (C) 2001 Free Software Foundation, Inc.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#ifndef _bp_asm_h_
-# define _bp_asm_h_ 1
-
-# if __ASSEMBLER__
-
-#  if __BOUNDED_POINTERS__
-
-/* Bounded pointers occupy three words.  */
-#   define PTR_SIZE 24
-/* Bounded pointer return values are passed back through a hidden
-   argument that points to caller-allocate space.  The hidden arg
-   occupies one word on the stack.  */
-#   define RTN_SIZE 6
-/* Although the caller pushes the hidden arg, the callee is
-   responsible for popping it.  */
-#   define RET_PTR ret $RTN_SIZE
-/* Maintain frame pointer chain in leaf assembler functions for the benefit
-   of debugging stack traces when bounds violations occur.  */
-#   define ENTER pushq %rbp; movq %rsp, %rbp
-#   define LEAVE movq %rbp, %rsp; popq %rbp
-/* Stack space overhead of procedure-call linkage: return address and
-   frame pointer.  */
-#   define LINKAGE 16
-/* Stack offset of return address after calling ENTER.  */
-#   define PCOFF 8
-
-/* Int 5 is the "bound range" exception also raised by the "bound"
-   instruction.  */
-#   define BOUNDS_VIOLATED int $5
-
-#   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)	\
-	cmpq 8+BP_MEM, VAL_REG;			\
-	jae 0f; /* continue if value >= low */	\
-	BOUNDS_VIOLATED;			\
-    0:
-
-#   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)	\
-	cmpq 16+BP_MEM, VAL_REG;			\
-	Jcc 0f; /* continue if value < high */		\
-	BOUNDS_VIOLATED;				\
-    0:
-
-#   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)	\
-	cmpq 8+BP_MEM, VAL_REG;			\
-	jb 1f; /* die if value < low */		\
-	cmpq 16+BP_MEM, VAL_REG;		\
-	jb 0f; /* continue if value < high */	\
-    1:	BOUNDS_VIOLATED;			\
-    0:
-
-#   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)	\
-	CHECK_BOUNDS_LOW(VAL_REG, BP_MEM);			\
-	addl LENGTH, VAL_REG;					\
-	cmpq 16+BP_MEM, VAL_REG;					\
-	jbe 0f; /* continue if value <= high */			\
-	BOUNDS_VIOLATED;					\
-    0:	subq LENGTH, VAL_REG /* restore value */
-
-/* Take bounds from BP_MEM and affix them to the pointer
-   value in %rax, stuffing all into memory at RTN(%esp).
-   Use %rdx as a scratch register.  */
-
-#   define RETURN_BOUNDED_POINTER(BP_MEM)	\
-	movq RTN(%rsp), %rdx;			\
-	movq %rax, 0(%rdx);			\
-	movq 8+BP_MEM, %rax;			\
-	movq %rax, 4(%rdx);			\
-	movq 16+BP_MEM, %rax;			\
-	movq %rax, 8(%rdx)
-
-#   define RETURN_NULL_BOUNDED_POINTER		\
-	movl RTN(%rsp), %rdx;			\
-	movl %rax, 0(%rdx);			\
-	movl %rax, 4(%rdx);			\
-	movl %rax, 8(%rdx)
-
-/* The caller of PAL(__errno_location) is responsible for allocating space
-   for the three-word BP return-value and passing pushing its address
-   as an implicit first argument.  */
-#   define PUSH_ERRNO_LOCATION_RETURN		\
-	subl $16, %esp;				\
-	subl $8, %esp;				\
-	pushq %rsp
-
-/* PAL(__errno_location) is responsible for popping the implicit first
-   argument, but we must pop the space for the BP itself.  We also
-   dereference the return value in order to dig out the pointer value.  */
-#   define POP_ERRNO_LOCATION_RETURN		\
-	popq %rax;				\
-	addq $16, %rsp
-
-#  else /* !__BOUNDED_POINTERS__ */
-
-/* Unbounded pointers occupy one word.  */
-#   define PTR_SIZE 8
-/* Unbounded pointer return values are passed back in the register %rax.  */
-#   define RTN_SIZE 0
-/* Use simple return instruction for unbounded pointer values.  */
-#   define RET_PTR ret
-/* Don't maintain frame pointer chain for leaf assembler functions.  */
-#   define ENTER
-#   define LEAVE
-/* Stack space overhead of procedure-call linkage: return address only.  */
-#   define LINKAGE 8
-/* Stack offset of return address after calling ENTER.  */
-#   define PCOFF 0
-
-#   define CHECK_BOUNDS_LOW(VAL_REG, BP_MEM)
-#   define CHECK_BOUNDS_HIGH(VAL_REG, BP_MEM, Jcc)
-#   define CHECK_BOUNDS_BOTH(VAL_REG, BP_MEM)
-#   define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH)
-#   define RETURN_BOUNDED_POINTER(BP_MEM)
-
-#   define RETURN_NULL_BOUNDED_POINTER
-
-#   define PUSH_ERRNO_LOCATION_RETURN
-#   define POP_ERRNO_LOCATION_RETURN
-
-#  endif /* !__BOUNDED_POINTERS__ */
-
-# endif /* __ASSEMBLER__ */
-
-#endif /* _bp_asm_h_ */

+ 0 - 16
Pal/include/sysdeps/generic/linkmap.h

@@ -1,16 +0,0 @@
-#if __WORDSIZE == 64
-struct link_map_machine
-  {
-    Elf64_Addr plt; /* Address of .plt + 0x16 */
-    Elf64_Addr gotplt; /* Address of .got + 0x18 */
-    void *tlsdesc_table; /* Address of TLS descriptor hash table.  */
-  };
-
-#else
-struct link_map_machine
-  {
-    Elf32_Addr plt; /* Address of .plt + 0x16 */
-    Elf32_Addr gotplt; /* Address of .got + 0x0c */
-    void *tlsdesc_table; /* Address of TLS descriptor hash table.  */
-  };
-#endif

+ 0 - 106
Pal/include/sysdeps/unix/i386/sysdep.S

@@ -1,106 +0,0 @@
-/* Copyright (C) 1991,1992,1993,1994,1995,1996,1997,2000,2002,2004,2005
-	Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <sysdep.h>
-#define _ERRNO_H
-#include <bits/errno.h>
-#include <bp-asm.h>
-#include <bp-sym.h>
-
-#ifdef IS_IN_rtld
-# include <dl-sysdep.h>		/* Defines RTLD_PRIVATE_ERRNO.  */
-#endif
-
-.globl C_SYMBOL_NAME(errno)
-.globl syscall_error
-
-#undef syscall_error
-#ifdef NO_UNDERSCORES
-__syscall_error:
-#else
-syscall_error:
-#endif
-#if defined (EWOULDBLOCK_sys) && EWOULDBLOCK_sys != EAGAIN
-	/* We translate the system's EWOULDBLOCK error into EAGAIN.
-	   The GNU C library always defines EWOULDBLOCK==EAGAIN.
-	   EWOULDBLOCK_sys is the original number.  */
-	cmpl $EWOULDBLOCK_sys, %eax /* Is it the old EWOULDBLOCK?  */
-	jne notb		/* Branch if not.  */
-	movl $EAGAIN, %eax	/* Yes; translate it to EAGAIN.  */
-notb:
-#endif
-#ifndef	PIC
-# if USE___THREAD
-#  ifndef NO_TLS_DIRECT_SEG_REFS
-	movl %eax, %gs:C_SYMBOL_NAME(errno@NTPOFF)
-#  else
-	movl %gs:0, %ecx
-	movl %eax, C_SYMBOL_NAME(errno@NTPOFF)(%ecx)
-#  endif
-# elif !defined _LIBC_REENTRANT
-	movl %eax, C_SYMBOL_NAME(errno)
-# else
-	pushl %eax
-	PUSH_ERRNO_LOCATION_RETURN
-	call BP_SYM (PAL(__errno_location))
-	POP_ERRNO_LOCATION_RETURN
-	popl %ecx
-	movl %ecx, (%eax)
-# endif
-#else
-	/* The caller has pushed %ebx and then set it up to
-	   point to the GOT before calling us through the PLT.  */
-# if USE___THREAD
-	movl C_SYMBOL_NAME(errno@GOTNTPOFF)(%ebx), %ecx
-
-	/* Pop %ebx value saved before jumping here.  */
-	popl %ebx
-#  ifndef NO_TLS_DIRECT_SEG_REFS
-	addl %gs:0, %ecx
-	movl %eax, (%ecx)
-#  else
-	movl %eax, %gs:0(%ecx)
-#  endif
-# elif RTLD_PRIVATE_ERRNO
-	movl %eax, C_SYMBOL_NAME(rtld_errno@GOTOFF)(%ebx)
-
-	/* Pop %ebx value saved before jumping here.  */
-	popl %ebx
-# elif !defined _LIBC_REENTRANT
-	movl C_SYMBOL_NAME(errno@GOT)(%ebx), %ecx
-
-	/* Pop %ebx value saved before jumping here.  */
-	popl %ebx
-	movl %eax, (%ecx)
-# else
-	pushl %eax
-	PUSH_ERRNO_LOCATION_RETURN
-	call C_SYMBOL_NAME (BP_SYM (PAL(__errno_location))@PLT)
-	POP_ERRNO_LOCATION_RETURN
-	popl %ecx
-	/* Pop %ebx value saved before jumping here.  */
-	popl %ebx
-	movl %ecx, (%eax)
-# endif
-#endif
-	movl $-1, %eax
-	ret
-
-#undef	__syscall_error
-END (__syscall_error)

+ 0 - 90
Pal/include/sysdeps/unix/x86_64/sysdep.S

@@ -1,90 +0,0 @@
-/* Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <sysdep.h>
-#define _ERRNO_H
-#include <bits/errno.h>
-#include <bp-asm.h>
-#include <bp-sym.h>
-//#include <tls.h>
-
-#ifdef IS_IN_rtld
-# include <dl-sysdep.h>		/* Defines RTLD_PRIVATE_ERRNO.  */
-#endif
-
-.globl C_SYMBOL_NAME(errno)
-.globl syscall_error
-
-#undef syscall_error
-#ifdef NO_UNDERSCORES
-__syscall_error:
-#else
-syscall_error:
-#endif
-#if defined (EWOULDBLOCK_sys) && EWOULDBLOCK_sys != EAGAIN
-	/* We translate the system's EWOULDBLOCK error into EAGAIN.
-	   The GNU C library always defines EWOULDBLOCK==EAGAIN.
-	   EWOULDBLOCK_sys is the original number.  */
-	cmpq $EWOULDBLOCK_sys, %rax /* Is it the old EWOULDBLOCK?  */
-	jne notb		/* Branch if not.  */
-	movl $EAGAIN, %eax	/* Yes; translate it to EAGAIN.  */
-notb:
-#endif
-#if USE___THREAD
-# ifdef PIC
-	movq C_SYMBOL_NAME(errno@GOTTPOFF)(%rip), %rcx
-	movl %eax, %fs:0(%rcx)
-# else
-	movl %eax, %fs:C_SYMBOL_NAME(errno@TPOFF)
-# endif
-#elif !defined PIC
-# ifndef _LIBC_REENTRANT
-	movl %eax, C_SYMBOL_NAME(errno)
-# else
-	pushq %rax
-	cfi_adjust_cfa_offset(8)
-	PUSH_ERRNO_LOCATION_RETURN
-	call BP_SYM (PAL(__errno_location))
-	POP_ERRNO_LOCATION_RETURN
-	popq %rcx
-	cfi_adjust_cfa_offset(-8)
-	movl %ecx, (%rax)
-# endif
-#else
-# if RTLD_PRIVATE_ERRNO
-	leaq rtld_errno(%rip), %rcx
-	movl %eax, (%rcx)
-# elif !defined _LIBC_REENTRANT
-	movq C_SYMBOL_NAME(errno)@GOTPCREL(%rip), %rcx
-	movl %eax, (%rcx)
-# else
-	pushq %rax
-	cfi_adjust_cfa_offset(8)
-	PUSH_ERRNO_LOCATION_RETURN
-	call C_SYMBOL_NAME (BP_SYM (PAL(__errno_location))@PLT)
-	POP_ERRNO_LOCATION_RETURN
-	popq %rcx
-	cfi_adjust_cfa_offset(-8)
-	movl %ecx, (%rax)
-# endif
-#endif
-	movq $-1, %rax
-	ret
-
-#undef	__syscall_error
-END (__syscall_error)

+ 14 - 1
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)

+ 1 - 1
Pal/lib/Makefile

@@ -13,7 +13,7 @@ include ../src/host/$(PAL_HOST)/Makefile.am
 CFLAGS += -I. -I../include -I../src
 subdirs = string stdlib network graphene util crypto crypto/mbedtls
 objs	= $(foreach dir,$(subdirs),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c)))
-headers = asm-errlist.h api.h
+headers = api.h
 
 # Select which crypto adpater you want to use here. This has to match
 # the #define in pal_crypto.h.

+ 0 - 1495
Pal/lib/asm-errlist.h

@@ -1,1495 +0,0 @@
-/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
-/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
-
-/* Copyright (C) 2014 OSCAR lab, Stony Brook University
-   This file is part of Graphene Library OS.
-
-   Graphene Library OS is free software: you can redistribute it and/or
-   modify it under the terms of the GNU General Public License
-   as published by the Free Software Foundation, either version 3 of the
-   License, or (at your option) any later version.
-
-   Graphene Library OS is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-
-/* This file is generated from errno.texi by errlist.awk.  */
-
-#include <asm-errno.h>
-
-#ifndef ERR_REMAP
-# define ERR_REMAP(n) n
-#endif
-
-#ifndef N
-#define N_(str) (str)
-#endif
-
-#ifdef ERR_MAX
-# define ERRLIST_SIZE ERR_MAX + 1
-#else
-# define ERRLIST_SIZE
-#endif
-static const char *const __sys_errlist_internal[ERRLIST_SIZE] =
-  {
-    [0] = N_("Success"),
-#ifdef EPERM
-/*
-TRANS Operation not permitted; only the owner of the file (or other resource)
-TRANS or processes with special privileges can perform the operation. */
-    [ERR_REMAP (EPERM)] = N_("Operation not permitted"),
-# if EPERM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPERM
-# endif
-#endif
-#ifdef ENOENT
-/*
-TRANS No such file or directory.  This is a ``file doesn't exist'' error
-TRANS for ordinary files that are referenced in contexts where they are
-TRANS expected to already exist. */
-    [ERR_REMAP (ENOENT)] = N_("No such file or directory"),
-# if ENOENT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOENT
-# endif
-#endif
-#ifdef ESRCH
-/*
-TRANS No process matches the specified process ID. */
-    [ERR_REMAP (ESRCH)] = N_("No such process"),
-# if ESRCH > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ESRCH
-# endif
-#endif
-#ifdef EINTR
-/*
-TRANS Interrupted function call; an asynchronous signal occurred and prevented
-TRANS completion of the call.  When this happens, you should try the call
-TRANS again.
-TRANS 
-TRANS You can choose to have functions resume after a signal that is handled,
-TRANS rather than failing with @code{EINTR}; see @ref{Interrupted
-TRANS Primitives}. */
-    [ERR_REMAP (EINTR)] = N_("Interrupted system call"),
-# if EINTR > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EINTR
-# endif
-#endif
-#ifdef EIO
-/*
-TRANS Input/output error; usually used for physical read or write errors. */
-    [ERR_REMAP (EIO)] = N_("Input/output error"),
-# if EIO > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EIO
-# endif
-#endif
-#ifdef ENXIO
-/*
-TRANS No such device or address.  The system tried to use the device
-TRANS represented by a file you specified, and it couldn't find the device.
-TRANS This can mean that the device file was installed incorrectly, or that
-TRANS the physical device is missing or not correctly attached to the
-TRANS computer. */
-    [ERR_REMAP (ENXIO)] = N_("No such device or address"),
-# if ENXIO > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENXIO
-# endif
-#endif
-#ifdef E2BIG
-/*
-TRANS Argument list too long; used when the arguments passed to a new program
-TRANS being executed with one of the @code{exec} functions (@pxref{Executing a
-TRANS File}) occupy too much memory space.  This condition never arises in the
-TRANS GNU system. */
-    [ERR_REMAP (E2BIG)] = N_("Argument list too long"),
-# if E2BIG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX E2BIG
-# endif
-#endif
-#ifdef ENOEXEC
-/*
-TRANS Invalid executable file format.  This condition is detected by the
-TRANS @code{exec} functions; see @ref{Executing a File}. */
-    [ERR_REMAP (ENOEXEC)] = N_("Exec format error"),
-# if ENOEXEC > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOEXEC
-# endif
-#endif
-#ifdef EBADF
-/*
-TRANS Bad file descriptor; for example, I/O on a descriptor that has been
-TRANS closed or reading from a descriptor open only for writing (or vice
-TRANS versa). */
-    [ERR_REMAP (EBADF)] = N_("Bad file descriptor"),
-# if EBADF > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBADF
-# endif
-#endif
-#ifdef ECHILD
-/*
-TRANS There are no child processes.  This error happens on operations that are
-TRANS supposed to manipulate child processes, when there aren't any processes
-TRANS to manipulate. */
-    [ERR_REMAP (ECHILD)] = N_("No child processes"),
-# if ECHILD > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ECHILD
-# endif
-#endif
-#ifdef EDEADLK
-/*
-TRANS Deadlock avoided; allocating a system resource would have resulted in a
-TRANS deadlock situation.  The system does not guarantee that it will notice
-TRANS all such situations.  This error means you got lucky and the system
-TRANS noticed; it might just hang.  @xref{File Locks}, for an example. */
-    [ERR_REMAP (EDEADLK)] = N_("Resource deadlock avoided"),
-# if EDEADLK > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EDEADLK
-# endif
-#endif
-#ifdef ENOMEM
-/*
-TRANS No memory available.  The system cannot allocate more virtual memory
-TRANS because its capacity is full. */
-    [ERR_REMAP (ENOMEM)] = N_("Cannot allocate memory"),
-# if ENOMEM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOMEM
-# endif
-#endif
-#ifdef EACCES
-/*
-TRANS Permission denied; the file permissions do not allow the attempted operation. */
-    [ERR_REMAP (EACCES)] = N_("Permission denied"),
-# if EACCES > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EACCES
-# endif
-#endif
-#ifdef EFAULT
-/*
-TRANS Bad address; an invalid pointer was detected.
-TRANS In the GNU system, this error never happens; you get a signal instead. */
-    [ERR_REMAP (EFAULT)] = N_("Bad address"),
-# if EFAULT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EFAULT
-# endif
-#endif
-#ifdef ENOTBLK
-/*
-TRANS A file that isn't a block special file was given in a situation that
-TRANS requires one.  For example, trying to mount an ordinary file as a file
-TRANS system in Unix gives this error. */
-    [ERR_REMAP (ENOTBLK)] = N_("Block device required"),
-# if ENOTBLK > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTBLK
-# endif
-#endif
-#ifdef EBUSY
-/*
-TRANS Resource busy; a system resource that can't be shared is already in use.
-TRANS For example, if you try to delete a file that is the root of a currently
-TRANS mounted filesystem, you get this error. */
-    [ERR_REMAP (EBUSY)] = N_("Device or resource busy"),
-# if EBUSY > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBUSY
-# endif
-#endif
-#ifdef EEXIST
-/*
-TRANS File exists; an existing file was specified in a context where it only
-TRANS makes sense to specify a new file. */
-    [ERR_REMAP (EEXIST)] = N_("File exists"),
-# if EEXIST > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EEXIST
-# endif
-#endif
-#ifdef EXDEV
-/*
-TRANS An attempt to make an improper link across file systems was detected.
-TRANS This happens not only when you use @code{link} (@pxref{Hard Links}) but
-TRANS also when you rename a file with @code{rename} (@pxref{Renaming Files}). */
-    [ERR_REMAP (EXDEV)] = N_("Invalid cross-device link"),
-# if EXDEV > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EXDEV
-# endif
-#endif
-#ifdef ENODEV
-/*
-TRANS The wrong type of device was given to a function that expects a
-TRANS particular sort of device. */
-    [ERR_REMAP (ENODEV)] = N_("No such device"),
-# if ENODEV > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENODEV
-# endif
-#endif
-#ifdef ENOTDIR
-/*
-TRANS A file that isn't a directory was specified when a directory is required. */
-    [ERR_REMAP (ENOTDIR)] = N_("Not a directory"),
-# if ENOTDIR > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTDIR
-# endif
-#endif
-#ifdef EISDIR
-/*
-TRANS File is a directory; you cannot open a directory for writing,
-TRANS or create or remove hard links to it. */
-    [ERR_REMAP (EISDIR)] = N_("Is a directory"),
-# if EISDIR > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EISDIR
-# endif
-#endif
-#ifdef EINVAL
-/*
-TRANS Invalid argument.  This is used to indicate various kinds of problems
-TRANS with passing the wrong argument to a library function. */
-    [ERR_REMAP (EINVAL)] = N_("Invalid argument"),
-# if EINVAL > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EINVAL
-# endif
-#endif
-#ifdef EMFILE
-/*
-TRANS The current process has too many files open and can't open any more.
-TRANS Duplicate descriptors do count toward this limit.
-TRANS 
-TRANS In BSD and GNU, the number of open files is controlled by a resource
-TRANS limit that can usually be increased.  If you get this error, you might
-TRANS want to increase the @code{RLIMIT_NOFILE} limit or make it unlimited;
-TRANS @pxref{Limits on Resources}. */
-    [ERR_REMAP (EMFILE)] = N_("Too many open files"),
-# if EMFILE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EMFILE
-# endif
-#endif
-#ifdef ENFILE
-/*
-TRANS There are too many distinct file openings in the entire system.  Note
-TRANS that any number of linked channels count as just one file opening; see
-TRANS @ref{Linked Channels}.  This error never occurs in the GNU system. */
-    [ERR_REMAP (ENFILE)] = N_("Too many open files in system"),
-# if ENFILE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENFILE
-# endif
-#endif
-#ifdef ENOTTY
-/*
-TRANS Inappropriate I/O control operation, such as trying to set terminal
-TRANS modes on an ordinary file. */
-    [ERR_REMAP (ENOTTY)] = N_("Inappropriate ioctl for device"),
-# if ENOTTY > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTTY
-# endif
-#endif
-#ifdef ETXTBSY
-/*
-TRANS An attempt to execute a file that is currently open for writing, or
-TRANS write to a file that is currently being executed.  Often using a
-TRANS debugger to run a program is considered having it open for writing and
-TRANS will cause this error.  (The name stands for ``text file busy''.)  This
-TRANS is not an error in the GNU system; the text is copied as necessary. */
-    [ERR_REMAP (ETXTBSY)] = N_("Text file busy"),
-# if ETXTBSY > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ETXTBSY
-# endif
-#endif
-#ifdef EFBIG
-/*
-TRANS File too big; the size of a file would be larger than allowed by the system. */
-    [ERR_REMAP (EFBIG)] = N_("File too large"),
-# if EFBIG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EFBIG
-# endif
-#endif
-#ifdef ENOSPC
-/*
-TRANS No space left on device; write operation on a file failed because the
-TRANS disk is full. */
-    [ERR_REMAP (ENOSPC)] = N_("No space left on device"),
-# if ENOSPC > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOSPC
-# endif
-#endif
-#ifdef ESPIPE
-/*
-TRANS Invalid seek operation (such as on a pipe). */
-    [ERR_REMAP (ESPIPE)] = N_("Illegal seek"),
-# if ESPIPE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ESPIPE
-# endif
-#endif
-#ifdef EROFS
-/*
-TRANS An attempt was made to modify something on a read-only file system. */
-    [ERR_REMAP (EROFS)] = N_("Read-only file system"),
-# if EROFS > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EROFS
-# endif
-#endif
-#ifdef EMLINK
-/*
-TRANS Too many links; the link count of a single file would become too large.
-TRANS @code{rename} can cause this error if the file being renamed already has
-TRANS as many links as it can take (@pxref{Renaming Files}). */
-    [ERR_REMAP (EMLINK)] = N_("Too many links"),
-# if EMLINK > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EMLINK
-# endif
-#endif
-#ifdef EPIPE
-/*
-TRANS Broken pipe; there is no process reading from the other end of a pipe.
-TRANS Every library function that returns this error code also generates a
-TRANS @code{SIGPIPE} signal; this signal terminates the program if not handled
-TRANS or blocked.  Thus, your program will never actually see @code{EPIPE}
-TRANS unless it has handled or blocked @code{SIGPIPE}. */
-    [ERR_REMAP (EPIPE)] = N_("Broken pipe"),
-# if EPIPE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPIPE
-# endif
-#endif
-#ifdef EDOM
-/*
-TRANS Domain error; used by mathematical functions when an argument value does
-TRANS not fall into the domain over which the function is defined. */
-    [ERR_REMAP (EDOM)] = N_("Numerical argument out of domain"),
-# if EDOM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EDOM
-# endif
-#endif
-#ifdef ERANGE
-/*
-TRANS Range error; used by mathematical functions when the result value is
-TRANS not representable because of overflow or underflow. */
-    [ERR_REMAP (ERANGE)] = N_("Numerical result out of range"),
-# if ERANGE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ERANGE
-# endif
-#endif
-#ifdef EAGAIN
-/*
-TRANS Resource temporarily unavailable; the call might work if you try again
-TRANS later.  The macro @code{EWOULDBLOCK} is another name for @code{EAGAIN};
-TRANS they are always the same in the GNU C library.
-TRANS 
-TRANS This error can happen in a few different situations:
-TRANS 
-TRANS @itemize @bullet
-TRANS @item
-TRANS An operation that would block was attempted on an object that has
-TRANS non-blocking mode selected.  Trying the same operation again will block
-TRANS until some external condition makes it possible to read, write, or
-TRANS connect (whatever the operation).  You can use @code{select} to find out
-TRANS when the operation will be possible; @pxref{Waiting for I/O}.
-TRANS 
-TRANS @strong{Portability Note:} In many older Unix systems, this condition
-TRANS was indicated by @code{EWOULDBLOCK}, which was a distinct error code
-TRANS different from @code{EAGAIN}.  To make your program portable, you should
-TRANS check for both codes and treat them the same.
-TRANS 
-TRANS @item
-TRANS A temporary resource shortage made an operation impossible.  @code{fork}
-TRANS can return this error.  It indicates that the shortage is expected to
-TRANS pass, so your program can try the call again later and it may succeed.
-TRANS It is probably a good idea to delay for a few seconds before trying it
-TRANS again, to allow time for other processes to release scarce resources.
-TRANS Such shortages are usually fairly serious and affect the whole system,
-TRANS so usually an interactive program should report the error to the user
-TRANS and return to its command loop.
-TRANS @end itemize */
-    [ERR_REMAP (EAGAIN)] = N_("Resource temporarily unavailable"),
-# if EAGAIN > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EAGAIN
-# endif
-#endif
-#if defined (EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
-/*
-TRANS In the GNU C library, this is another name for @code{EAGAIN} (above).
-TRANS The values are always the same, on every operating system.
-TRANS 
-TRANS C libraries in many older Unix systems have @code{EWOULDBLOCK} as a
-TRANS separate error code. */
-    [ERR_REMAP (EWOULDBLOCK)] = N_("Operation would block"),
-# if EWOULDBLOCK > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EWOULDBLOCK
-# endif
-#endif
-#ifdef EINPROGRESS
-/*
-TRANS An operation that cannot complete immediately was initiated on an object
-TRANS that has non-blocking mode selected.  Some functions that must always
-TRANS block (such as @code{connect}; @pxref{Connecting}) never return
-TRANS @code{EAGAIN}.  Instead, they return @code{EINPROGRESS} to indicate that
-TRANS the operation has begun and will take some time.  Attempts to manipulate
-TRANS the object before the call completes return @code{EALREADY}.  You can
-TRANS use the @code{select} function to find out when the pending operation
-TRANS has completed; @pxref{Waiting for I/O}. */
-    [ERR_REMAP (EINPROGRESS)] = N_("Operation now in progress"),
-# if EINPROGRESS > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EINPROGRESS
-# endif
-#endif
-#ifdef EALREADY
-/*
-TRANS An operation is already in progress on an object that has non-blocking
-TRANS mode selected. */
-    [ERR_REMAP (EALREADY)] = N_("Operation already in progress"),
-# if EALREADY > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EALREADY
-# endif
-#endif
-#ifdef ENOTSOCK
-/*
-TRANS A file that isn't a socket was specified when a socket is required. */
-    [ERR_REMAP (ENOTSOCK)] = N_("Socket operation on non-socket"),
-# if ENOTSOCK > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTSOCK
-# endif
-#endif
-#ifdef EMSGSIZE
-/*
-TRANS The size of a message sent on a socket was larger than the supported
-TRANS maximum size. */
-    [ERR_REMAP (EMSGSIZE)] = N_("Message too long"),
-# if EMSGSIZE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EMSGSIZE
-# endif
-#endif
-#ifdef EPROTOTYPE
-/*
-TRANS The socket type does not support the requested communications protocol. */
-    [ERR_REMAP (EPROTOTYPE)] = N_("Protocol wrong type for socket"),
-# if EPROTOTYPE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPROTOTYPE
-# endif
-#endif
-#ifdef ENOPROTOOPT
-/*
-TRANS You specified a socket option that doesn't make sense for the
-TRANS particular protocol being used by the socket.  @xref{Socket Options}. */
-    [ERR_REMAP (ENOPROTOOPT)] = N_("Protocol not available"),
-# if ENOPROTOOPT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOPROTOOPT
-# endif
-#endif
-#ifdef EPROTONOSUPPORT
-/*
-TRANS The socket domain does not support the requested communications protocol
-TRANS (perhaps because the requested protocol is completely invalid).
-TRANS @xref{Creating a Socket}. */
-    [ERR_REMAP (EPROTONOSUPPORT)] = N_("Protocol not supported"),
-# if EPROTONOSUPPORT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPROTONOSUPPORT
-# endif
-#endif
-#ifdef ESOCKTNOSUPPORT
-/*
-TRANS The socket type is not supported. */
-    [ERR_REMAP (ESOCKTNOSUPPORT)] = N_("Socket type not supported"),
-# if ESOCKTNOSUPPORT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ESOCKTNOSUPPORT
-# endif
-#endif
-#ifdef EOPNOTSUPP
-/*
-TRANS The operation you requested is not supported.  Some socket functions
-TRANS don't make sense for all types of sockets, and others may not be
-TRANS implemented for all communications protocols.  In the GNU system, this
-TRANS error can happen for many calls when the object does not support the
-TRANS particular operation; it is a generic indication that the server knows
-TRANS nothing to do for that call. */
-    [ERR_REMAP (EOPNOTSUPP)] = N_("Operation not supported"),
-# if EOPNOTSUPP > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EOPNOTSUPP
-# endif
-#endif
-#ifdef EPFNOSUPPORT
-/*
-TRANS The socket communications protocol family you requested is not supported. */
-    [ERR_REMAP (EPFNOSUPPORT)] = N_("Protocol family not supported"),
-# if EPFNOSUPPORT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPFNOSUPPORT
-# endif
-#endif
-#ifdef EAFNOSUPPORT
-/*
-TRANS The address family specified for a socket is not supported; it is
-TRANS inconsistent with the protocol being used on the socket.  @xref{Sockets}. */
-    [ERR_REMAP (EAFNOSUPPORT)] = N_("Address family not supported by protocol"),
-# if EAFNOSUPPORT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EAFNOSUPPORT
-# endif
-#endif
-#ifdef EADDRINUSE
-/*
-TRANS The requested socket address is already in use.  @xref{Socket Addresses}. */
-    [ERR_REMAP (EADDRINUSE)] = N_("Address already in use"),
-# if EADDRINUSE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EADDRINUSE
-# endif
-#endif
-#ifdef EADDRNOTAVAIL
-/*
-TRANS The requested socket address is not available; for example, you tried
-TRANS to give a socket a name that doesn't match the local host name.
-TRANS @xref{Socket Addresses}. */
-    [ERR_REMAP (EADDRNOTAVAIL)] = N_("Cannot assign requested address"),
-# if EADDRNOTAVAIL > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EADDRNOTAVAIL
-# endif
-#endif
-#ifdef ENETDOWN
-/*
-TRANS A socket operation failed because the network was down. */
-    [ERR_REMAP (ENETDOWN)] = N_("Network is down"),
-# if ENETDOWN > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENETDOWN
-# endif
-#endif
-#ifdef ENETUNREACH
-/*
-TRANS A socket operation failed because the subnet containing the remote host
-TRANS was unreachable. */
-    [ERR_REMAP (ENETUNREACH)] = N_("Network is unreachable"),
-# if ENETUNREACH > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENETUNREACH
-# endif
-#endif
-#ifdef ENETRESET
-/*
-TRANS A network connection was reset because the remote host crashed. */
-    [ERR_REMAP (ENETRESET)] = N_("Network dropped connection on reset"),
-# if ENETRESET > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENETRESET
-# endif
-#endif
-#ifdef ECONNABORTED
-/*
-TRANS A network connection was aborted locally. */
-    [ERR_REMAP (ECONNABORTED)] = N_("Software caused connection abort"),
-# if ECONNABORTED > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ECONNABORTED
-# endif
-#endif
-#ifdef ECONNRESET
-/*
-TRANS A network connection was closed for reasons outside the control of the
-TRANS local host, such as by the remote machine rebooting or an unrecoverable
-TRANS protocol violation. */
-    [ERR_REMAP (ECONNRESET)] = N_("Connection reset by peer"),
-# if ECONNRESET > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ECONNRESET
-# endif
-#endif
-#ifdef ENOBUFS
-/*
-TRANS The kernel's buffers for I/O operations are all in use.  In GNU, this
-TRANS error is always synonymous with @code{ENOMEM}; you may get one or the
-TRANS other from network operations. */
-    [ERR_REMAP (ENOBUFS)] = N_("No buffer space available"),
-# if ENOBUFS > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOBUFS
-# endif
-#endif
-#ifdef EISCONN
-/*
-TRANS You tried to connect a socket that is already connected.
-TRANS @xref{Connecting}. */
-    [ERR_REMAP (EISCONN)] = N_("Transport endpoint is already connected"),
-# if EISCONN > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EISCONN
-# endif
-#endif
-#ifdef ENOTCONN
-/*
-TRANS The socket is not connected to anything.  You get this error when you
-TRANS try to transmit data over a socket, without first specifying a
-TRANS destination for the data.  For a connectionless socket (for datagram
-TRANS protocols, such as UDP), you get @code{EDESTADDRREQ} instead. */
-    [ERR_REMAP (ENOTCONN)] = N_("Transport endpoint is not connected"),
-# if ENOTCONN > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTCONN
-# endif
-#endif
-#ifdef EDESTADDRREQ
-/*
-TRANS No default destination address was set for the socket.  You get this
-TRANS error when you try to transmit data over a connectionless socket,
-TRANS without first specifying a destination for the data with @code{connect}. */
-    [ERR_REMAP (EDESTADDRREQ)] = N_("Destination address required"),
-# if EDESTADDRREQ > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EDESTADDRREQ
-# endif
-#endif
-#ifdef ESHUTDOWN
-/*
-TRANS The socket has already been shut down. */
-    [ERR_REMAP (ESHUTDOWN)] = N_("Cannot send after transport endpoint shutdown"),
-# if ESHUTDOWN > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ESHUTDOWN
-# endif
-#endif
-#ifdef ETOOMANYREFS
-/*
-TRANS ??? */
-    [ERR_REMAP (ETOOMANYREFS)] = N_("Too many references: cannot splice"),
-# if ETOOMANYREFS > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ETOOMANYREFS
-# endif
-#endif
-#ifdef ETIMEDOUT
-/*
-TRANS A socket operation with a specified timeout received no response during
-TRANS the timeout period. */
-    [ERR_REMAP (ETIMEDOUT)] = N_("Connection timed out"),
-# if ETIMEDOUT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ETIMEDOUT
-# endif
-#endif
-#ifdef ECONNREFUSED
-/*
-TRANS A remote host refused to allow the network connection (typically because
-TRANS it is not running the requested service). */
-    [ERR_REMAP (ECONNREFUSED)] = N_("Connection refused"),
-# if ECONNREFUSED > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ECONNREFUSED
-# endif
-#endif
-#ifdef ELOOP
-/*
-TRANS Too many levels of symbolic links were encountered in looking up a file name.
-TRANS This often indicates a cycle of symbolic links. */
-    [ERR_REMAP (ELOOP)] = N_("Too many levels of symbolic links"),
-# if ELOOP > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ELOOP
-# endif
-#endif
-#ifdef ENAMETOOLONG
-/*
-TRANS Filename too long (longer than @code{PATH_MAX}; @pxref{Limits for
-TRANS Files}) or host name too long (in @code{gethostname} or
-TRANS @code{sethostname}; @pxref{Host Identification}). */
-    [ERR_REMAP (ENAMETOOLONG)] = N_("File name too long"),
-# if ENAMETOOLONG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENAMETOOLONG
-# endif
-#endif
-#ifdef EHOSTDOWN
-/*
-TRANS The remote host for a requested network connection is down. */
-    [ERR_REMAP (EHOSTDOWN)] = N_("Host is down"),
-# if EHOSTDOWN > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EHOSTDOWN
-# endif
-#endif
-#ifdef EHOSTUNREACH
-/*
-TRANS The remote host for a requested network connection is not reachable. */
-    [ERR_REMAP (EHOSTUNREACH)] = N_("No route to host"),
-# if EHOSTUNREACH > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EHOSTUNREACH
-# endif
-#endif
-#ifdef ENOTEMPTY
-/*
-TRANS Directory not empty, where an empty directory was expected.  Typically,
-TRANS this error occurs when you are trying to delete a directory. */
-    [ERR_REMAP (ENOTEMPTY)] = N_("Directory not empty"),
-# if ENOTEMPTY > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTEMPTY
-# endif
-#endif
-#ifdef EPROCLIM
-/*
-TRANS This means that the per-user limit on new process would be exceeded by
-TRANS an attempted @code{fork}.  @xref{Limits on Resources}, for details on
-TRANS the @code{RLIMIT_NPROC} limit. */
-    [ERR_REMAP (EPROCLIM)] = N_("Too many processes"),
-# if EPROCLIM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPROCLIM
-# endif
-#endif
-#ifdef EUSERS
-/*
-TRANS The file quota system is confused because there are too many users.
-TRANS @c This can probably happen in a GNU system when using NFS. */
-    [ERR_REMAP (EUSERS)] = N_("Too many users"),
-# if EUSERS > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EUSERS
-# endif
-#endif
-#ifdef EDQUOT
-/*
-TRANS The user's disk quota was exceeded. */
-    [ERR_REMAP (EDQUOT)] = N_("Disk quota exceeded"),
-# if EDQUOT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EDQUOT
-# endif
-#endif
-#ifdef ESTALE
-/*
-TRANS Stale NFS file handle.  This indicates an internal confusion in the NFS
-TRANS system which is due to file system rearrangements on the server host.
-TRANS Repairing this condition usually requires unmounting and remounting
-TRANS the NFS file system on the local host. */
-    [ERR_REMAP (ESTALE)] = N_("Stale NFS file handle"),
-# if ESTALE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ESTALE
-# endif
-#endif
-#ifdef EREMOTE
-/*
-TRANS An attempt was made to NFS-mount a remote file system with a file name that
-TRANS already specifies an NFS-mounted file.
-TRANS (This is an error on some operating systems, but we expect it to work
-TRANS properly on the GNU system, making this error code impossible.) */
-    [ERR_REMAP (EREMOTE)] = N_("Object is remote"),
-# if EREMOTE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EREMOTE
-# endif
-#endif
-#ifdef EBADRPC
-/*
-TRANS ??? */
-    [ERR_REMAP (EBADRPC)] = N_("RPC struct is bad"),
-# if EBADRPC > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBADRPC
-# endif
-#endif
-#ifdef ERPCMISMATCH
-/*
-TRANS ??? */
-    [ERR_REMAP (ERPCMISMATCH)] = N_("RPC version wrong"),
-# if ERPCMISMATCH > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ERPCMISMATCH
-# endif
-#endif
-#ifdef EPROGUNAVAIL
-/*
-TRANS ??? */
-    [ERR_REMAP (EPROGUNAVAIL)] = N_("RPC program not available"),
-# if EPROGUNAVAIL > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPROGUNAVAIL
-# endif
-#endif
-#ifdef EPROGMISMATCH
-/*
-TRANS ??? */
-    [ERR_REMAP (EPROGMISMATCH)] = N_("RPC program version wrong"),
-# if EPROGMISMATCH > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPROGMISMATCH
-# endif
-#endif
-#ifdef EPROCUNAVAIL
-/*
-TRANS ??? */
-    [ERR_REMAP (EPROCUNAVAIL)] = N_("RPC bad procedure for program"),
-# if EPROCUNAVAIL > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPROCUNAVAIL
-# endif
-#endif
-#ifdef ENOLCK
-/*
-TRANS No locks available.  This is used by the file locking facilities; see
-TRANS @ref{File Locks}.  This error is never generated by the GNU system, but
-TRANS it can result from an operation to an NFS server running another
-TRANS operating system. */
-    [ERR_REMAP (ENOLCK)] = N_("No locks available"),
-# if ENOLCK > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOLCK
-# endif
-#endif
-#ifdef EFTYPE
-/*
-TRANS Inappropriate file type or format.  The file was the wrong type for the
-TRANS operation, or a data file had the wrong format.
-TRANS 
-TRANS On some systems @code{chmod} returns this error if you try to set the
-TRANS sticky bit on a non-directory file; @pxref{Setting Permissions}. */
-    [ERR_REMAP (EFTYPE)] = N_("Inappropriate file type or format"),
-# if EFTYPE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EFTYPE
-# endif
-#endif
-#ifdef EAUTH
-/*
-TRANS ??? */
-    [ERR_REMAP (EAUTH)] = N_("Authentication error"),
-# if EAUTH > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EAUTH
-# endif
-#endif
-#ifdef ENEEDAUTH
-/*
-TRANS ??? */
-    [ERR_REMAP (ENEEDAUTH)] = N_("Need authenticator"),
-# if ENEEDAUTH > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENEEDAUTH
-# endif
-#endif
-#ifdef ENOSYS
-/*
-TRANS Function not implemented.  This indicates that the function called is
-TRANS not implemented at all, either in the C library itself or in the
-TRANS operating system.  When you get this error, you can be sure that this
-TRANS particular function will always fail with @code{ENOSYS} unless you
-TRANS install a new version of the C library or the operating system. */
-    [ERR_REMAP (ENOSYS)] = N_("Function not implemented"),
-# if ENOSYS > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOSYS
-# endif
-#endif
-#if defined (ENOTSUP) && ENOTSUP != EOPNOTSUPP
-/*
-TRANS Not supported.  A function returns this error when certain parameter
-TRANS values are valid, but the functionality they request is not available.
-TRANS This can mean that the function does not implement a particular command
-TRANS or option value or flag bit at all.  For functions that operate on some
-TRANS object given in a parameter, such as a file descriptor or a port, it
-TRANS might instead mean that only @emph{that specific object} (file
-TRANS descriptor, port, etc.) is unable to support the other parameters given;
-TRANS different file descriptors might support different ranges of parameter
-TRANS values.
-TRANS 
-TRANS If the entire function is not available at all in the implementation,
-TRANS it returns @code{ENOSYS} instead. */
-    [ERR_REMAP (ENOTSUP)] = N_("Not supported"),
-# if ENOTSUP > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTSUP
-# endif
-#endif
-#ifdef EILSEQ
-/*
-TRANS While decoding a multibyte character the function came along an invalid
-TRANS or an incomplete sequence of bytes or the given wide character is invalid. */
-    [ERR_REMAP (EILSEQ)] = N_("Invalid or incomplete multibyte or wide character"),
-# if EILSEQ > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EILSEQ
-# endif
-#endif
-#ifdef EBACKGROUND
-/*
-TRANS In the GNU system, servers supporting the @code{term} protocol return
-TRANS this error for certain operations when the caller is not in the
-TRANS foreground process group of the terminal.  Users do not usually see this
-TRANS error because functions such as @code{read} and @code{write} translate
-TRANS it into a @code{SIGTTIN} or @code{SIGTTOU} signal.  @xref{Job Control},
-TRANS for information on process groups and these signals. */
-    [ERR_REMAP (EBACKGROUND)] = N_("Inappropriate operation for background process"),
-# if EBACKGROUND > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBACKGROUND
-# endif
-#endif
-#ifdef EDIED
-/*
-TRANS In the GNU system, opening a file returns this error when the file is
-TRANS translated by a program and the translator program dies while starting
-TRANS up, before it has connected to the file. */
-    [ERR_REMAP (EDIED)] = N_("Translator died"),
-# if EDIED > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EDIED
-# endif
-#endif
-#ifdef ED
-/*
-TRANS The experienced user will know what is wrong.
-TRANS @c This error code is a joke.  Its perror text is part of the joke.
-TRANS @c Don't change it. */
-    [ERR_REMAP (ED)] = N_("?"),
-# if ED > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ED
-# endif
-#endif
-#ifdef EGREGIOUS
-/*
-TRANS You did @strong{what}? */
-    [ERR_REMAP (EGREGIOUS)] = N_("You really blew it this time"),
-# if EGREGIOUS > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EGREGIOUS
-# endif
-#endif
-#ifdef EIEIO
-/*
-TRANS Go home and have a glass of warm, dairy-fresh milk. */
-    [ERR_REMAP (EIEIO)] = N_("Computer bought the farm"),
-# if EIEIO > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EIEIO
-# endif
-#endif
-#ifdef EGRATUITOUS
-/*
-TRANS This error code has no purpose. */
-    [ERR_REMAP (EGRATUITOUS)] = N_("Gratuitous error"),
-# if EGRATUITOUS > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EGRATUITOUS
-# endif
-#endif
-#ifdef EBADMSG
-/* */
-    [ERR_REMAP (EBADMSG)] = N_("Bad message"),
-# if EBADMSG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBADMSG
-# endif
-#endif
-#ifdef EIDRM
-/* */
-    [ERR_REMAP (EIDRM)] = N_("Identifier removed"),
-# if EIDRM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EIDRM
-# endif
-#endif
-#ifdef EMULTIHOP
-/* */
-    [ERR_REMAP (EMULTIHOP)] = N_("Multihop attempted"),
-# if EMULTIHOP > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EMULTIHOP
-# endif
-#endif
-#ifdef ENODATA
-/* */
-    [ERR_REMAP (ENODATA)] = N_("No data available"),
-# if ENODATA > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENODATA
-# endif
-#endif
-#ifdef ENOLINK
-/* */
-    [ERR_REMAP (ENOLINK)] = N_("Link has been severed"),
-# if ENOLINK > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOLINK
-# endif
-#endif
-#ifdef ENOMSG
-/* */
-    [ERR_REMAP (ENOMSG)] = N_("No message of desired type"),
-# if ENOMSG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOMSG
-# endif
-#endif
-#ifdef ENOSR
-/* */
-    [ERR_REMAP (ENOSR)] = N_("Out of streams resources"),
-# if ENOSR > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOSR
-# endif
-#endif
-#ifdef ENOSTR
-/* */
-    [ERR_REMAP (ENOSTR)] = N_("Device not a stream"),
-# if ENOSTR > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOSTR
-# endif
-#endif
-#ifdef EOVERFLOW
-/* */
-    [ERR_REMAP (EOVERFLOW)] = N_("Value too large for defined data type"),
-# if EOVERFLOW > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EOVERFLOW
-# endif
-#endif
-#ifdef EPROTO
-/* */
-    [ERR_REMAP (EPROTO)] = N_("Protocol error"),
-# if EPROTO > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EPROTO
-# endif
-#endif
-#ifdef ETIME
-/* */
-    [ERR_REMAP (ETIME)] = N_("Timer expired"),
-# if ETIME > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ETIME
-# endif
-#endif
-#ifdef ECANCELED
-/*
-TRANS Operation canceled; an asynchronous operation was canceled before it
-TRANS completed.  @xref{Asynchronous I/O}.  When you call @code{aio_cancel},
-TRANS the normal result is for the operations affected to complete with this
-TRANS error; @pxref{Cancel AIO Operations}. */
-    [ERR_REMAP (ECANCELED)] = N_("Operation canceled"),
-# if ECANCELED > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ECANCELED
-# endif
-#endif
-#ifdef ERESTART
-/* */
-    [ERR_REMAP (ERESTART)] = N_("Interrupted system call should be restarted"),
-# if ERESTART > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ERESTART
-# endif
-#endif
-#ifdef ECHRNG
-/* */
-    [ERR_REMAP (ECHRNG)] = N_("Channel number out of range"),
-# if ECHRNG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ECHRNG
-# endif
-#endif
-#ifdef EL2NSYNC
-/* */
-    [ERR_REMAP (EL2NSYNC)] = N_("Level 2 not synchronized"),
-# if EL2NSYNC > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EL2NSYNC
-# endif
-#endif
-#ifdef EL3HLT
-/* */
-    [ERR_REMAP (EL3HLT)] = N_("Level 3 halted"),
-# if EL3HLT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EL3HLT
-# endif
-#endif
-#ifdef EL3RST
-/* */
-    [ERR_REMAP (EL3RST)] = N_("Level 3 reset"),
-# if EL3RST > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EL3RST
-# endif
-#endif
-#ifdef ELNRNG
-/* */
-    [ERR_REMAP (ELNRNG)] = N_("Link number out of range"),
-# if ELNRNG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ELNRNG
-# endif
-#endif
-#ifdef EUNATCH
-/* */
-    [ERR_REMAP (EUNATCH)] = N_("Protocol driver not attached"),
-# if EUNATCH > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EUNATCH
-# endif
-#endif
-#ifdef ENOCSI
-/* */
-    [ERR_REMAP (ENOCSI)] = N_("No CSI structure available"),
-# if ENOCSI > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOCSI
-# endif
-#endif
-#ifdef EL2HLT
-/* */
-    [ERR_REMAP (EL2HLT)] = N_("Level 2 halted"),
-# if EL2HLT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EL2HLT
-# endif
-#endif
-#ifdef EBADE
-/* */
-    [ERR_REMAP (EBADE)] = N_("Invalid exchange"),
-# if EBADE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBADE
-# endif
-#endif
-#ifdef EBADR
-/* */
-    [ERR_REMAP (EBADR)] = N_("Invalid request descriptor"),
-# if EBADR > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBADR
-# endif
-#endif
-#ifdef EXFULL
-/* */
-    [ERR_REMAP (EXFULL)] = N_("Exchange full"),
-# if EXFULL > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EXFULL
-# endif
-#endif
-#ifdef ENOANO
-/* */
-    [ERR_REMAP (ENOANO)] = N_("No anode"),
-# if ENOANO > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOANO
-# endif
-#endif
-#ifdef EBADRQC
-/* */
-    [ERR_REMAP (EBADRQC)] = N_("Invalid request code"),
-# if EBADRQC > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBADRQC
-# endif
-#endif
-#ifdef EBADSLT
-/* */
-    [ERR_REMAP (EBADSLT)] = N_("Invalid slot"),
-# if EBADSLT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBADSLT
-# endif
-#endif
-#if defined (EDEADLOCK) && EDEADLOCK != EDEADLK
-/* */
-    [ERR_REMAP (EDEADLOCK)] = N_("File locking deadlock error"),
-# if EDEADLOCK > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EDEADLOCK
-# endif
-#endif
-#ifdef EBFONT
-/* */
-    [ERR_REMAP (EBFONT)] = N_("Bad font file format"),
-# if EBFONT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBFONT
-# endif
-#endif
-#ifdef ENONET
-/* */
-    [ERR_REMAP (ENONET)] = N_("Machine is not on the network"),
-# if ENONET > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENONET
-# endif
-#endif
-#ifdef ENOPKG
-/* */
-    [ERR_REMAP (ENOPKG)] = N_("Package not installed"),
-# if ENOPKG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOPKG
-# endif
-#endif
-#ifdef EADV
-/* */
-    [ERR_REMAP (EADV)] = N_("Advertise error"),
-# if EADV > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EADV
-# endif
-#endif
-#ifdef ESRMNT
-/* */
-    [ERR_REMAP (ESRMNT)] = N_("Srmount error"),
-# if ESRMNT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ESRMNT
-# endif
-#endif
-#ifdef ECOMM
-/* */
-    [ERR_REMAP (ECOMM)] = N_("Communication error on send"),
-# if ECOMM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ECOMM
-# endif
-#endif
-#ifdef EDOTDOT
-/* */
-    [ERR_REMAP (EDOTDOT)] = N_("RFS specific error"),
-# if EDOTDOT > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EDOTDOT
-# endif
-#endif
-#ifdef ENOTUNIQ
-/* */
-    [ERR_REMAP (ENOTUNIQ)] = N_("Name not unique on network"),
-# if ENOTUNIQ > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTUNIQ
-# endif
-#endif
-#ifdef EBADFD
-/* */
-    [ERR_REMAP (EBADFD)] = N_("File descriptor in bad state"),
-# if EBADFD > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EBADFD
-# endif
-#endif
-#ifdef EREMCHG
-/* */
-    [ERR_REMAP (EREMCHG)] = N_("Remote address changed"),
-# if EREMCHG > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EREMCHG
-# endif
-#endif
-#ifdef ELIBACC
-/* */
-    [ERR_REMAP (ELIBACC)] = N_("Can not access a needed shared library"),
-# if ELIBACC > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ELIBACC
-# endif
-#endif
-#ifdef ELIBBAD
-/* */
-    [ERR_REMAP (ELIBBAD)] = N_("Accessing a corrupted shared library"),
-# if ELIBBAD > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ELIBBAD
-# endif
-#endif
-#ifdef ELIBSCN
-/* */
-    [ERR_REMAP (ELIBSCN)] = N_(".lib section in a.out corrupted"),
-# if ELIBSCN > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ELIBSCN
-# endif
-#endif
-#ifdef ELIBMAX
-/* */
-    [ERR_REMAP (ELIBMAX)] = N_("Attempting to link in too many shared libraries"),
-# if ELIBMAX > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ELIBMAX
-# endif
-#endif
-#ifdef ELIBEXEC
-/* */
-    [ERR_REMAP (ELIBEXEC)] = N_("Cannot exec a shared library directly"),
-# if ELIBEXEC > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ELIBEXEC
-# endif
-#endif
-#ifdef ESTRPIPE
-/* */
-    [ERR_REMAP (ESTRPIPE)] = N_("Streams pipe error"),
-# if ESTRPIPE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ESTRPIPE
-# endif
-#endif
-#ifdef EUCLEAN
-/* */
-    [ERR_REMAP (EUCLEAN)] = N_("Structure needs cleaning"),
-# if EUCLEAN > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EUCLEAN
-# endif
-#endif
-#ifdef ENOTNAM
-/* */
-    [ERR_REMAP (ENOTNAM)] = N_("Not a XENIX named type file"),
-# if ENOTNAM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTNAM
-# endif
-#endif
-#ifdef ENAVAIL
-/* */
-    [ERR_REMAP (ENAVAIL)] = N_("No XENIX semaphores available"),
-# if ENAVAIL > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENAVAIL
-# endif
-#endif
-#ifdef EISNAM
-/* */
-    [ERR_REMAP (EISNAM)] = N_("Is a named type file"),
-# if EISNAM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EISNAM
-# endif
-#endif
-#ifdef EREMOTEIO
-/* */
-    [ERR_REMAP (EREMOTEIO)] = N_("Remote I/O error"),
-# if EREMOTEIO > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EREMOTEIO
-# endif
-#endif
-#ifdef ENOMEDIUM
-/* */
-    [ERR_REMAP (ENOMEDIUM)] = N_("No medium found"),
-# if ENOMEDIUM > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOMEDIUM
-# endif
-#endif
-#ifdef EMEDIUMTYPE
-/* */
-    [ERR_REMAP (EMEDIUMTYPE)] = N_("Wrong medium type"),
-# if EMEDIUMTYPE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EMEDIUMTYPE
-# endif
-#endif
-#ifdef ENOKEY
-/* */
-    [ERR_REMAP (ENOKEY)] = N_("Required key not available"),
-# if ENOKEY > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOKEY
-# endif
-#endif
-#ifdef EKEYEXPIRED
-/* */
-    [ERR_REMAP (EKEYEXPIRED)] = N_("Key has expired"),
-# if EKEYEXPIRED > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EKEYEXPIRED
-# endif
-#endif
-#ifdef EKEYREVOKED
-/* */
-    [ERR_REMAP (EKEYREVOKED)] = N_("Key has been revoked"),
-# if EKEYREVOKED > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EKEYREVOKED
-# endif
-#endif
-#ifdef EKEYREJECTED
-/* */
-    [ERR_REMAP (EKEYREJECTED)] = N_("Key was rejected by service"),
-# if EKEYREJECTED > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EKEYREJECTED
-# endif
-#endif
-#ifdef EOWNERDEAD
-/* */
-    [ERR_REMAP (EOWNERDEAD)] = N_("Owner died"),
-# if EOWNERDEAD > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX EOWNERDEAD
-# endif
-#endif
-#ifdef ENOTRECOVERABLE
-/* */
-    [ERR_REMAP (ENOTRECOVERABLE)] = N_("State not recoverable"),
-# if ENOTRECOVERABLE > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ENOTRECOVERABLE
-# endif
-#endif
-#ifdef ERFKILL
-/* */
-    [ERR_REMAP (ERFKILL)] = N_("Operation not possible due to RF-kill"),
-# if ERFKILL > ERR_MAX
-# undef ERR_MAX
-# define ERR_MAX ERFKILL
-# endif
-#endif
-  };
-
-#define NERR \
-  (sizeof __sys_errlist_internal / sizeof __sys_errlist_internal [0])
-
-#ifdef EMIT_ERR_MAX
-void dummy (void)
-{ asm volatile (" @@@ %0 @@@ " : : "i" (ERR_REMAP (ERR_MAX))); }
-#endif

+ 334 - 1
Pal/lib/crypto/aes.c

@@ -28,6 +28,7 @@
 
 #define XMEMSET memset
 #define XMEMCPY memcpy
+#define XMEMCMP memcmp
 
 #ifndef rotlFixed
 static inline word32 rotlFixed(word32 x, word32 y)
@@ -1334,7 +1335,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;
 
@@ -1383,4 +1384,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;
+}

+ 13 - 0
Pal/lib/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 */

+ 7 - 3
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;
 }

+ 3 - 3
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 = {

+ 34 - 1
Pal/src/db_main.c

@@ -33,7 +33,6 @@
 
 #include <sysdeps/generic/ldsodefs.h>
 #include <elf/elf.h>
-#include <bits/dlfcn.h>
 
 PAL_CONTROL __pal_control;
 
@@ -347,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");

+ 7 - 0
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;

+ 0 - 1
Pal/src/db_rtld.c

@@ -36,7 +36,6 @@
 
 #include <sysdeps/generic/ldsodefs.h>
 #include <elf/elf.h>
-#include <bits/dlfcn.h>
 
 struct link_map * loaded_maps = NULL;
 struct link_map * exec_map = NULL;

+ 1 - 1
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);
 }

+ 2 - 2
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);

+ 6 - 2
Pal/src/host/Linux-SGX/Makefile

@@ -1,6 +1,6 @@
 include Makefile.am
 
-CFLAGS	+= -I. -Iinclude -I../.. -I../../../include -I../../../lib
+CFLAGS	+= -I. -Iinclude -I../.. -I../../../include -I../../../lib -Isgx-driver
 ASFLAGS += -I. -I../.. -I../../../include
 
 host_files = libpal-Linux-SGX.a pal-sgx debugger/sgx_gdb.so
@@ -14,7 +14,8 @@ enclave-asm-objs = enclave_entry
 urts-objs = $(addprefix sgx_,enclave framework main rtld thread process exception graphene)
 urts-asm-objs = sgx_entry
 graphene_lib = ../../.lib/graphene-lib.a
-headers	= $(wildcard *.h) $(wildcard ../../*.h) $(wildcard ../../../lib/*.h)
+headers	= $(wildcard *.h) $(wildcard ../../*.h) $(wildcard ../../../lib/*.h) \
+	  $(addprefix sgx-driver/,graphene-sgx.h isgx_version.h)
 
 all: $(host_files)
 
@@ -64,6 +65,9 @@ debugger/sgx_gdb.so: debugger/sgx_gdb.c debugger/sgx_gdb.h sgx_arch.h
 	$(CC) -Wall -fPIC -O2 -std=gnu99 -fgnu89-inline -c debugger/sgx_gdb.c -o debugger/sgx_gdb.o
 	$(LD) -shared debugger/sgx_gdb.o -o debugger/sgx_gdb.so -lc
 
+sgx-driver/isgx_version.h:
+	cd sgx-driver && make isgx_version.h
+
 ../../libpal.so: ../../libpal-enclave.so
 	ln -s libpal-enclave.so $@
 

+ 1 - 1
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;
 

+ 3 - 3
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;
 

+ 4 - 4
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;

+ 0 - 1
Pal/src/host/Linux-SGX/db_rtld.c

@@ -39,7 +39,6 @@
 
 #include <sysdeps/generic/ldsodefs.h>
 #include <elf/elf.h>
-#include <bits/dlfcn.h>
 
 #include "elf-x86_64.h"
 

+ 1 - 1
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)

+ 46 - 8
Pal/src/host/Linux-SGX/enclave_framework.c

@@ -124,7 +124,8 @@ int load_trusted_file (PAL_HANDLE file, sgx_arch_mac_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;
@@ -133,24 +134,38 @@ int load_trusted_file (PAL_HANDLE file, sgx_arch_mac_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);
 
@@ -171,7 +186,7 @@ int load_trusted_file (PAL_HANDLE file, sgx_arch_mac_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
@@ -248,6 +263,16 @@ failed:
     }
     _DkSpinUnlock(&trusted_file_lock);
 
+#if PRINT_ENCLAVE_STAT
+    if (!ret) {
+        sgx_stub_t * loaded_stub;
+        uint64_t loaded_size;
+        PAL_HANDLE handle = NULL;
+        if (!_DkStreamOpen(&handle, normpath, PAL_ACCESS_RDONLY, 0, 0, 0))
+            load_trusted_file (handle, &loaded_stub, &loaded_size);
+    }
+#endif
+
     return ret;
 }
 
@@ -377,7 +402,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);
 
@@ -385,7 +411,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)

+ 4 - 4
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)

+ 2 - 2
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);
 

+ 4 - 2
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 {

+ 1 - 0
Pal/src/host/Linux-SGX/sgx-driver/.gitignore

@@ -7,3 +7,4 @@ Module.symvers
 modules.order
 .tmp_versions
 linux-sgx-driver
+isgx_version.h

+ 10 - 3
Pal/src/host/Linux-SGX/sgx-driver/Makefile

@@ -1,18 +1,25 @@
 ifneq ($(KERNELRELEASE),)
-	ccflags-y += -I$(PWD)/linux-sgx-driver
 	graphene-sgx-y := \
+		gsgx_ioctl_1_6.o \
+		gsgx_ioctl_1_7.o \
+		gsgx_fsgsbase.o \
 		gsgx_main.o
 	obj-m += graphene-sgx.o
 else
 KDIR := /lib/modules/$(shell uname -r)/build
 PWD  := $(shell pwd)
 
-default: linux-sgx-driver/isgx.h
+default: isgx_version.h linux-sgx-driver
 	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) CFLAGS_MODULE="-DDEBUG -g -O0" modules
 
-linux-sgx-driver/isgx.h:
+.INTERMEDIATE: link-sgx-driver
+link-sgx-driver:
 	@./link-intel-driver.py
+
+isgx_version.h linux-sgx-driver: link-sgx-driver
+
 endif
 
 clean:
+	rm -vrf linux-sgx-driver isgx_version.h
 	rm -vrf *.o *.ko *.order *.symvers *.mod.c .tmp_versions .*o.cmd

+ 46 - 0
Pal/src/host/Linux-SGX/sgx-driver/graphene-sgx.h

@@ -5,9 +5,25 @@
 #include <linux/stddef.h>
 #include <linux/types.h>
 
+#include "isgx_version.h"
+
 #define GSGX_FILE	"/dev/gsgx"
 #define GSGX_MINOR	MISC_DYNAMIC_MINOR
 
+#if SDK_DRIVER_VERSION >= KERNEL_VERSION(1, 8, 0)
+
+#ifndef __packed
+#define __packed __attribute__((packed))
+#endif
+
+#include "linux-sgx-driver/sgx_user.h"
+
+#endif
+
+#if SDK_DRIVER_VERSION < KERNEL_VERSION(1, 8, 0)
+
+#include "linux-sgx-driver/isgx_user.h"
+
 #define GSGX_IOCTL_ENCLAVE_CREATE	_IOWR('p', 0x01, struct gsgx_enclave_create)
 #define GSGX_IOCTL_ENCLAVE_ADD_PAGES	_IOW('p',  0x02, struct gsgx_enclave_add_pages)
 #define GSGX_IOCTL_ENCLAVE_INIT		_IOW('p',  0x03, struct gsgx_enclave_init)
@@ -35,4 +51,34 @@ struct gsgx_enclave_init {
 	uint64_t einittoken;
 };
 
+#endif /* SDK_DRIVER_VERSION < KERNEL_VERSION(1, 8, 0) */
+
+#if SDK_DRIVER_VERSION == KERNEL_VERSION(1, 6, 0)
+#define SGX_SUCCESS			ISGX_SUCCESS
+#define SGX_INVALID_SIG_STRUCT		ISGX_INVALID_SIG_STRUCT
+#define SGX_INVALID_ATTRIBUTE		ISGX_INVALID_ATTRIBUTE
+#define SGX_BLKSTATE			ISGX_BLKSTATE
+#define SGX_INVALID_MEASUREMENT		ISGX_INVALID_MEASUREMENT
+#define SGX_NOTBLOCKABLE		ISGX_NOTBLOCKABLE
+#define SGX_PG_INVLD			ISGX_PG_INVLD
+#define SGX_LOCKFAIL			ISGX_LOCKFAIL
+#define SGX_INVALID_SIGNATURE		ISGX_INVALID_SIGNATURE
+#define SGX_MAC_COMPARE_FAIL		ISGX_MAC_COMPARE_FAIL
+#define SGX_PAGE_NOT_BLOCKED		ISGX_PAGE_NOT_BLOCKED
+#define SGX_NOT_TRACKED			ISGX_NOT_TRACKED
+#define SGX_VA_SLOT_OCCUPIED		ISGX_VA_SLOT_OCCUPIED
+#define SGX_CHILD_PRESENT		ISGX_CHILD_PRESENT
+#define SGX_ENCLAVE_ACT			ISGX_ENCLAVE_ACT
+#define SGX_ENTRYEPOCH_LOCKED		ISGX_ENTRYEPOCH_LOCKED
+#define SGX_INVALID_LICENSE		ISGX_INVALID_LICENSE
+#define SGX_PREV_TRK_INCMPL 		ISGX_PREV_TRK_INCMPL
+#define SGX_PG_IS_SECS 			ISGX_PG_IS_SECS
+#define SGX_INVALID_CPUSVN		ISGX_INVALID_CPUSVN
+#define SGX_INVALID_ISVSVN		ISGX_INVALID_ISVSVN
+#define SGX_UNMASKED_EVENT		ISGX_UNMASKED_EVENT
+#define SGX_INVALID_KEYNAME		ISGX_INVALID_KEYNAME
+#define SGX_POWER_LOST_ENCLAVE		ISGX_POWER_LOST_ENCLAVE
+#define SGX_LE_ROLLBACK			ISGX_LE_ROLLBACK
+#endif
+
 #endif /* _X86_GSGX_USER_H */

+ 35 - 25
Pal/src/host/Linux-SGX/sgx-driver/gsgx.h

@@ -1,25 +1,35 @@
-/*
- * (C) Copyright 2013 Intel Corporation
- * Author: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; version 2
- * of the License.
- */
-
-#ifndef __ARCH_GSGX_H__
-#define __ARCH_GSGX_H__
-
-#include <isgx.h>
-#include <isgx_arch.h>
-#include <isgx_user.h>
-
-#include "graphene-sgx.h"
-#include "isgx_ksyms.h"
-
-extern struct vm_operations_struct gsgx_vm_ops;
-
-long gsgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
-
-#endif /* __ARCH_X86_GSGX_H__ */
+/*
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#ifndef __ARCH_GSGX_H__
+#define __ARCH_GSGX_H__
+
+#include "isgx_version.h"
+#include "graphene-sgx.h"
+
+#if SDK_DRIVER_VERSION < KERNEL_VERSION(1, 8, 0)
+
+#include "isgx_ksyms.h"
+
+extern struct file *isgx_dev;
+
+extern long gsgx_ioctl(struct file *, unsigned int, unsigned long);
+extern int gsgx_mmap(struct file *, struct vm_area_struct *);
+extern unsigned long gsgx_get_unmapped_area(struct file *, unsigned long,
+					    unsigned long, unsigned long,
+					    unsigned long);
+
+extern int gsgx_lookup_ksyms(void);
+
+#endif
+
+extern int gsgx_open(struct inode *, struct file *);
+
+#endif /* __ARCH_GSGX_H__ */

+ 37 - 0
Pal/src/host/Linux-SGX/sgx-driver/gsgx_fsgsbase.c

@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2015 Intel Corporation
+ * Author: Chia-Che Tsai <chiache-che.tsai@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/highmem.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/security.h>
+#include <asm/tlbflush.h>
+
+#include "gsgx.h"
+
+static void __enable_fsgsbase(void *v)
+{
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
+	write_cr4(read_cr4() | X86_CR4_FSGSBASE);
+#else
+	cr4_set_bits(X86_CR4_FSGSBASE);
+	__write_cr4(__read_cr4() | X86_CR4_FSGSBASE);
+#endif
+}
+
+int gsgx_open(struct inode *inode, struct file *file)
+{
+	__enable_fsgsbase(NULL);
+	smp_call_function(__enable_fsgsbase, NULL, 1);
+	return 0;
+}

+ 177 - 0
Pal/src/host/Linux-SGX/sgx-driver/gsgx_ioctl_1_6.c

@@ -0,0 +1,177 @@
+/*
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/highmem.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/security.h>
+#include <asm/tlbflush.h>
+
+#include "gsgx.h"
+
+#if SDK_DRIVER_VERSION == KERNEL_VERSION(1, 6, 0)
+
+#include "isgx.h"
+#include "isgx_arch.h"
+#include "isgx_user.h"
+
+struct file *isgx_dev;
+
+static long enclave_create(struct file *filep, void * arg)
+{
+	struct gsgx_enclave_create *createp = arg;
+	struct isgx_create_param isgx_create;
+
+	isgx_create.addr = createp->src;
+	filep->private_data = (void *) createp->src;
+
+	return KSYM(isgx_ioctl_enclave_create)(filep, ISGX_IOCTL_ENCLAVE_CREATE,
+					       (unsigned long) &isgx_create);
+}
+
+static long enclave_add_pages(struct file *filep, void * arg)
+{
+	struct gsgx_enclave_add_pages *addp = arg;
+	struct isgx_add_param isgx_add;
+	uint64_t off;
+	int ret = 0;
+
+	if (!addp->addr || (addp->addr & (PAGE_SIZE - 1)))
+		return -EINVAL;
+	if (!addp->size || (addp->size & (PAGE_SIZE - 1)))
+		return -EINVAL;
+	if (!addp->secinfo)
+		return -EINVAL;
+
+	isgx_add.secinfo = (struct isgx_secinfo *) addp->secinfo;
+
+	for (off = 0 ; off < addp->size ; off += PAGE_SIZE) {
+		isgx_add.addr = addp->addr + off;
+		isgx_add.user_addr =
+			addp->flags & GSGX_ENCLAVE_ADD_PAGES_REPEAT_SRC ?
+			addp->user_addr : addp->user_addr + off;
+		isgx_add.flags =
+			addp->flags & GSGX_ENCLAVE_ADD_PAGES_SKIP_EEXTEND ?
+			ISGX_ADD_SKIP_EEXTEND : 0;
+		ret = KSYM(isgx_ioctl_enclave_add_page)(filep,
+			ISGX_IOCTL_ENCLAVE_ADD_PAGE, (unsigned long) &isgx_add);
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+
+static long enclave_init(struct file *filep, void * arg)
+{
+	struct gsgx_enclave_init *initp = arg;
+	struct isgx_init_param isgx_init;
+
+	isgx_init.addr = initp->addr;
+	isgx_init.sigstruct = (void *) initp->sigstruct;
+	isgx_init.einittoken = (struct isgx_einittoken *) initp->einittoken;
+
+	return KSYM(isgx_ioctl_enclave_init)(filep, ISGX_IOCTL_ENCLAVE_INIT,
+					     (unsigned long) &isgx_init);
+}
+
+long gsgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+	char data[256];
+	long (*handler) (struct file *filp, void *arg) = NULL;
+	long ret;
+
+	switch (cmd) {
+		case GSGX_IOCTL_ENCLAVE_CREATE:
+			handler = enclave_create;
+			break;
+		case GSGX_IOCTL_ENCLAVE_ADD_PAGES:
+			handler = enclave_add_pages;
+			break;
+		case GSGX_IOCTL_ENCLAVE_INIT:
+			handler = enclave_init;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	if (copy_from_user(data, (void __user *) arg, _IOC_SIZE(cmd)))
+		return -EFAULT;
+
+	ret = handler(filep, (void *) data);
+
+	if (!ret && (cmd & IOC_OUT)) {
+		if (copy_to_user((void __user *) arg, data, _IOC_SIZE(cmd)))
+			return -EFAULT;
+	}
+
+	return ret;
+}
+
+int gsgx_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	return KSYM(isgx_mmap)(file, vma);
+}
+
+unsigned long gsgx_get_unmapped_area(struct file *file, unsigned long addr,
+				     unsigned long len, unsigned long pgoff,
+				     unsigned long flags)
+{
+	if (file->private_data == (void *) GSGX_ENCLAVE_CREATE_NO_ADDR) {
+		unsigned long unmapped_addr =
+			KSYM(isgx_get_unmapped_area)(file, addr, len,
+						     pgoff, flags);
+		file->private_data = (void *) unmapped_addr;
+		return unmapped_addr;
+	} else {
+		unsigned long unmapped_addr = (unsigned long) file->private_data;
+		struct mm_struct *mm = current->mm;
+		struct vm_area_struct *vma = find_vma(mm, unmapped_addr);
+		if (vma && vma->vm_start <= len)
+			return -EINVAL;
+		return unmapped_addr;
+	}
+}
+
+IMPORT_KSYM_PROTO(isgx_ioctl_enclave_create, long,
+	struct file *filep, unsigned int cmd, unsigned long arg);
+IMPORT_KSYM_PROTO(isgx_ioctl_enclave_init, long,
+	struct file *filep, unsigned int cmd, unsigned long arg);
+IMPORT_KSYM_PROTO(isgx_ioctl_enclave_add_page, long,
+	struct file *filep, unsigned int cmd, unsigned long arg);
+
+IMPORT_KSYM(isgx_enclave_release);
+IMPORT_KSYM_PROTO(isgx_mmap, int, struct file *, struct vm_area_struct *);
+IMPORT_KSYM_PROTO(isgx_get_unmapped_area, unsigned long,
+	struct file *, unsigned long, unsigned long,
+	unsigned long, unsigned long);
+
+int gsgx_lookup_ksyms(void)
+{
+	int ret;
+	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_create)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_init)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_add_page)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_enclave_release)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_mmap)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_get_unmapped_area)))
+		return ret;
+	return 0;
+}
+
+#endif /* SGX_DRIVER_VERSION == 1.7 */

+ 173 - 0
Pal/src/host/Linux-SGX/sgx-driver/gsgx_ioctl_1_7.c

@@ -0,0 +1,173 @@
+/*
+ * (C) Copyright 2013 Intel Corporation
+ * Author: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/highmem.h>
+#include <linux/miscdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/security.h>
+#include <asm/tlbflush.h>
+
+#include "gsgx.h"
+
+#if SDK_DRIVER_VERSION == KERNEL_VERSION(1, 7, 0)
+
+struct file *isgx_dev;
+
+static long enclave_create(struct file *filep, void * arg)
+{
+	struct gsgx_enclave_create *createp = arg;
+	struct sgx_enclave_create isgx_create;
+
+	isgx_create.src = createp->src;
+	filep->private_data = (void *) createp->src;
+
+	return KSYM(isgx_ioctl_enclave_create)(filep, SGX_IOC_ENCLAVE_CREATE,
+					       (unsigned long) &isgx_create);
+}
+
+static long enclave_add_pages(struct file *filep, void * arg)
+{
+	struct gsgx_enclave_add_pages *addp = arg;
+	struct sgx_enclave_add_page isgx_add;
+	uint64_t off;
+	int ret = 0;
+
+	if (!addp->addr || (addp->addr & (PAGE_SIZE - 1)))
+		return -EINVAL;
+	if (!addp->size || (addp->size & (PAGE_SIZE - 1)))
+		return -EINVAL;
+	if (!addp->secinfo)
+		return -EINVAL;
+
+	isgx_add.secinfo = addp->secinfo;
+
+	for (off = 0 ; off < addp->size ; off += PAGE_SIZE) {
+		isgx_add.addr = addp->addr + off;
+		isgx_add.src =
+			addp->flags & GSGX_ENCLAVE_ADD_PAGES_REPEAT_SRC ?
+			addp->user_addr : addp->user_addr + off;
+		isgx_add.mrmask =
+			addp->flags & GSGX_ENCLAVE_ADD_PAGES_SKIP_EEXTEND ?
+ 		        0 : ~0;
+		ret = KSYM(isgx_ioctl_enclave_add_page)(filep,
+			SGX_IOC_ENCLAVE_ADD_PAGE, (unsigned long) &isgx_add);
+		if (ret < 0)
+			break;
+	}
+
+	return ret;
+}
+
+static long enclave_init(struct file *filep, void * arg)
+{
+	struct gsgx_enclave_init *initp = arg;
+	struct sgx_enclave_init isgx_init;
+
+	isgx_init.addr = initp->addr;
+	isgx_init.sigstruct = initp->sigstruct;
+	isgx_init.einittoken = initp->einittoken;
+
+	return KSYM(isgx_ioctl_enclave_init)(filep, SGX_IOC_ENCLAVE_INIT,
+					     (unsigned long) &isgx_init);
+}
+
+long gsgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+	char data[256];
+	long (*handler) (struct file *filp, void *arg) = NULL;
+	long ret;
+
+	switch (cmd) {
+		case GSGX_IOCTL_ENCLAVE_CREATE:
+			handler = enclave_create;
+			break;
+		case GSGX_IOCTL_ENCLAVE_ADD_PAGES:
+			handler = enclave_add_pages;
+			break;
+		case GSGX_IOCTL_ENCLAVE_INIT:
+			handler = enclave_init;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	if (copy_from_user(data, (void __user *) arg, _IOC_SIZE(cmd)))
+		return -EFAULT;
+
+	ret = handler(filep, (void *) data);
+
+	if (!ret && (cmd & IOC_OUT)) {
+		if (copy_to_user((void __user *) arg, data, _IOC_SIZE(cmd)))
+			return -EFAULT;
+	}
+
+	return ret;
+}
+
+int gsgx_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	return KSYM(isgx_mmap)(file, vma);
+}
+
+unsigned long gsgx_get_unmapped_area(struct file *file, unsigned long addr,
+				     unsigned long len, unsigned long pgoff,
+				     unsigned long flags)
+{
+	if (file->private_data == (void *) GSGX_ENCLAVE_CREATE_NO_ADDR) {
+		unsigned long unmapped_addr =
+			KSYM(isgx_get_unmapped_area)(file, addr, len,
+						     pgoff, flags);
+		file->private_data = (void *) unmapped_addr;
+		return unmapped_addr;
+	} else {
+		unsigned long unmapped_addr = (unsigned long) file->private_data;
+		struct mm_struct *mm = current->mm;
+		struct vm_area_struct *vma = find_vma(mm, unmapped_addr);
+		if (vma && vma->vm_start <= len)
+			return -EINVAL;
+		return unmapped_addr;
+	}
+}
+
+IMPORT_KSYM_PROTO(isgx_ioctl_enclave_create, long,
+	struct file *filep, unsigned int cmd, unsigned long arg);
+IMPORT_KSYM_PROTO(isgx_ioctl_enclave_init, long,
+	struct file *filep, unsigned int cmd, unsigned long arg);
+IMPORT_KSYM_PROTO(isgx_ioctl_enclave_add_page, long,
+	struct file *filep, unsigned int cmd, unsigned long arg);
+
+IMPORT_KSYM(isgx_enclave_release);
+IMPORT_KSYM_PROTO(isgx_mmap, int, struct file *, struct vm_area_struct *);
+IMPORT_KSYM_PROTO(isgx_get_unmapped_area, unsigned long,
+	struct file *, unsigned long, unsigned long,
+	unsigned long, unsigned long);
+
+int gsgx_lookup_ksyms(void)
+{
+	int ret;
+	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_create)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_init)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_add_page)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_enclave_release)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_mmap)))
+		return ret;
+	if ((ret = LOOKUP_KSYM(isgx_get_unmapped_area)))
+		return ret;
+	return 0;
+}
+
+#endif /* SGX_DRIVER_VERSION == 1.7 */

+ 21 - 208
Pal/src/host/Linux-SGX/sgx-driver/gsgx_main.c

@@ -1,6 +1,6 @@
 /*
- * (C) Copyright 2013 Intel Corporation
- * Author: Jarkko Sakkinen <jarkko.sakkinen@intel.com>
+ * (C) Copyright 2015 Intel Corporation
+ * Author: Chia-Che Tsai <chiache-che.tsai@intel.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -11,178 +11,30 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/version.h>
-#include <linux/highmem.h>
+#include <linux/fs.h>
 #include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-#include <linux/security.h>
-#include <asm/tlbflush.h>
+
 #include "gsgx.h"
 
 #define DRV_DESCRIPTION "Graphene SGX Driver"
-#define DRV_VERSION "0.10"
+#define DRV_VERSION "0.10-" SDK_DRIVER_VERSION_STRING
 
 MODULE_DESCRIPTION(DRV_DESCRIPTION);
 MODULE_AUTHOR("Chia-Che Tsai <chia-che.tsai@intel.com>");
 MODULE_VERSION(DRV_VERSION);
 
-IMPORT_KSYM(dac_mmap_min_addr);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-static void __enable_fsgsbase(void *v)
-{
-	write_cr4(read_cr4() | X86_CR4_FSGSBASE);
-}
-#endif
-
-static long gsgx_ioctl_enclave_create(struct file *filep, unsigned int cmd,
-				      unsigned long arg)
-{
-	struct gsgx_enclave_create *createp = (struct gsgx_enclave_create *) arg;
-	struct sgx_enclave_create isgx_create;
-	unsigned long old_mmap_min_addr = *KSYM(dac_mmap_min_addr);
-	int ret;
-
-	if (createp->src != GSGX_ENCLAVE_CREATE_NO_ADDR &&
-	    createp->src < old_mmap_min_addr) {
-		*KSYM(dac_mmap_min_addr) = createp->src;
-		old_mmap_min_addr = 0;
-	}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0)
-	__enable_fsgsbase(NULL);
-	smp_call_function(__enable_fsgsbase, NULL, 1);
-#endif
-
-	isgx_create.src = createp->src;
-	filep->private_data = (void *) createp->src;
-
-	ret = KSYM(isgx_ioctl_enclave_create)(filep, SGX_IOC_ENCLAVE_CREATE,
-					      (unsigned long) &isgx_create);
-
-	if (old_mmap_min_addr)
-		*KSYM(dac_mmap_min_addr) = old_mmap_min_addr;
-	return ret;
-}
-
-static long gsgx_ioctl_enclave_add_pages(struct file *filep, unsigned int cmd,
-					 unsigned long arg)
-{
-	struct gsgx_enclave_add_pages *addp = (struct gsgx_enclave_add_pages *) arg;
-	struct sgx_enclave_add_page isgx_add;
-	uint64_t off;
-	int ret = 0;
-
-	if (!addp->addr || (addp->addr & (PAGE_SIZE - 1)))
-		return -EINVAL;
-	if (!addp->size || (addp->size & (PAGE_SIZE - 1)))
-		return -EINVAL;
-	if (!addp->secinfo)
-		return -EINVAL;
-
-	isgx_add.secinfo = addp->secinfo;
-
-	for (off = 0 ; off < addp->size ; off += PAGE_SIZE) {
-		isgx_add.addr = addp->addr + off;
-		isgx_add.src =
-			addp->flags & GSGX_ENCLAVE_ADD_PAGES_REPEAT_SRC ?
-			addp->user_addr : addp->user_addr + off;
-		isgx_add.mrmask =
-			addp->flags & GSGX_ENCLAVE_ADD_PAGES_SKIP_EEXTEND ?
- 		        0 : ~0;
-		ret = KSYM(isgx_ioctl_enclave_add_page)(filep,
-			SGX_IOC_ENCLAVE_ADD_PAGE, (unsigned long) &isgx_add);
-		if (ret < 0)
-			break;
-	}
-
-	return ret;
-}
-
-static long gsgx_ioctl_enclave_init(struct file *filep, unsigned int cmd,
-				    unsigned long arg)
-{
-	struct gsgx_enclave_init *initp = (struct gsgx_enclave_init *) arg;
-	struct sgx_enclave_init isgx_init;
-
-	isgx_init.addr = initp->addr;
-	isgx_init.sigstruct = initp->sigstruct;
-	isgx_init.einittoken = initp->einittoken;
-
-	return KSYM(isgx_ioctl_enclave_init)(filep, SGX_IOC_ENCLAVE_INIT,
-					     (unsigned long) &isgx_init);
-}
-
-typedef long (*ioctl_t)(struct file *filep, unsigned int cmd, unsigned long arg);
-
-long gsgx_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
-{
-	char data[256];
-	ioctl_t handler = NULL;
-	long ret;
-
-	switch (cmd) {
-		case GSGX_IOCTL_ENCLAVE_CREATE:
-			handler = gsgx_ioctl_enclave_create;
-			break;
-		case GSGX_IOCTL_ENCLAVE_ADD_PAGES:
-			handler = gsgx_ioctl_enclave_add_pages;
-			break;
-		case GSGX_IOCTL_ENCLAVE_INIT:
-			handler = gsgx_ioctl_enclave_init;
-			break;
-		default:
-			return -EINVAL;
-	}
-
-	if (copy_from_user(data, (void __user *) arg, _IOC_SIZE(cmd)))
-		return -EFAULT;
-
-	ret = handler(filep, cmd, (unsigned long) ((void *) data));
-
-	if (!ret && (cmd & IOC_OUT)) {
-		if (copy_to_user((void __user *) arg, data, _IOC_SIZE(cmd)))
-			return -EFAULT;
-	}
-
-	return ret;
-}
-
-static int gsgx_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	return KSYM(isgx_mmap)(file, vma);
-}
-
-static unsigned long gsgx_get_unmapped_area(struct file *file,
-					    unsigned long addr,
-					    unsigned long len,
-					    unsigned long pgoff,
-					    unsigned long flags)
-{
-	if (file->private_data == (void *) GSGX_ENCLAVE_CREATE_NO_ADDR) {
-		unsigned long unmapped_addr =
-			KSYM(isgx_get_unmapped_area)(file, addr, len,
-						     pgoff, flags);
-		file->private_data = (void *) unmapped_addr;
-		return unmapped_addr;
-	} else {
-		unsigned long unmapped_addr = (unsigned long) file->private_data;
-		struct mm_struct *mm = current->mm;
-		struct vm_area_struct *vma = find_vma(mm, unmapped_addr);
-		if (vma && vma->vm_start <= len)
-			return -EINVAL;
-		return unmapped_addr;
-	}
-}
-
 static const struct file_operations gsgx_fops = {
 	.owner		= THIS_MODULE,
+	.open		= gsgx_open,
+
+#if SDK_DRIVER_VERSION < KERNEL_VERSION(1, 8, 0)
 	.unlocked_ioctl	= gsgx_ioctl,
 #ifdef CONFIG_COMPAT
 	.compat_ioctl	= gsgx_ioctl,
 #endif
 	.mmap		= gsgx_mmap,
 	.get_unmapped_area = gsgx_get_unmapped_area,
+#endif
 };
 
 static struct miscdevice gsgx_dev = {
@@ -192,51 +44,10 @@ static struct miscdevice gsgx_dev = {
 	.mode	= S_IRUGO | S_IWUGO,
 };
 
-IMPORT_KSYM_PROTO(isgx_ioctl_enclave_create, long,
-	struct file *filep, unsigned int cmd, unsigned long arg);
-IMPORT_KSYM_PROTO(isgx_ioctl_enclave_init, long,
-	struct file *filep, unsigned int cmd, unsigned long arg);
-IMPORT_KSYM_PROTO(isgx_ioctl_enclave_add_page, long,
-	struct file *filep, unsigned int cmd, unsigned long arg);
-
-IMPORT_KSYM(isgx_enclave_release);
-IMPORT_KSYM_PROTO(isgx_mmap, int, struct file *, struct vm_area_struct *);
-IMPORT_KSYM_PROTO(isgx_get_unmapped_area, unsigned long,
-	struct file *, unsigned long, unsigned long,
-	unsigned long, unsigned long);
-
-static int gsgx_lookup_ksyms(void)
-{
-	int ret;
-	if ((ret = LOOKUP_KSYM(dac_mmap_min_addr)))
-		return ret;
-	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_create)))
-		return ret;
-	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_init)))
-		return ret;
-	if ((ret = LOOKUP_KSYM(isgx_ioctl_enclave_add_page)))
-		return ret;
-	if ((ret = LOOKUP_KSYM(isgx_enclave_release)))
-		return ret;
-	if ((ret = LOOKUP_KSYM(isgx_mmap)))
-		return ret;
-	if ((ret = LOOKUP_KSYM(isgx_get_unmapped_area)))
-		return ret;
-	return 0;
-}
-
-struct file *isgx_dev;
-
 static int gsgx_setup(void)
 {
-	unsigned cpu;
 	int ret;
 
-	isgx_dev = filp_open("/dev/isgx", O_RDONLY, 0);
-	if (!isgx_dev) {
-		return PTR_ERR(isgx_dev);
-	}
-
 	ret = misc_register(&gsgx_dev);
 	if (ret) {
 		pr_err("gsgx: misc_register() failed\n");
@@ -244,9 +55,16 @@ static int gsgx_setup(void)
 		return ret;
 	}
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
-	for_each_online_cpu(cpu) {
-		per_cpu(cpu_tlbstate.cr4, cpu) |= X86_CR4_FSGSBASE;
+#if SDK_DRIVER_VERSION < KERNEL_VERSION(1, 8, 0)
+	isgx_dev = filp_open("/dev/isgx", O_RDONLY, 0);
+	if (!isgx_dev) {
+		return PTR_ERR(isgx_dev);
+	}
+
+	ret = gsgx_lookup_ksyms();
+	if (ret) {
+		pr_err("gsgx: lookup kernel symbols failed\n");
+		return ret;
 	}
 #endif
 
@@ -258,8 +76,10 @@ static void gsgx_teardown(void)
 	if (gsgx_dev.this_device)
 		misc_deregister(&gsgx_dev);
 
+#if SDK_DRIVER_VERSION < KERNEL_VERSION(1, 8, 0)
 	if (isgx_dev)
 		filp_close(isgx_dev, NULL);
+#endif
 }
 
 static int __init gsgx_init(void)
@@ -268,15 +88,8 @@ static int __init gsgx_init(void)
 
 	pr_info("gsgx: " DRV_DESCRIPTION " v" DRV_VERSION "\n");
 
-	ret = gsgx_lookup_ksyms();
-	if (ret) {
-		pr_err("Likely module \"isgx\" is not loaded\n");
-		return ret;
-	}
-
 	ret = gsgx_setup();
 	if (ret) {
-		pr_err("Likely module \"isgx\" is not loaded\n");
 		gsgx_teardown();
 		return ret;
 	}

+ 7 - 0
Pal/src/host/Linux-SGX/sgx-driver/isgx_ksyms.h

@@ -1,6 +1,11 @@
 #ifndef _ISGX_KSYMS_H
 #define _ISGX_KSYMS_H
 
+#include "isgx_version.h"
+
+#if SDK_DRIVER_VERSION < KERNEL_VERSION(1, 8, 0)
+
+#include "linux-sgx-driver/isgx.h"
 #include "ksyms.h"
 
 extern IMPORT_KSYM_PROTO(isgx_ioctl_enclave_create, long,
@@ -18,3 +23,5 @@ extern IMPORT_KSYM_PROTO(isgx_get_unmapped_area, unsigned long,
 	unsigned long, unsigned long);
 
 #endif
+
+#endif

+ 53 - 12
Pal/src/host/Linux-SGX/sgx-driver/link-intel-driver.py

@@ -1,27 +1,68 @@
 #!/usr/bin/python
 
+import sys, os, re
 
-import sys, os, string, subprocess, shutil, fileinput, multiprocessing, re, resource
+
+isgx_path    = os.getenv("ISGX_DRIVER_PATH")
+isgx_version = os.getenv("ISGX_DRIVER_VERSION")
 
 try:
-    #########################################
-    #### get the locations of directories ###
-    #########################################
+    # get the locations of directories
+    print "\n" + \
+          "*****************************************************************\n" + \
+          "Make sure you have downloaded and installed the Intel sgx driver \n" + \
+          "from https://github.com/01org/linux-sgx-driver.\n" + \
+          "*****************************************************************\n" + \
+          "\n"
+
+    while True:
+        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
 
-    print "Make sure you have downloaded and installed the Intel sgx driver " + \
-          "from https://github.com/01org/linux-sgx-driver."
+
+    # get the driver version
     while True:
-        isgx = raw_input('Enter the Intel sgx driver derctory: ')
-        if os.path.exists(isgx + '/isgx.h'):
+        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
+            break
+        m = re.match('([1-9])\.([0-9]+)', isgx_version)
+        if m:
+            isgx_version_major = m.group(1)
+            isgx_version_minor = m.group(2)
             break
-        print '{0} is not a directory for the Intel sgx driver'.format(isgx)
+        print '{0} is not a valid version (x.xx)'.format(isgx_version)
+        isgx_version = None
+
 
+    # create a symbolic link called 'linux-sgx-driver'
     isgx_link = 'linux-sgx-driver'
-    isgx = os.path.abspath(isgx)
-    print isgx_link + ' -> ' + isgx
+    isgx_path = os.path.abspath(isgx_path)
+    print isgx_link + ' -> ' + isgx_path
     if os.path.exists(isgx_link):
         os.unlink(isgx_link)
-    os.symlink(isgx, isgx_link)
+    os.symlink(isgx_path, isgx_link)
+
+
+    # create isgx_version.h
+    with open('isgx_version.h', 'w') as versionfile:
+        print 'create isgx_version.h'
+        print >> versionfile, '#include <linux/version.h>'
+        print >> versionfile
+        print >> versionfile, '#define SDK_DRIVER_VERSION KERNEL_VERSION(' + \
+                              str(isgx_version_major) + ',' + \
+                              str(isgx_version_minor) + ',0)'
+        print >> versionfile, '#define SDK_DRIVER_VERSION_STRING "' + \
+                              str(isgx_version_major) + '.' + \
+                              str(isgx_version_minor) + '"'
 
 except:
     print 'uh-oh: {0}'.format(sys.exc_info()[0])

+ 0 - 2
Pal/src/host/Linux-SGX/sgx_arch.h

@@ -243,8 +243,6 @@ typedef struct {
 
 typedef uint8_t sgx_arch_key128_t[16] __attribute__((aligned(16)));
 
-#include "sgx-driver/graphene-sgx.h"
-
 #else /* !__ASSEMBLER__ */
 
 /* microcode to call ENCLU */

+ 2 - 2
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;

+ 96 - 54
Pal/src/host/Linux-SGX/sgx_framework.c

@@ -6,7 +6,7 @@
 #include "sgx_internal.h"
 #include "sgx_arch.h"
 #include "sgx_enclave.h"
-#include "sgx-driver/graphene-sgx.h"
+#include "graphene-sgx.h"
 
 #include <asm/errno.h>
 
@@ -18,18 +18,12 @@ void * zero_page;
 
 int open_gsgx(void)
 {
-    int fd = INLINE_SYSCALL(open, 3, GSGX_FILE, O_RDWR, 0);
-    if (IS_ERR(fd))
-        return -ERRNO(fd);
-
-    gsgx_device = fd;
-
-    fd = INLINE_SYSCALL(open, 3, ISGX_FILE, O_RDWR, 0);
-    if (IS_ERR(fd))
-        return -ERRNO(fd);
-
-    isgx_device = fd;
-    
+    gsgx_device = INLINE_SYSCALL(open, 3, GSGX_FILE, O_RDWR, 0);
+    if (IS_ERR(gsgx_device))
+        return -ERRNO(gsgx_device);
+    isgx_device = INLINE_SYSCALL(open, 3, ISGX_FILE, O_RDWR, 0);
+    if (IS_ERR(isgx_device))
+        return -ERRNO(isgx_device);
     return 0;
 }
 
@@ -125,8 +119,6 @@ int create_enclave(sgx_arch_secs_t * secs,
                    sgx_arch_token_t * token)
 {
     int flags = MAP_SHARED;
-    if (gsgx_device == -1)
-        return -EACCES;
 
     if (!zero_page) {
         zero_page = (void *)
@@ -148,7 +140,6 @@ int create_enclave(sgx_arch_secs_t * secs,
     memcpy(&secs->mrenclave, &token->mrenclave, sizeof(sgx_arch_hash_t));
     memcpy(&secs->mrsigner,  &token->mrsigner,  sizeof(sgx_arch_hash_t));
 
-    struct gsgx_enclave_create param;
     if (baseaddr) {
         secs->baseaddr = (uint64_t) baseaddr & ~(secs->size - 1);
         flags |= MAP_FIXED;
@@ -156,7 +147,7 @@ int create_enclave(sgx_arch_secs_t * secs,
         secs->baseaddr = 0ULL;
     }
 
-    uint64_t addr = INLINE_SYSCALL(mmap, 6, secs->baseaddr, size,
+    uint64_t addr = INLINE_SYSCALL(mmap, 6, secs->baseaddr, secs->size,
                                    PROT_READ|PROT_WRITE|PROT_EXEC, flags,
                                    isgx_device, 0);
 
@@ -171,13 +162,22 @@ int create_enclave(sgx_arch_secs_t * secs,
     }
 
     secs->baseaddr = addr;
-    param.src = (uint64_t) secs;
+
+#if SDK_DRIVER_VERSION >= KERNEL_VERSION(1, 8, 0)
+    struct sgx_enclave_create param = {
+        .src = (uint64_t) secs,
+    };
+    int ret = INLINE_SYSCALL(ioctl, 3, isgx_device, SGX_IOC_ENCLAVE_CREATE,
+                         &param);
+#else
+    struct gsgx_enclave_create param = {
+        .src = (uint64_t) secs,
+    };
     int ret = INLINE_SYSCALL(ioctl, 3, gsgx_device, GSGX_IOCTL_ENCLAVE_CREATE,
                          &param);
-    
+#endif
+
     if (IS_ERR(ret)) {
-        if (ERRNO(ret) == EBADF)
-            gsgx_device = -1;
         SGX_DBG(DBG_I, "enclave ECREATE failed in enclave creation ioctl - %d\n", ERRNO(ret));
         return -ERRNO(ret);
     }
@@ -208,11 +208,8 @@ int add_pages_to_enclave(sgx_arch_secs_t * secs,
                          bool skip_eextend,
                          const char * comment)
 {
-    if (gsgx_device == -1)
-        return -EACCES;
-
-    struct gsgx_enclave_add_pages param;
     sgx_arch_secinfo_t secinfo;
+    int ret;
 
     memset(&secinfo, 0, sizeof(sgx_arch_secinfo_t));
 
@@ -233,17 +230,6 @@ int add_pages_to_enclave(sgx_arch_secs_t * secs,
             break;
     }
 
-    param.addr = secs->baseaddr + (uint64_t) addr;
-    param.user_addr = (uint64_t) user_addr;
-    param.size = size;
-    param.secinfo = (uint64_t) &secinfo;
-    param.flags = skip_eextend ? GSGX_ENCLAVE_ADD_PAGES_SKIP_EEXTEND : 0;
-
-    if (!param.user_addr) {
-        param.user_addr = (unsigned long) zero_page;
-        param.flags |= GSGX_ENCLAVE_ADD_PAGES_REPEAT_SRC;
-    }
-
     char p[4] = "---";
     const char * t = (type == SGX_PAGE_TCS) ? "TCS" : "REG";
     const char * m = skip_eextend ? "" : " measured";
@@ -265,15 +251,49 @@ int add_pages_to_enclave(sgx_arch_secs_t * secs,
                 addr, addr + size, t, p, comment, m);
 
 
-    int ret = INLINE_SYSCALL(ioctl, 3, gsgx_device,
-                             GSGX_IOCTL_ENCLAVE_ADD_PAGES,
-                             &param);
+#if SDK_DRIVER_VERSION >= KERNEL_VERSION(1, 8, 0)
+    struct sgx_enclave_add_page param = {
+        .addr       = secs->baseaddr + (uint64_t) addr,
+        .src        = (uint64_t) (user_addr ? : zero_page),
+        .secinfo    = (uint64_t) &secinfo,
+        .mrmask     = skip_eextend ? 0 : (uint16_t) -1,
+    };
+
+    uint64_t added_size = 0;
+    while (added_size < size) {
+        ret = INLINE_SYSCALL(ioctl, 3, isgx_device,
+                             SGX_IOC_ENCLAVE_ADD_PAGE, &param);
+        if (IS_ERR(ret)) {
+            SGX_DBG(DBG_I, "Enclave add page returned %d\n", ret);
+            return -ERRNO(ret);
+        }
+
+        param.addr += pagesize;
+        if (param.src != (uint64_t) zero_page) param.src += pagesize;
+        added_size += pagesize;
+    }
+#else
+    struct gsgx_enclave_add_pages param = {
+        .addr       = secs->baseaddr + (uint64_t) addr,
+        .user_addr  = (uint64_t) user_addr,
+        .size       = size,
+        .secinfo    = (uint64_t) &secinfo,
+        .flags      = skip_eextend ? GSGX_ENCLAVE_ADD_PAGES_SKIP_EEXTEND : 0,
+    };
+
+    if (!user_addr) {
+        param.user_addr = (unsigned long) zero_page;
+        param.flags |= GSGX_ENCLAVE_ADD_PAGES_REPEAT_SRC;
+    }
+
+    ret = INLINE_SYSCALL(ioctl, 3, gsgx_device,
+                         GSGX_IOCTL_ENCLAVE_ADD_PAGES,
+                         &param);
     if (IS_ERR(ret)) {
         SGX_DBG(DBG_I, "Enclave add page returned %d\n", ret);
-        if (ERRNO(ret) == EBADF)
-            gsgx_device = -1;
         return -ERRNO(ret);
     }
+#endif
 
     return 0;
 }
@@ -282,9 +302,6 @@ int init_enclave(sgx_arch_secs_t * secs,
                  sgx_arch_sigstruct_t * sigstruct,
                  sgx_arch_token_t * token)
 {
-    if (gsgx_device == -1)
-        return -EACCES;
-
     unsigned long enclave_valid_addr =
                 secs->baseaddr + secs->size - pagesize;
 
@@ -295,23 +312,48 @@ int init_enclave(sgx_arch_secs_t * secs,
         SGX_DBG(DBG_I, " %02x", sigstruct->enclave_hash[i]);
     SGX_DBG(DBG_I, "\n");
 
-    struct gsgx_enclave_init param;
-    param.addr = enclave_valid_addr;
-    // DEP 11/6/16: I think sigstruct and token are supposed to
-    //              be pointers in the new driver
-    param.sigstruct = (uint64_t) sigstruct;
-    param.einittoken = (uint64_t) token;
-
+#if SDK_DRIVER_VERSION >= KERNEL_VERSION(1, 8, 0)
+    struct sgx_enclave_init param = {
+        .addr           = enclave_valid_addr,
+        .sigstruct      = (uint64_t) sigstruct,
+        .einittoken     = (uint64_t) token,
+    };
+    int ret = INLINE_SYSCALL(ioctl, 3, isgx_device, SGX_IOC_ENCLAVE_INIT,
+                             &param);
+#else
+    struct gsgx_enclave_init param = {
+        .addr           = enclave_valid_addr,
+        .sigstruct      = (uint64_t) sigstruct,
+        .einittoken     = (uint64_t) token,
+    };
     int ret = INLINE_SYSCALL(ioctl, 3, gsgx_device, GSGX_IOCTL_ENCLAVE_INIT,
                              &param);
+#endif
+
     if (IS_ERR(ret)) {
-        if (ERRNO(ret) == EBADF)
-            gsgx_device = -1;
         return -ERRNO(ret);
     }
 
     if (ret) {
-        SGX_DBG(DBG_I, "enclave EINIT failed\n");
+        const char * error;
+        /* DEP 3/22/17: Try to improve error messages */
+        switch(ret) {
+        case SGX_INVALID_SIG_STRUCT:
+            error = "Invalid SIGSTRUCT";          break;
+        case SGX_INVALID_ATTRIBUTE:
+            error = "Invalid enclave attribute";  break;
+        case SGX_INVALID_MEASUREMENT:
+            error = "Invalid measurement";        break;
+        case SGX_INVALID_SIGNATURE:
+            error = "Invalid signature";          break;
+        case SGX_INVALID_LICENSE:
+            error = "Invalid EINIT token";        break;
+        case SGX_INVALID_CPUSVN:
+            error = "Invalid CPU SVN";            break;
+        default:
+            error = "Unknown reason";             break;
+        }
+        SGX_DBG(DBG_I, "enclave EINIT failed - %s\n", error);
         return -EPERM;
     }
 

+ 20 - 1
Pal/src/host/Linux-SGX/signer/pal-sgx-get-token

@@ -67,7 +67,26 @@ def connect_aesmd(attr):
     req_msg_raw = req_msg.SerializeToString()
 
     aesm_service = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
-    aesm_service.connect("\0sgx_aesm_socket_base" + "\0" * 87)
+    connected = False
+
+    # try to connect to the unnamed socket (for PSW 1.6 and 1.7)
+    if not connected:
+        try:
+            aesm_service.connect("\0sgx_aesm_socket_base" + "\0" * 87)
+            connected = True
+        except socket.error:
+            pass
+
+    # try to connect to the named socket (for PSW 1.8+)
+    if not connected:
+        try:
+            aesm_service.connect("/var/run/aesmd/aesm.socket")
+            connected = True
+        except socket.error:
+            pass
+
+    if not connected:
+        raise socket.error("Cannot connect to the AESMD service")
 
     aesm_service.send(struct.pack("<I", len(req_msg_raw)))
     aesm_service.send(req_msg_raw)

+ 1 - 1
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;
 

+ 3 - 3
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));
 

+ 1 - 1
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

+ 2 - 2
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)

+ 0 - 1
Pal/src/host/Linux/db_rtld.c

@@ -39,7 +39,6 @@
 
 #include <sysdeps/generic/ldsodefs.h>
 #include <elf/elf.h>
-#include <bits/dlfcn.h>
 
 #include "elf-x86_64.h"
 

+ 3 - 3
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 */

+ 1 - 1
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,

+ 3 - 1
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);

+ 7 - 6
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 */

+ 0 - 1
Pal/src/pal_rtld.h

@@ -30,7 +30,6 @@
 
 #include <sysdeps/generic/ldsodefs.h>
 #include <elf/elf.h>
-#include <bits/dlfcn.h>
 
 #ifndef DT_THISPROCNUM
 # define DT_THISPROCNUM 0

+ 0 - 63
Pal/test/test.c

@@ -1,63 +0,0 @@
-#include <stdio.h>            // printf 
-#include <string.h>           // strerror
-#include <errno.h>            // errno
-#include <unistd.h>           // execl
-#include <sys/ptrace.h>       // ptrace
-#include <sys/user.h>         // user_regs_struct
-#include <sys/personality.h>  // personality
-#include <sys/wait.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-int
-main(int argc, char *argv[], char *envp[]) {
-
-	// create a child process
-	int pid = fork();
-
-	// if error occurs
-	if (0 > pid) {
-	printf("Error during forking: %s\n", strerror(errno));
-	return 1;
-	}
-
-	// child process
-	if (0 == pid) {
-		ptrace(PTRACE_TRACEME, 0, 0, 0);
-		personality(ADDR_NO_RANDOMIZE);
-		execve(argv[1], &(argv[1]), envp);
-	}
-
-	// parent process
-	int status;
-	struct user_regs_struct regs;
-	int n;
-
-	wait(&status);
-	if(1407 == status) {
-		char infilename[128], line[256], out[256];
-		char* outfilename = "/tmp/pal_range";
-		int mapfd, ret, outfd;
-		unsigned long vas;
-		unsigned long vae;
-
-		sprintf(infilename, "/proc/%d/maps",pid);
-		while((mapfd = open(infilename,O_RDONLY)) == -1);
-		read(mapfd, &line, 256);
-
-		/*scan for the virtual addresses*/
-		n = sscanf(line, "%lX-%lX r-xp", &vas, &vae);
-		if(n == 2)
-		{
-			outfd = open(outfilename, O_WRONLY|O_CREAT, S_IRUSR);
-			memset(out,0,256);
-			sprintf(out,"%lX,%lX\n", vas, vae);
-			write(outfd, out, 256);
-			close(outfd);
-		}
-		close(mapfd);
-	}
-	kill(pid,SIGKILL);
-	return 0;
-}

Some files were not shown because too many files changed in this diff