Browse Source

[PAL/Linux-SGX] Allow ocall_sock_send/recv to allocate on heap

ocall_sock_recv/send copied/allocated buffers on untrusted stack.
If buffer sizes were large, the stack overflowed. This patch
allocates buffers on untrusted heap if size is too large.
smherwig 6 years ago
parent
commit
4b8f74a8d8
1 changed files with 38 additions and 4 deletions
  1. 38 4
      Pal/src/host/Linux-SGX/enclave_ocalls.c

+ 38 - 4
Pal/src/host/Linux-SGX/enclave_ocalls.c

@@ -581,12 +581,23 @@ int ocall_sock_recv (int sockfd, void * buf, unsigned int count,
                      struct sockaddr * addr, unsigned int * addrlen)
 {
     int retval = 0;
+    void *obuf = NULL;
     unsigned int len = addrlen ? *addrlen : 0;
+
+    if ((count + len) > 4096) {
+        retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
+        if (retval < 0)
+            return retval;
+    }
+
     ms_ocall_sock_recv_t * ms;
     OCALLOC(ms, ms_ocall_sock_recv_t *, sizeof(*ms));
 
     ms->ms_sockfd = sockfd;
-    ms->ms_buf = ALLOC_IN_USER(buf, count);
+    if (obuf)
+        ms->ms_buf = obuf;
+    else
+        ms->ms_buf = ALLOC_IN_USER(buf, count);
     ms->ms_count = count;
     ms->ms_addr = addr ? ALLOC_IN_USER(addr, len) : NULL;
     ms->ms_addrlen = len;
@@ -595,8 +606,8 @@ int ocall_sock_recv (int sockfd, void * buf, unsigned int count,
     if (retval >= 0) {
         if (len && (!sgx_is_completely_outside_enclave(ms->ms_addr, len) ||
                     ms->ms_addrlen > len)) {
-            OCALL_EXIT();
-            return -EPERM;
+            retval = -EPERM;
+            goto done;
         }
 
         COPY_FROM_USER(buf, ms->ms_buf, retval);
@@ -604,7 +615,13 @@ int ocall_sock_recv (int sockfd, void * buf, unsigned int count,
         if (addrlen)
             *addrlen = ms->ms_addrlen;
     }
+
+done:
     OCALL_EXIT();
+
+    if (obuf)
+        ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count));
+
     return retval;
 }
 
@@ -612,17 +629,34 @@ int ocall_sock_send (int sockfd, const void * buf, unsigned int count,
                      const struct sockaddr * addr, unsigned int addrlen)
 {
     int retval = 0;
+    void *obuf = NULL;
+
+    if ((count + addrlen) > 4096) {
+        retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
+        if (retval < 0)
+            return retval;
+    }
+
     ms_ocall_sock_send_t * ms;
     OCALLOC(ms, ms_ocall_sock_send_t *, sizeof(*ms));
 
     ms->ms_sockfd = sockfd;
-    ms->ms_buf = COPY_TO_USER(buf, count);
+    if (obuf) {
+        ms->ms_buf = obuf;
+        memcpy(obuf, buf, count);
+    } else {
+        ms->ms_buf = COPY_TO_USER(buf, count);
+    }
     ms->ms_count = count;
     ms->ms_addr = addr ? COPY_TO_USER(addr, addrlen) : NULL;
     ms->ms_addrlen = addrlen;
 
     retval = SGX_OCALL(OCALL_SOCK_SEND, ms);
     OCALL_EXIT();
+
+    if (obuf)
+        ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count));
+
     return retval;
 }