Browse Source

Lots of bugfixes (#145)

- Fix a severe bug caused by merging #87. The patch does not check the return values from get_config_entries_size(), while the return values can easily be negative (-PAL_ERROR_INVAL). Any usage of this function should carefully check the return values and also pass the size into get_config_entries() to prevent buffer overflow.
- Fix a minor bug in handling IPC disconnection. The callback ipc_child_exit() never receives a "term_signal" parameter. The callback is called when thepipe to a child process unexpectedly terminates, which can only mean the child process has crashed. I believe the proper signal to send is SIGKILL.
- Remove a compilation warning caused by type mismatch of __malloc().
- Allow binding TCP socket to ANY address
- enable LD_PRELOAD in glibc
- disable output buffering in LTP tests to reveal omitted passes
- Remove a double-unlock in shim_async.c
- Replace all int with size_t or ssize_t in Graphene configuration API
- Add new passed LTP tests
Chia-Che Tsai 5 years ago
parent
commit
84f81d8f13

+ 4 - 56
LibOS/glibc-2.19.patch

@@ -664,41 +664,10 @@ index 6dcbabc..c87c773 100644
    LIBC_PROBE (init_start, 2, LM_ID_BASE, r);
  
    /* Auditing checkpoint: we are ready to signal that the initial map
-@@ -1605,140 +1654,11 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
+@@ -1636,89 +1654,6 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
  	}
      }
  
--  /* We have two ways to specify objects to preload: via environment
--     variable and via the file /etc/ld.so.preload.  The latter can also
--     be used when security is enabled.  */
--  assert (*first_preload == NULL);
--  struct link_map **preloads = NULL;
--  unsigned int npreloads = 0;
--
--  if (__builtin_expect (preloadlist != NULL, 0))
--    {
--      /* The LD_PRELOAD environment variable gives list of libraries
--	 separated by white space or colons that are loaded before the
--	 executable's dependencies and prepended to the global scope
--	 list.  If the binary is running setuid all elements
--	 containing a '/' are ignored since it is insecure.  */
--      char *list = strdupa (preloadlist);
--      char *p;
--
--      HP_TIMING_NOW (start);
--
--      /* Prevent optimizing strsep.  Speed is not important here.  */
--      while ((p = (strsep) (&list, " :")) != NULL)
--	if (p[0] != '\0'
--	    && (__builtin_expect (! INTUSE(__libc_enable_secure), 1)
--		|| strchr (p, '/') == NULL))
--	  npreloads += do_preload (p, main_map, "LD_PRELOAD");
--
--      HP_TIMING_NOW (stop);
--      HP_TIMING_DIFF (diff, start, stop);
--      HP_TIMING_ACCUM_NT (load_time, diff);
--    }
--
 -  /* There usually is no ld.so.preload file, it should only be used
 -     for emergencies and testing.  So the open call etc should usually
 -     fail.  Using access() on a non-existing file is faster than using
@@ -782,30 +751,9 @@ index 6dcbabc..c87c773 100644
 -	  __munmap (file, file_size);
 -	}
 -    }
--
--  if (__builtin_expect (*first_preload != NULL, 0))
--    {
--      /* Set up PRELOADS with a vector of the preloaded libraries.  */
--      struct link_map *l = *first_preload;
--      preloads = __alloca (npreloads * sizeof preloads[0]);
--      i = 0;
--      do
--	{
--	  preloads[i++] = l;
--	  l = l->l_next;
--	} while (l);
--      assert (i == npreloads);
--    }
--
-   /* Load all the libraries specified by DT_NEEDED entries.  If LD_PRELOAD
-      specified some libraries to load, these are inserted before the actual
-      dependencies in the executable's searchlist for symbol resolution.  */
-   HP_TIMING_NOW (start);
--  _dl_map_object_deps (main_map, preloads, npreloads, mode == trace, 0);
-+  _dl_map_object_deps (main_map, NULL, 0, mode == trace, 0);
-   HP_TIMING_NOW (stop);
-   HP_TIMING_DIFF (diff, start, stop);
-   HP_TIMING_ACCUM_NT (load_time, diff);
+
+  if (__builtin_expect (*first_preload != NULL, 0))
+    {
 @@ -2301,7 +2221,7 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
       the address since by now the variable might be in another object.  */
    r = _dl_debug_initialize (0, LM_ID_BASE);

+ 2 - 2
LibOS/shim/include/shim_ipc.h

@@ -600,9 +600,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 term_signal);
+                       unsigned int exitcode);
 void ipc_child_exit   (struct shim_ipc_port * port, IDTYPE vmid,
-                       unsigned int exitcode, unsigned int term_signal);
+                       unsigned int exitcode);
 
 int exit_with_ipc_helper (bool handover);
 

+ 6 - 2
LibOS/shim/src/fs/shim_fs.c

@@ -192,9 +192,13 @@ static int __mount_others (void)
         return 0;
 
     int nkeys;
-    char * keybuf = __alloca(get_config_entries_size(root_config, "fs.mount"));
+    ssize_t keybuf_size;
+    keybuf_size = get_config_entries_size(root_config, "fs.mount");
+    if (keybuf_size < 0)
+        return 0;
 
-    nkeys = get_config_entries(root_config, "fs.mount", keybuf);
+    char * keybuf = __alloca(keybuf_size);
+    nkeys = get_config_entries(root_config, "fs.mount", keybuf, keybuf_size);
 
     if (nkeys < 0)
         return 0;

+ 10 - 3
LibOS/shim/src/ipc/shim_ipc_child.c

@@ -82,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 term_signal)
+                      unsigned int exitcode)
 {
     debug("ipc port %p of process %u closed suggests parent exiting\n",
           port, vmid);
@@ -159,12 +159,19 @@ int remove_child_thread (IDTYPE vmid, unsigned int exitcode, unsigned int term_s
 }
 
 void ipc_child_exit (struct shim_ipc_port * port, IDTYPE vmid,
-                     unsigned int exitcode, unsigned int term_signal)
+                     unsigned int exitcode)
 {
     debug("ipc port %p of process %u closed suggests child exiting\n",
           port, vmid);
 
-    remove_child_thread(vmid, 0, term_signal);
+    /*
+     * Chia-Che 12/12/2017:
+     * Can't assume there is a termination signal. this callback
+     * is only called when the child process is not responding, and
+     * under this circumstance can only assume the child process
+     * has encountered severe failure, hence SIGKILL.
+     */
+    remove_child_thread(vmid, exitcode, SIGKILL);
 }
 
 static struct shim_ipc_port * get_parent_port (IDTYPE * dest)

+ 1 - 3
LibOS/shim/src/shim_async.c

@@ -108,10 +108,8 @@ uint64_t install_async_event (PAL_HANDLE object, unsigned long time,
         free(event);
     else
         listp_add_tail(event, &async_list, list);   
-    
-    unlock(async_helper_lock);
 
-    if (atomic_read(&async_helper_state) == HELPER_NOTALIVE)
+    if (async_helper_state == HELPER_NOTALIVE)
         create_async_helper();
 
     unlock(async_helper_lock);

+ 3 - 3
LibOS/shim/src/shim_init.c

@@ -154,8 +154,8 @@ long int glibc_option (const char * opt)
     char cfg[CONFIG_MAX];
 
     if (strcmp_static(opt, "heap_size")) {
-        int ret = get_config(root_config, "glibc.heap_size", cfg, CONFIG_MAX);
-        if (ret < 0) {
+        ssize_t ret = get_config(root_config, "glibc.heap_size", cfg, CONFIG_MAX);
+        if (ret <= 0) {
             debug("no glibc option: %s (err=%d)\n", opt, ret);
             return -ENOENT;
         }
@@ -433,7 +433,7 @@ int read_environs (const char ** envp)
 
 struct config_store * root_config = NULL;
 
-static void * __malloc (int size)
+static void * __malloc (size_t size)
 {
     return malloc(size);
 }

+ 21 - 13
LibOS/shim/src/sys/shim_sandbox.c

@@ -72,11 +72,16 @@ static int isolate_fs (struct config_store * cfg, const char * path)
     char * dpath = dentry_get_path(dent, true, &dpath_len);
     bool root_created = false;
     char t[CONFIG_MAX], u[CONFIG_MAX];
+    ssize_t prefix_len;
 
     int nkeys;
-    char * keybuf = __alloca(get_config_entries_size(cfg, "fs.mount.other"));
+    ssize_t keybuf_size;
+    keybuf_size = get_config_entries_size(cfg, "fs.mount.other");
+    if (keybuf_size <= 0)
+        goto root;
 
-    nkeys = get_config_entries(cfg, "fs.mount.other", keybuf);
+    char * keybuf = __alloca(keybuf_size);
+    nkeys = get_config_entries(cfg, "fs.mount.other", keybuf, keybuf_size);
 
     if (nkeys <= 0)
         goto root;
@@ -88,15 +93,15 @@ static int isolate_fs (struct config_store * cfg, const char * path)
     for (int n = 0 ; n < nkeys ; key = next, n++) {
         for (next = key ; *next ; next++);
         next++;
-        int key_len = next - key - 1;
+        size_t key_len = next - key - 1;
         memcpy(tmp, key, key_len);
         char * kp = tmp + key_len;
-        int ulen, plen;
+        ssize_t ulen, plen;
         bool is_chroot = false;
 
         /* Skip FS that are not chroot */
         strcpy_static(kp, ".type", k + CONFIG_MAX - kp);
-        if ((ret = get_config(cfg, k, t, CONFIG_MAX)) <= 0)
+        if (get_config(cfg, k, t, CONFIG_MAX) <= 0)
             continue;
         if (strpartcmp_static(t, "chroot"))
             is_chroot = true;
@@ -156,10 +161,8 @@ remove:
     }
 
 root:
-    if ((ret = get_config(cfg, "fs.mount.root.uri", u, CONFIG_MAX)) > 0) {
-        int prefix_len = ret;
-
-        if ((ret = get_config(cfg, "fs.mount.root.type", t, CONFIG_MAX)) > 0 &&
+    if ((prefix_len = get_config(cfg, "fs.mount.root.uri", u, CONFIG_MAX)) > 0) {
+        if (get_config(cfg, "fs.mount.root.type", t, CONFIG_MAX) > 0 &&
             strcmp_static(t, "chroot")) {
             /* remove the root FS */
             set_config(cfg, "fs.mount.root.uri",  NULL);
@@ -184,10 +187,15 @@ root:
 static int isolate_net (struct config_store * cfg, struct net_sb * sb)
 {
     int nkeys;
-    char k[CONFIG_MAX];
-    char * keybuf = __alloca(get_config_entries_size(cfg, "net.rules"));
+    ssize_t keybuf_size;
+    char k[CONFIG_MAX], * keybuf;
+
+    keybuf_size = get_config_entries_size(cfg, "net.rules");
+    if (keybuf_size <= 0)
+        goto add;
 
-    nkeys = get_config_entries(cfg, "net.rules", keybuf);
+    keybuf = __alloca(keybuf_size);
+    nkeys = get_config_entries(cfg, "net.rules", keybuf, keybuf_size);
 
     if (nkeys <= 0)
         goto add;
@@ -277,7 +285,7 @@ next:
     return 0;
 }
 
-static void * __malloc (int size)
+static void * __malloc (size_t size)
 {
     return malloc(size);
 }

+ 2 - 2
LibOS/shim/src/sys/shim_socket.c

@@ -838,8 +838,8 @@ int __do_accept (struct shim_handle * hdl, int flags, struct sockaddr * addr,
     PAL_HANDLE accepted = NULL;
 
     if (sock->sock_type != SOCK_STREAM) {
-        debug("shim_listen: not a stream socket\n");
-        return -EINVAL;
+        debug("shim_accept: not a stream socket\n");
+        return -EOPNOTSUPP;
     }
 
     lock(hdl->lock);

+ 36 - 0
LibOS/shim/test/apps/ltp/PASSED

@@ -1,6 +1,11 @@
 Test,Subtest number
 accept01,1
 accept01,2
+accept01,3
+accept01,4
+accept01,5
+accept01,6
+accept01,7
 accept4_01,1
 accept4_01,2
 accept4_01,3
@@ -20,6 +25,7 @@ asyncio02,5
 asyncio02,6
 brk01,1
 chdir01,1
+chdir02,1
 chmod01,1
 chmod01,2
 chmod01,3
@@ -78,6 +84,7 @@ confstr01,16
 confstr01,17
 confstr01,18
 confstr01,19
+connect01,1
 creat01,2
 creat01,3
 creat01,4
@@ -88,8 +95,12 @@ creat03,3
 dup01,1
 dup02,1
 dup02,2
+dup04,1
+dup04,2
 dup07,1
 dup07,2
+dup201,1
+dup201,2
 dup202,1
 dup202,2
 dup203,1
@@ -233,6 +244,8 @@ getitimer01,5
 getpagesize01,1
 getpeername01,1
 getpeername01,2
+getpeername01,3
+getpeername01,4
 getpgid01,1
 getpgid01,2
 getpgrp01,1
@@ -245,8 +258,14 @@ getrlimit01,6
 getrlimit01,8
 getrlimit01,10
 getsid01,1
+getsockname01,3
+getsockname01,4
 getsockopt01,1
 getsockopt01,2
+getsockopt01,3
+getsockopt01,4
+getsockopt01,8
+getsockopt01,9
 gettid01,1
 getuid01,1
 getuid03,1
@@ -321,6 +340,7 @@ nanosleep03,1
 newuname01,1
 open01,2
 open03,1
+open08,1
 open09,1
 open09,2
 pathconf01,1
@@ -392,6 +412,12 @@ read04,1
 readdir01,1
 readv01,1
 readv01,2
+recv01,1
+recv01,2
+recvfrom01,1
+recvfrom01,2
+recvmsg01,1
+recvmsg01,2
 rmdir01,1
 rmdir04,1
 rt_sigaction01,1
@@ -721,6 +747,8 @@ semget03,1
 semop01,1
 semop04,1
 semop04,2
+send01,1
+send01,2
 sendfile03,1
 sendfile03,2
 sendfile03,3
@@ -728,6 +756,9 @@ sendfile03_64,1
 sendfile03_64,2
 sendfile03_64,3
 sendfile05_64,1
+sendto01,1
+sendto01,2
+sendto01,3
 setgid01,1
 setitimer01,1
 setpgid01,1
@@ -737,6 +768,11 @@ setpgrp02,1
 setrlimit01,1
 setsockopt01,1
 setsockopt01,2
+setsockopt01,3
+setsockopt01,5
+setsockopt01,6
+setsockopt01,7
+setsockopt01,8
 set_tid_address01,1
 settimeofday01,3
 setuid01,1

+ 3 - 0
LibOS/shim/test/apps/ltp/manifest.template

@@ -1,6 +1,8 @@
 loader.preload = file:$(SHIMPATH)
 loader.env.LD_LIBRARY_PATH = /lib:/lib/x86_64-linux-gnu:/usr/lib:/usr/lib64
 loader.env.PATH = /bin:/usr/bin:.
+loader.env.LD_PRELOAD = /usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so
+loader.env._STDBUF_O = L
 loader.debug_type = none
 
 fs.mount.shm.type = chroot
@@ -31,5 +33,6 @@ 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.trusted_files.libstdbuf = file:/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so
 
 sgx.allowed_files.tmp = file:/tmp

+ 2 - 1
LibOS/shim/test/native/tcp.c

@@ -15,6 +15,7 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 
+#define SRV_BIND_IP "0.0.0.0"
 #define SRV_IP "127.0.0.1"
 #define PORT 9930
 #define BUFLEN 512
@@ -38,7 +39,7 @@ int server(void)
         printf("The socket was created\n");
 
     address.sin_family = AF_INET;
-    inet_pton(AF_INET, SRV_IP, &(address.sin_addr));
+    inet_pton(AF_INET, SRV_BIND_IP, &(address.sin_addr));
     address.sin_port = htons(PORT);
 
     if (bind(create_socket, (struct sockaddr *) &address,

+ 9 - 4
Pal/lib/api.h

@@ -24,6 +24,11 @@
 #include <stdint.h>
 #include <stdarg.h>
 
+/* WARNING: this declaration may conflict with some header files */
+#ifndef ssize_t
+typedef ptrdiff_t ssize_t;
+#endif
+
 /* Macros */
 
 #ifndef likely
@@ -129,11 +134,11 @@ int free_config (struct config_store * store);
 int copy_config (struct config_store * store, struct config_store * new_store);
 int write_config (void * file, int (*write) (void *, void *, int),
                   struct config_store * store);
-int get_config (struct config_store * cfg, const char * key,
-                char * val_buf, int size);
+ssize_t get_config (struct config_store * cfg, const char * key,
+                    char * val_buf, size_t size);
 int get_config_entries (struct config_store * cfg, const char * key,
-                        char * key_buf);
-int get_config_entries_size (struct config_store * cfg, const char * key);
+                        char * key_buf, size_t key_bufsize);
+ssize_t get_config_entries_size (struct config_store * cfg, const char * key);
 int set_config (struct config_store * cfg, const char * key, const char * val);
 
 #define CONFIG_MAX      4096

+ 17 - 12
Pal/lib/graphene/config.c

@@ -31,8 +31,10 @@
 DEFINE_LIST(config);
 struct config {
     const char * key, * val;
-    int klen, vlen;
-    int entries_size;
+    size_t klen, vlen; /* for leaf nodes, vlen stores the size of config
+                          values; for branch nodes, vlen stores the sum
+                          of config value lengths plus one of all the
+                          immediate children. */
     char * buf;
     LIST_TYPE(config) list;
     LISTP_TYPE(config) children;
@@ -53,7 +55,7 @@ static int __add_config (struct config_store * store,
             return -PAL_ERROR_INVAL;
 
         const char * token = key;
-        int len = 0;
+        size_t len = 0;
         for ( ; len < klen ; len++)
             if (token[len] == '.')
                 break;
@@ -71,14 +73,13 @@ static int __add_config (struct config_store * store,
         e->val  = NULL;
         e->vlen = 0;
         e->buf  = NULL;
-        e->entries_size = 0;
         INIT_LIST_HEAD(e, list);
         listp_add_tail(e, &store->entries, list);
         INIT_LISTP(&e->children);
         INIT_LIST_HEAD(e, siblings);
         listp_add_tail(e, list, siblings);
         if (parent)
-            parent->entries_size += (len + 1);
+            parent->vlen += (len + 1);
 
 next:
         if (len < klen)
@@ -130,8 +131,8 @@ next:
     return e;
 }
 
-int get_config (struct config_store * store, const char * key,
-                char * val_buf, int size)
+ssize_t get_config (struct config_store * store, const char * key,
+                    char * val_buf, size_t size)
 {
     struct config * e = __get_config(store, key);
 
@@ -147,7 +148,7 @@ int get_config (struct config_store * store, const char * key,
 }
 
 int get_config_entries (struct config_store * store, const char * key,
-                        char * key_buf)
+                        char * key_buf, size_t key_bufsize)
 {
     struct config * e = __get_config(store, key);
 
@@ -158,22 +159,27 @@ int get_config_entries (struct config_store * store, const char * key,
     int nentries = 0;
 
     listp_for_each_entry(e, children, siblings) {
+        if (e->klen + 1 > key_bufsize)
+            return -PAL_ERROR_TOOLONG;
         memcpy(key_buf, e->key, e->klen);
         key_buf[e->klen] = 0;
         key_buf += e->klen + 1;
+        key_bufsize -= e->klen + 1;
         nentries++;
     }
 
     return nentries;
 }
-int get_config_entries_size (struct config_store * store, const char * key)
+
+ssize_t get_config_entries_size (struct config_store * store,
+                                 const char * key)
 {
     struct config * e = __get_config(store, key);
 
     if (!e || e->val)
         return -PAL_ERROR_INVAL;
 
-    return e->entries_size;
+    return e->vlen;
 }
 
 static int __del_config (struct config_store * store,
@@ -209,7 +215,7 @@ static int __del_config (struct config_store * store,
     }
 
     if (p)
-        p->entries_size -= (found->klen + 1);
+        p->vlen -= (found->klen + 1);
     listp_del(found, root, siblings);
     listp_del(found, &store->entries, list);
     if (found->buf)
@@ -433,7 +439,6 @@ static int __dup_config (const struct config_store * ss,
         new->val  = val;
         new->vlen = e->vlen;
         new->buf  = buf;
-        new->entries_size = e->entries_size;
         INIT_LIST_HEAD(new, list);
         listp_add_tail(new, &ts->entries, list);
         INIT_LISTP(&new->children);

+ 14 - 11
Pal/src/db_main.c

@@ -47,7 +47,7 @@ static void load_libraries (void)
 {
     /* we will not make any assumption for where the libraries are loaded */
     char cfgbuf[CONFIG_MAX];
-    int len, ret = 0;
+    ssize_t len, ret = 0;
 
     /* loader.preload:
        any other libraries to preload. The can be multiple URIs,
@@ -84,6 +84,7 @@ static void load_libraries (void)
 
 static void read_environments (const char *** envpp)
 {
+    struct config_store * store = pal_state.root_config;
     const char ** envp = *envpp;
     char * cfgbuf;
 
@@ -97,10 +98,13 @@ static void read_environments (const char *** envpp)
     if (!pal_state.root_config)
         return;
 
-    cfgbuf = malloc(get_config_entries_size(pal_state.root_config,
-                                            "loader.env"));
-    nsetenvs = get_config_entries(pal_state.root_config, "loader.env",
-                                  cfgbuf);
+    ssize_t cfgsize = get_config_entries_size(store, "loader.env");
+    if (cfgsize < 0)
+        return;
+
+    cfgbuf = malloc(cfgsize);
+    assert(cfgbuf);
+    nsetenvs = get_config_entries(store, "loader.env", cfgbuf, cfgsize);
 
     if (nsetenvs <= 0) {
         free(cfgbuf);
@@ -110,7 +114,7 @@ static void read_environments (const char *** envpp)
     setenvs = __alloca(sizeof(struct setenv) * nsetenvs);
     char * cfg = cfgbuf;
     for (int i = 0 ; i < nsetenvs ; i++) {
-        int len = strlen(cfg);
+        size_t len = strlen(cfg);
         char * str = __alloca(len + 1);
         setenvs[i].str = str;
         setenvs[i].len = len;
@@ -147,11 +151,10 @@ static void read_environments (const char *** envpp)
         const char * str = setenvs[i].str;
         int len = setenvs[i].len;
         int idx = setenvs[i].idx;
-        int bytes;
+        ssize_t bytes;
         ptr = &envp[(idx == -1) ? nenvs++ : idx];
         memcpy(key + prefix_len, str, len + 1);
-        if ((bytes = get_config(pal_state.root_config, key, cfgbuf,
-                                CONFIG_MAX)) > 0) {
+        if ((bytes = get_config(store, key, cfgbuf, CONFIG_MAX)) > 0) {
             char * e = malloc(len + bytes + 2);
             memcpy(e, str, len);
             e[len] = '=';
@@ -172,7 +175,7 @@ static void read_environments (const char *** envpp)
 static void set_debug_type (void)
 {
     char cfgbuf[CONFIG_MAX];
-    int ret = 0;
+    ssize_t ret = 0;
 
     if (!pal_state.root_config)
         return;
@@ -255,7 +258,7 @@ void pal_main (
 
     char uri_buf[URI_MAX];
     char * manifest_uri = NULL, * exec_uri = NULL;
-    int ret;
+    ssize_t ret;
 
     if (exec_handle) {
         ret = _DkStreamGetName(exec_handle, uri_buf, URI_MAX);

+ 43 - 13
Pal/src/host/FreeBSD/db_sockets.c

@@ -279,54 +279,56 @@ PAL_HANDLE socket_create_handle (int type, int fd, int options,
     return hdl;
 }
 
-static int check_zero (void * mem, int size)
+#if ALLOW_BIND_ANY == 0
+static bool check_zero (void * mem, size_t size)
 {
     void * p = mem, * q = mem + size;
 
     while (p < q) {
         if (p <= q - sizeof(long)) {
             if (*(long *) p)
-                return 1;
+                return false;
             p += sizeof(long);
         } else if (p <= q - sizeof(int)) {
             if (*(int *) p)
-                return 1;
+                return false;
             p += sizeof(int);
         } else if (p <= q - sizeof(short)) {
             if (*(short *) p)
-                return 1;
+                return false;
             p += sizeof(short);
         } else {
             if (*(char *) p)
-                return 1;
+                return false;
             p++;
         }
     }
 
-    return 0;
+    return true;
 }
 
 /* check if an address is "Any" */
-static int addr_check_any (struct sockaddr * addr)
+static bool check_any_addr (struct sockaddr * addr)
 {
     if (addr->sa_family == AF_INET) {
         struct sockaddr_in * addr_in =
                         (struct sockaddr_in *) addr;
 
-        return addr_in->sin_port ||
+        return addr_in->sin_port == 0 &&
                check_zero(&addr_in->sin_addr,
                           sizeof(addr_in->sin_addr));
     } else if (addr->sa_family == AF_INET6) {
         struct sockaddr_in6 * addr_in6 =
                         (struct sockaddr_in6 *) addr;
 
-        return addr_in6->sin6_port ||
+        return addr_in6->sin6_port == 0 &&
                check_zero(&addr_in6->sin6_addr,
                           sizeof(addr_in6->sin6_addr));
     }
 
-    return -PAL_ERROR_NOTSUPPORT;
+    return false;
 }
+#endif
 
 /* listen on a tcp socket */
 static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
@@ -338,8 +340,15 @@ static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
     if ((ret = socket_parse_uri(uri, &bind_addr, &bind_addrlen,
                                 NULL, NULL)) < 0)
         return ret;
-    
-	options = HOST_SOCKET_OPTIONS(options);
+
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
+    options = HOST_SOCKET_OPTIONS(options);
     /* the socket need to have a binding address, a null address or an
        any address is not allowed */
     if (!bind_addr || addr_check_any(bind_addr) == 0)
@@ -460,6 +469,13 @@ static int tcp_connect (PAL_HANDLE * handle, char * uri, int options)
     if (bind_addr && bind_addr->sa_family != dest_addr->sa_family)
         return -PAL_ERROR_INVAL;
 
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (bind_addr && addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
     fd = INLINE_SYSCALL(socket, 3, dest_addr->sa_family,
                         SOCK_STREAM|SOCK_CLOEXEC|options, 0);
     if (IS_ERR(fd))
@@ -630,7 +646,14 @@ static int udp_bind (PAL_HANDLE * handle, char * uri, int options)
 
     assert(bind_addr);
     assert(bind_addrlen == addr_size(bind_addr));
-	
+
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
     options = HOST_SOCKET_OPTIONS(options);
     fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family,
                         SOCK_DGRAM|SOCK_CLOEXEC|options, 0);
@@ -681,6 +704,13 @@ static int udp_connect (PAL_HANDLE * handle, char * uri, int options)
                                 &dest_addr, &dest_addrlen)) < 0)
         return ret;
 
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (bind_addr && addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
     options = HOST_SOCKET_OPTIONS(options);
 	
     fd = INLINE_SYSCALL(socket, 3, dest_addr ? dest_addr->sa_family : AF_INET,

+ 40 - 12
Pal/src/host/Linux-SGX/db_sockets.c

@@ -273,52 +273,56 @@ PAL_HANDLE socket_create_handle (int type, int fd, int options,
     return hdl;
 }
 
-static int check_zero (void * mem, int size)
+#if ALLOW_BIND_ANY == 0
+static bool check_zero (void * mem, size_t size)
 {
     void * p = mem, * q = mem + size;
+
     while (p < q) {
         if (p <= q - sizeof(long)) {
             if (*(long *) p)
-                return 1;
+                return false;
             p += sizeof(long);
         } else if (p <= q - sizeof(int)) {
             if (*(int *) p)
-                return 1;
+                return false;
             p += sizeof(int);
         } else if (p <= q - sizeof(short)) {
             if (*(short *) p)
-                return 1;
+                return false;
             p += sizeof(short);
         } else {
             if (*(char *) p)
-                return 1;
+                return false;
             p++;
         }
     }
-    return 0;
+
+    return true;
 }
 
 /* check if an address is "Any" */
-static int addr_check_any (struct sockaddr * addr)
+static bool check_any_addr (struct sockaddr * addr)
 {
     if (addr->sa_family == AF_INET) {
         struct sockaddr_in * addr_in =
                         (struct sockaddr_in *) addr;
 
-        return addr_in->sin_port ||
+        return addr_in->sin_port == 0 &&
                check_zero(&addr_in->sin_addr,
                           sizeof(addr_in->sin_addr));
     } else if (addr->sa_family == AF_INET6) {
         struct sockaddr_in6 * addr_in6 =
                         (struct sockaddr_in6 *) addr;
 
-        return addr_in6->sin6_port ||
+        return addr_in6->sin6_port == 0 &&
                check_zero(&addr_in6->sin6_addr,
                           sizeof(addr_in6->sin6_addr));
     }
 
-    return -PAL_ERROR_NOTSUPPORT;
+    return false;
 }
+#endif
 
 static inline int sock_type (int type, int options)
 {
@@ -338,10 +342,12 @@ static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
                                 NULL, NULL)) < 0)
         return ret;
 
+#if ALLOW_BIND_ANY == 0
     /* the socket need to have a binding address, a null address or an
        any address is not allowed */
-    if (!bind_addr || addr_check_any(bind_addr) == 0)
-        return -PAL_ERROR_INVAL;
+    if (addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
 
     struct sockopt sock_options;
     ret = ocall_sock_listen(bind_addr->sa_family,
@@ -417,6 +423,14 @@ static int tcp_connect (PAL_HANDLE * handle, char * uri, int options)
     if (bind_addr && bind_addr->sa_family != dest_addr->sa_family)
         return -PAL_ERROR_INVAL;
 
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (bind_addr && addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
+
     struct sockopt sock_options;
     ret = ocall_sock_connect(dest_addr->sa_family,
                              sock_type(SOCK_STREAM, options), 0,
@@ -518,6 +532,13 @@ static int udp_bind (PAL_HANDLE * handle, char * uri, int options)
     assert(bind_addr);
     assert(bind_addrlen == addr_size(bind_addr));
 
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
     struct sockopt sock_options;
     ret = ocall_sock_listen(bind_addr->sa_family,
                             sock_type(SOCK_DGRAM, options), 0,
@@ -549,6 +570,13 @@ static int udp_connect (PAL_HANDLE * handle, char * uri, int options)
                                 &dest_addr, &dest_addrlen)) < 0)
         return ret;
 
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (bind_addr && addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
     struct sockopt sock_options;
     ret = ocall_sock_connect(dest_addr ? dest_addr->sa_family : AF_INET,
                              sock_type(SOCK_DGRAM, options), 0,

+ 42 - 37
Pal/src/host/Linux-SGX/enclave_framework.c

@@ -412,7 +412,7 @@ static int init_trusted_file (const char * key, const char * uri)
     tmp = strcpy_static(cskey, "sgx.trusted_checksum.", URI_MAX);
     memcpy(tmp, key, strlen(key) + 1);
 
-    int len = get_config(pal_state.root_config, cskey, checksum, CONFIG_MAX);
+    ssize_t len = get_config(pal_state.root_config, cskey, checksum, CONFIG_MAX);
     if (len < 0)
         return 0;
 
@@ -433,8 +433,10 @@ static int init_trusted_file (const char * key, const char * uri)
 
 int init_trusted_files (void)
 {
-    char *cfgbuf;
-    int ret;
+    struct config_store * store = pal_state.root_config;
+    char * cfgbuf;
+    ssize_t cfgsize;
+    int nuris, ret;
 
     if (pal_sec.exec_fd != PAL_IDX_POISON) {
         ret = init_trusted_file("exec", pal_sec.exec_name);
@@ -443,9 +445,8 @@ int init_trusted_files (void)
     }
 
     cfgbuf = __alloca(CONFIG_MAX);
-    int len = get_config(pal_state.root_config, "loader.preload",
-                         cfgbuf, CONFIG_MAX);
-    if (len) {
+    ssize_t len = get_config(store, "loader.preload", cfgbuf, CONFIG_MAX);
+    if (len > 0) {
         int npreload = 0;
         char key[10];
         const char * start, * end;
@@ -465,14 +466,16 @@ int init_trusted_files (void)
         }
     }
 
-    cfgbuf = __alloca(get_config_entries_size(pal_state.root_config,
-                                              "sgx.trusted_files"));
-    int nuris = get_config_entries(pal_state.root_config, "sgx.trusted_files",
-                                   cfgbuf);
-    if (nuris == -PAL_ERROR_INVAL)
-        nuris = 0;
+    cfgsize = get_config_entries_size(store, "sgx.trusted_files");
+    if (cfgsize <= 0)
+        goto no_trusted;
+
+    cfgbuf = __alloca(cfgsize);
+    nuris = get_config_entries(store, "sgx.trusted_files", cfgbuf, cfgsize);
+    if (nuris <= 0)
+        goto no_trusted;
 
-    if (nuris >= 0) {
+    {
         char key[CONFIG_MAX], uri[CONFIG_MAX];
         char * k = cfgbuf, * tmp;
 
@@ -482,26 +485,27 @@ int init_trusted_files (void)
             len = strlen(k);
             memcpy(tmp, k, len + 1);
             k += len + 1;
-            len = get_config(pal_state.root_config, key, uri, CONFIG_MAX);
+            len = get_config(store, key, uri, CONFIG_MAX);
             if (len > 0) {
                 ret = init_trusted_file(key + 18, uri);
                 if (ret < 0)
                     goto out;
             }
         }
-    } else {
-        ret = nuris;
-        goto out;
     }
 
-    cfgbuf = __alloca(get_config_entries_size(pal_state.root_config,
-                                              "sgx.allowed_files"));
-    nuris = get_config_entries(pal_state.root_config, "sgx.allowed_files",
-                               cfgbuf);
-    if (nuris == -PAL_ERROR_INVAL)
-        nuris = 0;
+no_trusted:
 
-    if (nuris >= 0) {
+    cfgsize = get_config_entries_size(store, "sgx.allowed_files");
+    if (cfgsize <= 0)
+        goto no_allowed;
+
+    cfgbuf = __alloca(cfgsize);
+    nuris = get_config_entries(store, "sgx.allowed_files", cfgbuf, cfgsize);
+    if (nuris <= 0)
+        goto no_allowed;
+
+    {
         char key[CONFIG_MAX], uri[CONFIG_MAX];
         char * k = cfgbuf, * tmp;
 
@@ -511,33 +515,35 @@ int init_trusted_files (void)
             len = strlen(k);
             memcpy(tmp, k, len + 1);
             k += len + 1;
-            len = get_config(pal_state.root_config, key, uri, CONFIG_MAX);
+            len = get_config(store, key, uri, CONFIG_MAX);
             if (len > 0)
                 register_trusted_file(uri, NULL);
         }
-    } else {
-        ret = nuris;
-        goto out;
     }
-    ret = 0;
 
+no_allowed:
+    ret = 0;
 out:
     return ret;
 }
 
 int init_trusted_children (void)
 {
-    char *cfgbuf;
+    struct config_store * store = pal_state.root_config;
+
     char key[CONFIG_MAX], mrkey[CONFIG_MAX];
     char uri[CONFIG_MAX], mrenclave[CONFIG_MAX];
 
     char * tmp1 = strcpy_static(key, "sgx.trusted_children.", CONFIG_MAX);
     char * tmp2 = strcpy_static(mrkey, "sgx.trusted_mrenclave.", CONFIG_MAX);
 
-    cfgbuf = __alloca(get_config_entries_size(pal_state.root_config,
-                                              "sgx.trusted_mrenclave"));
-    int nuris = get_config_entries(pal_state.root_config,
-                                   "sgx.trusted_mrenclave", cfgbuf);
+    ssize_t cfgsize = get_config_entries_size(store, "sgx.trusted_mrenclave");
+    if (cfgsize <= 0)
+        return 0;
+
+    char * cfgbuf = __alloca(cfgsize);
+    int nuris = get_config_entries(store, "sgx.trusted_mrenclave",
+                                   cfgbuf, cfgsize);
     if (nuris > 0) {
         char * k = cfgbuf;
         for (int i = 0 ; i < nuris ; i++) {
@@ -546,12 +552,11 @@ int init_trusted_children (void)
             memcpy(tmp2, k, len + 1);
             k += len + 1;
 
-            int ret = get_config(pal_state.root_config, key, uri, CONFIG_MAX);
+            ssize_t ret = get_config(store, key, uri, CONFIG_MAX);
             if (ret < 0)
                 continue;
 
-            ret = get_config(pal_state.root_config, mrkey, mrenclave,
-                             CONFIG_MAX);
+            ret = get_config(store, mrkey, mrenclave, CONFIG_MAX);
             if (ret > 0)
                 register_trusted_child(uri, mrenclave);
         }

+ 33 - 12
Pal/src/host/Linux/db_sockets.c

@@ -290,54 +290,56 @@ PAL_HANDLE socket_create_handle (int type, int fd, int options,
     return hdl;
 }
 
-static int check_zero (void * mem, int size)
+#if ALLOW_BIND_ANY == 0
+static bool check_zero (void * mem, size_t size)
 {
     void * p = mem, * q = mem + size;
 
     while (p < q) {
         if (p <= q - sizeof(long)) {
             if (*(long *) p)
-                return 1;
+                return false;
             p += sizeof(long);
         } else if (p <= q - sizeof(int)) {
             if (*(int *) p)
-                return 1;
+                return false;
             p += sizeof(int);
         } else if (p <= q - sizeof(short)) {
             if (*(short *) p)
-                return 1;
+                return false;
             p += sizeof(short);
         } else {
             if (*(char *) p)
-                return 1;
+                return false;
             p++;
         }
     }
 
-    return 0;
+    return true;
 }
 
 /* check if an address is "Any" */
-static int addr_check_any (struct sockaddr * addr)
+static bool check_any_addr (struct sockaddr * addr)
 {
     if (addr->sa_family == AF_INET) {
         struct sockaddr_in * addr_in =
                         (struct sockaddr_in *) addr;
 
-        return addr_in->sin_port ||
+        return addr_in->sin_port == 0 &&
                check_zero(&addr_in->sin_addr,
                           sizeof(addr_in->sin_addr));
     } else if (addr->sa_family == AF_INET6) {
         struct sockaddr_in6 * addr_in6 =
                         (struct sockaddr_in6 *) addr;
 
-        return addr_in6->sin6_port ||
+        return addr_in6->sin6_port == 0 &&
                check_zero(&addr_in6->sin6_addr,
                           sizeof(addr_in6->sin6_addr));
     }
 
-    return -PAL_ERROR_NOTSUPPORT;
+    return false;
 }
+#endif
 
 /* listen on a tcp socket */
 static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
@@ -350,10 +352,15 @@ static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
                                 NULL, NULL)) < 0)
         return ret;
 
+    assert(bind_addr);
+    assert(bind_addrlen == addr_size(bind_addr));
+
+#if ALLOW_BIND_ANY == 0
     /* the socket need to have a binding address, a null address or an
        any address is not allowed */
-    if (!bind_addr || addr_check_any(bind_addr) == 0)
-        return -PAL_ERROR_INVAL;
+    if (addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
 
     fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family,
                         SOCK_STREAM|SOCK_CLOEXEC|options, 0);
@@ -656,6 +663,13 @@ static int udp_bind (PAL_HANDLE * handle, char * uri, int options)
     assert(bind_addr);
     assert(bind_addrlen == addr_size(bind_addr));
 
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
     fd = INLINE_SYSCALL(socket, 3, bind_addr->sa_family,
                         SOCK_DGRAM|SOCK_CLOEXEC|options, 0);
 
@@ -711,6 +725,13 @@ static int udp_connect (PAL_HANDLE * handle, char * uri, int options)
                                 &dest_addr, &dest_addrlen)) < 0)
         return ret;
 
+#if ALLOW_BIND_ANY == 0
+    /* the socket need to have a binding address, a null address or an
+       any address is not allowed */
+    if (bind_addr && addr_check_any(bind_addr))
+       return -PAL_ERROR_INVAL;
+#endif
+
     fd = INLINE_SYSCALL(socket, 3, dest_addr ? dest_addr->sa_family : AF_INET,
                         SOCK_DGRAM|SOCK_CLOEXEC|options, 0);
 

+ 3 - 0
Pal/src/pal_defs.h

@@ -17,6 +17,9 @@
 /* maximum length of URIs */
 #define URI_MAX                  256
 
+/* allow binding sockets to ANY addresses (e.g., 0.0.0.0:0) */
+#define ALLOW_BIND_ANY           1
+
 /* turn on the following option to trace heap memory leak */
 #define TRACE_HEAP_LEAK          0
 

+ 23 - 9
Pal/src/security/Linux/manifest.c

@@ -103,11 +103,16 @@ next:
 
 int get_fs_paths (struct config_store * config, const char *** paths)
 {
-    char *keys;
+    char * keys;
     int nkeys;
+    ssize_t cfgsize;
 
-    keys = __alloca(get_config_entries_size(config, "fs.mount"));
-    if ((nkeys = get_config_entries(config, "fs.mount", keys)) < 0)
+    cfgsize = get_config_entries_size(config, "fs.mount");
+    if (cfgsize)
+        return 0;
+
+    keys = __alloca(cfgsize);
+    if ((nkeys = get_config_entries(config, "fs.mount", keys, cfgsize)) < 0)
         nkeys = 0;
 
     *paths = malloc(sizeof(const char *) * (1 + nkeys));
@@ -144,16 +149,25 @@ int get_net_rules (struct config_store * config,
                    struct graphene_net_rule ** net_rules,
                    int * nbind_rules)
 {
-    char *binds, *peers;
+    char * binds, * peers;
     int nbinds, npeers;
     int nrules = 0;
+    ssize_t cfgsize;
+
+    cfgsize = get_config_entries_size(config, "net.allow_bind");
+    if (cfgsize < 0)
+        return 0;
+
+    binds = __alloca(cfgsize);
+    if ((nbinds = get_config_entries(config, "net.allow_bind", binds, cfgsize)) < 0)
+        return 0;
 
-    binds = __alloca(get_config_entries_size(config, "net.allow_bind"));
-    if ((nbinds = get_config_entries(config, "net.allow_bind", binds)) < 0)
+    cfgsize = get_config_entries_size(config, "net.allow_peer");
+    if (cfgsize < 0)
         return 0;
 
-    peers = __alloca(get_config_entries_size(config, "net.allow_peer"));
-    if ((npeers = get_config_entries(config, "net.allow_peer", peers)) < 0)
+    peers = __alloca(cfgsize);
+    if ((npeers = get_config_entries(config, "net.allow_peer", peers, cfgsize)) < 0)
         return 0;
 
     struct graphene_net_rule * rules =
@@ -190,7 +204,7 @@ int get_net_rules (struct config_store * config,
             memcpy(tmp, k, len + 1);
             tmp[len] = 0;
 
-            int cfglen = get_config(config, key, cfgbuf, CONFIG_MAX);
+            ssize_t cfglen = get_config(config, key, cfgbuf, CONFIG_MAX);
             if (cfglen <= 0)
                 goto next;
 

+ 1 - 1
Scripts/regression.py

@@ -88,7 +88,7 @@ class Regression:
                             if timed_out : print 'Test timed out!'
                             keep_log = True
                             if flaky:
-                                print '   This test is kown  not to work, but should be fixed'
+                                print '   This test is known not to work, but should be fixed'
                             else:
                                 something_failed = 1