Przeglądaj źródła

[Pal/Linux-SGX] Allow to write/send from buffer in untrusted memory

Previously, ocall_write() and ocall_sock_send() disallowed to write/send
data from a buffer allocated in untrusted memory (as it was considered
an impossible scenario). However, sendfile() logic may write an allowed
regular file (which is mmapped in untrusted memory) directly to a socket.
Thus, this commit allows such writes/sends.
Dmitrii Kuvaiskii 4 lat temu
rodzic
commit
b3d00dc647
1 zmienionych plików z 36 dodań i 18 usunięć
  1. 36 18
      Pal/src/host/Linux-SGX/enclave_ocalls.c

+ 36 - 18
Pal/src/host/Linux-SGX/enclave_ocalls.c

@@ -266,10 +266,21 @@ int ocall_write (int fd, const void * buf, unsigned int count)
     void * obuf = NULL;
     ms_ocall_write_t * ms;
 
-    if (count > PRESET_PAGESIZE) {
-        retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
-        if (IS_ERR(retval))
-            return retval;
+    if (sgx_is_completely_outside_enclave(buf, count)) {
+        /* buf is in untrusted memory (e.g., allowed file mmaped in untrusted memory) */
+        obuf = (void*)buf;
+    } else if (sgx_is_completely_within_enclave(buf, count)) {
+        /* typical case of buf inside of enclave memory */
+        if (count > PRESET_PAGESIZE) {
+            /* buf is too big and may overflow untrusted stack, so use untrusted heap */
+            retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
+            if (IS_ERR(retval))
+                return retval;
+            memcpy(obuf, buf, count);
+        }
+    } else {
+        /* buf is partially in/out of enclave memory */
+        return -EPERM;
     }
 
     ms = sgx_alloc_on_ustack(sizeof(*ms));
@@ -280,12 +291,10 @@ int ocall_write (int fd, const void * buf, unsigned int count)
 
     ms->ms_fd = fd;
     ms->ms_count = count;
-    if (obuf) {
+    if (obuf)
         ms->ms_buf = obuf;
-        memcpy(obuf, buf, count);
-    } else {
+    else
         ms->ms_buf = sgx_copy_to_ustack(buf, count);
-    }
 
     if (!ms->ms_buf) {
         retval = -EPERM;
@@ -296,7 +305,7 @@ int ocall_write (int fd, const void * buf, unsigned int count)
 
 out:
     sgx_reset_ustack();
-    if (obuf)
+    if (obuf && obuf != buf)
         ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count));
     return retval;
 }
@@ -791,10 +800,21 @@ int ocall_sock_send (int sockfd, const void * buf, unsigned int count,
     void * obuf = NULL;
     ms_ocall_sock_send_t * ms;
 
-    if ((count + addrlen) > PRESET_PAGESIZE) {
-        retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
-        if (IS_ERR(retval))
-            return retval;
+    if (sgx_is_completely_outside_enclave(buf, count)) {
+        /* buf is in untrusted memory (e.g., allowed file mmaped in untrusted memory) */
+        obuf = (void*)buf;
+    } else if (sgx_is_completely_within_enclave(buf, count)) {
+        /* typical case of buf inside of enclave memory */
+        if ((count + addrlen) > PRESET_PAGESIZE) {
+            /* buf is too big and may overflow untrusted stack, so use untrusted heap */
+            retval = ocall_alloc_untrusted(ALLOC_ALIGNUP(count), &obuf);
+            if (IS_ERR(retval))
+                return retval;
+            memcpy(obuf, buf, count);
+        }
+    } else {
+        /* buf is partially in/out of enclave memory */
+        return -EPERM;
     }
 
     ms = sgx_alloc_on_ustack(sizeof(*ms));
@@ -807,12 +827,10 @@ int ocall_sock_send (int sockfd, const void * buf, unsigned int count,
     ms->ms_count = count;
     ms->ms_addrlen = addrlen;
     ms->ms_addr = addr ? sgx_copy_to_ustack(addr, addrlen) : NULL;
-    if (obuf) {
+    if (obuf)
         ms->ms_buf = obuf;
-        memcpy(obuf, buf, count);
-    } else {
+    else
         ms->ms_buf = sgx_copy_to_ustack(buf, count);
-    }
 
     if (!ms->ms_buf || (addr && !ms->ms_addr)) {
         retval = -EPERM;
@@ -823,7 +841,7 @@ int ocall_sock_send (int sockfd, const void * buf, unsigned int count,
 
 out:
     sgx_reset_ustack();
-    if (obuf)
+    if (obuf && obuf != buf)
         ocall_unmap_untrusted(obuf, ALLOC_ALIGNUP(count));
     return retval;
 }