Browse Source

[Pal/{Linux,Linux-SGX}] Use pread/pwrite instead of lseek + read/write

Isaku Yamahata 4 years ago
parent
commit
2fea898faa

+ 2 - 23
Pal/src/host/Linux-SGX/db_files.c

@@ -82,7 +82,6 @@ static int file_open(PAL_HANDLE* handle, const char* type, const char* uri, int
 
     hdl->file.stubs  = (PAL_PTR)stubs;
     hdl->file.total  = total;
-    hdl->file.offset = 0;
 
     if (hdl->file.stubs && hdl->file.total) {
         /* case of trusted file: mmap the whole file in untrusted memory for future reads/writes */
@@ -104,19 +103,9 @@ static int64_t file_read(PAL_HANDLE handle, uint64_t offset, uint64_t count, voi
     sgx_stub_t* stubs = (sgx_stub_t*)handle->file.stubs;
 
     if (!stubs) {
-        /* case of allowed file: emulate via lseek + read */
-        if (handle->file.offset != offset) {
-            ret = ocall_lseek(handle->file.fd, offset, SEEK_SET);
-            if (IS_ERR(ret))
-                return -PAL_ERROR_DENIED;
-            handle->file.offset = offset;
-        }
-
-        ret = ocall_read(handle->file.fd, buffer, count);
+        ret = ocall_pread(handle->file.fd, buffer, count, offset);
         if (IS_ERR(ret))
             return unix_to_pal_error(ERRNO(ret));
-
-        handle->file.offset = offset + ret;
         return ret;
     }
 
@@ -146,19 +135,9 @@ static int64_t file_write(PAL_HANDLE handle, uint64_t offset, uint64_t count, co
     sgx_stub_t* stubs = (sgx_stub_t*)handle->file.stubs;
 
     if (!stubs) {
-        /* case of allowed file: emulate via lseek + write */
-        if (handle->file.offset != offset) {
-            ret = ocall_lseek(handle->file.fd, offset, SEEK_SET);
-            if (IS_ERR(ret))
-                return -PAL_ERROR_DENIED;
-            handle->file.offset = offset;
-        }
-
-        ret = ocall_write(handle->file.fd, buffer, count);
+        ret = ocall_pwrite(handle->file.fd, buffer, count, offset);
         if (IS_ERR(ret))
             return unix_to_pal_error(ERRNO(ret));
-
-        handle->file.offset = offset + ret;
         return ret;
     }
 

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

@@ -117,7 +117,6 @@ static PAL_HANDLE setup_dummy_file_handle (const char * name)
     handle->file.realpath = path;
 
     handle->file.total  = 0;
-    handle->file.offset = 0;
     handle->file.stubs  = NULL;
 
     return handle;

+ 117 - 45
Pal/src/host/Linux-SGX/enclave_ocalls.c

@@ -168,16 +168,23 @@ int ocall_close (int fd)
     return retval;
 }
 
-int ocall_read (int fd, void * buf, unsigned int count)
-{
+int ocall_read(int fd, void* buf, unsigned int count) {
     int retval = 0;
-    void * obuf = NULL;
-    ms_ocall_read_t * ms;
+    void* obuf = NULL;
+    ms_ocall_read_t* ms;
+    void* ms_buf;
 
     if (count > MAX_UNTRUSTED_STACK_BUF) {
         retval = ocall_mmap_untrusted(-1, 0, ALLOC_ALIGN_UP(count), PROT_READ | PROT_WRITE, &obuf);
         if (IS_ERR(retval))
             return retval;
+        ms_buf = obuf;
+    } else {
+        ms_buf = sgx_alloc_on_ustack(count);
+        if (!ms_buf) {
+            retval = -EPERM;
+            goto out;
+        }
     }
 
     ms = sgx_alloc_on_ustack(sizeof(*ms));
@@ -188,15 +195,7 @@ int ocall_read (int fd, void * buf, unsigned int count)
 
     ms->ms_fd = fd;
     ms->ms_count = count;
-    if (obuf)
-        ms->ms_buf = obuf;
-    else
-        ms->ms_buf = sgx_alloc_on_ustack(count);
-
-    if (!ms->ms_buf) {
-        retval = -EPERM;
-        goto out;
-    }
+    ms->ms_buf = ms_buf;
 
     retval = sgx_ocall(OCALL_READ, ms);
 
@@ -214,15 +213,15 @@ out:
     return retval;
 }
 
-int ocall_write (int fd, const void * buf, unsigned int count)
-{
+int ocall_write(int fd, const void* buf, unsigned int count) {
     int retval = 0;
-    void * obuf = NULL;
-    ms_ocall_write_t * ms;
+    void* obuf = NULL;
+    ms_ocall_write_t* ms;
+    const void* ms_buf;
 
     if (sgx_is_completely_outside_enclave(buf, count)) {
         /* buf is in untrusted memory (e.g., allowed file mmaped in untrusted memory) */
-        obuf = (void*)buf;
+        ms_buf = buf;
     } else if (sgx_is_completely_within_enclave(buf, count)) {
         /* typical case of buf inside of enclave memory */
         if (count > MAX_UNTRUSTED_STACK_BUF) {
@@ -231,10 +230,17 @@ int ocall_write (int fd, const void * buf, unsigned int count)
             if (IS_ERR(retval))
                 return retval;
             memcpy(obuf, buf, count);
+            ms_buf = obuf;
+        } else {
+            ms_buf = sgx_copy_to_ustack(buf, count);
         }
     } else {
         /* buf is partially in/out of enclave memory */
-        return -EPERM;
+        ms_buf = NULL;
+    }
+    if (!ms_buf) {
+        retval = -EPERM;
+        goto out;
     }
 
     ms = sgx_alloc_on_ustack(sizeof(*ms));
@@ -245,21 +251,107 @@ int ocall_write (int fd, const void * buf, unsigned int count)
 
     ms->ms_fd = fd;
     ms->ms_count = count;
+    ms->ms_buf = ms_buf;
+
+    retval = sgx_ocall(OCALL_WRITE, ms);
+
+out:
+    sgx_reset_ustack();
     if (obuf)
-        ms->ms_buf = obuf;
-    else
-        ms->ms_buf = sgx_copy_to_ustack(buf, count);
+        ocall_munmap_untrusted(obuf, ALLOC_ALIGN_UP(count));
+    return retval;
+}
 
-    if (!ms->ms_buf) {
+ssize_t ocall_pread(int fd, void* buf, size_t count, off_t offset) {
+    long retval = 0;
+    void* obuf = NULL;
+    ms_ocall_pread_t* ms;
+    void* ms_buf;
+
+    if (count > MAX_UNTRUSTED_STACK_BUF) {
+        retval = ocall_mmap_untrusted(-1, 0, ALLOC_ALIGN_UP(count), PROT_READ | PROT_WRITE, &obuf);
+        if (IS_ERR(retval))
+            return retval;
+        ms_buf = obuf;
+    } else {
+        ms_buf = sgx_alloc_on_ustack(count);
+        if (!ms_buf) {
+            retval = -EPERM;
+            goto out;
+        }
+    }
+
+    ms = sgx_alloc_on_ustack(sizeof(*ms));
+    if (!ms) {
         retval = -EPERM;
         goto out;
     }
 
-    retval = sgx_ocall(OCALL_WRITE, ms);
+    ms->ms_fd = fd;
+    ms->ms_count = count;
+    ms->ms_offset = offset;
+    ms->ms_buf = ms_buf;
+
+    retval = sgx_ocall(OCALL_PREAD, ms);
+    if (retval > 0) {
+        if (!sgx_copy_to_enclave(buf, count, ms->ms_buf, retval)) {
+            retval = -EPERM;
+        }
+    }
 
 out:
     sgx_reset_ustack();
-    if (obuf && obuf != buf)
+    if (obuf)
+        ocall_munmap_untrusted(obuf, ALLOC_ALIGN_UP(count));
+    return retval;
+}
+
+ssize_t ocall_pwrite(int fd, const void* buf, size_t count, off_t offset) {
+    long retval = 0;
+    void* obuf = NULL;
+    ms_ocall_pwrite_t* ms;
+    const void* ms_buf;
+
+    if (sgx_is_completely_outside_enclave(buf, count)) {
+        /* buf is in untrusted memory (e.g., allowed file mmaped in untrusted memory) */
+        ms_buf = buf;
+    } else if (sgx_is_completely_within_enclave(buf, count)) {
+        /* typical case of buf inside of enclave memory */
+        if (count > MAX_UNTRUSTED_STACK_BUF) {
+            /* buf is too big and may overflow untrusted stack, so use untrusted heap */
+            retval = ocall_mmap_untrusted(-1, 0, ALLOC_ALIGN_UP(count), PROT_READ | PROT_WRITE, &obuf);
+            if (IS_ERR(retval))
+                return retval;
+            memcpy(obuf, buf, count);
+            ms_buf = obuf;
+        } else {
+            ms_buf = sgx_copy_to_ustack(buf, count);
+        }
+    } else {
+        /* buf is partially in/out of enclave memory */
+        ms_buf = NULL;
+    }
+    if (!ms_buf) {
+        retval = -EPERM;
+        goto out;
+    }
+
+    ms = sgx_alloc_on_ustack(sizeof(*ms));
+    if (!ms) {
+        retval = -EPERM;
+        goto out;
+    }
+
+    ms->ms_fd = fd;
+    ms->ms_count = count;
+    ms->ms_offset = offset;
+    ms->ms_buf = ms_buf;
+
+    retval = sgx_ocall(OCALL_PWRITE, ms);
+
+out:
+    sgx_reset_ustack();
+    if (obuf)
         ocall_munmap_untrusted(obuf, ALLOC_ALIGN_UP(count));
     return retval;
 }
@@ -385,26 +477,6 @@ int ocall_ftruncate (int fd, uint64_t length)
     return retval;
 }
 
-int ocall_lseek(int fd, uint64_t offset, int whence) {
-    int retval = 0;
-    ms_ocall_lseek_t* ms;
-
-    ms = sgx_alloc_on_ustack(sizeof(*ms));
-    if (!ms) {
-        sgx_reset_ustack();
-        return -EPERM;
-    }
-
-    ms->ms_fd     = fd;
-    ms->ms_offset = offset;
-    ms->ms_whence = whence;
-
-    retval = sgx_ocall(OCALL_LSEEK, ms);
-
-    sgx_reset_ustack();
-    return retval;
-}
-
 int ocall_mkdir (const char * pathname, unsigned short mode)
 {
     int retval = 0;

+ 5 - 2
Pal/src/host/Linux-SGX/enclave_ocalls.h

@@ -7,6 +7,7 @@
 #include <asm/stat.h>
 #include <linux/socket.h>
 #include <linux/poll.h>
+#include <sys/types.h>
 
 noreturn void ocall_exit (int exitcode, int is_exitgroup);
 
@@ -27,6 +28,10 @@ int ocall_read (int fd, void * buf, unsigned int count);
 
 int ocall_write (int fd, const void * buf, unsigned int count);
 
+ssize_t ocall_pread(int fd, void* buf, size_t count, off_t offset);
+
+ssize_t ocall_pwrite(int fd, const void* buf, size_t count, off_t offset);
+
 int ocall_fstat (int fd, struct stat * buf);
 
 int ocall_fionread (int fd);
@@ -39,8 +44,6 @@ int ocall_fsync (int fd);
 
 int ocall_ftruncate (int fd, uint64_t length);
 
-int ocall_lseek(int fd, uint64_t offset, int whence);
-
 int ocall_mkdir (const char *pathname, unsigned short mode);
 
 int ocall_getdents (int fd, struct linux_dirent64 *dirp, unsigned int size);

+ 17 - 7
Pal/src/host/Linux-SGX/ocall_types.h

@@ -4,6 +4,7 @@
 
 #include <stdbool.h>
 #include <stddef.h>
+#include <sys/types.h>
 #include "linux_types.h"
 #include "pal.h"
 #include "sgx_arch.h"
@@ -28,13 +29,14 @@ enum {
     OCALL_CLOSE,
     OCALL_READ,
     OCALL_WRITE,
+    OCALL_PREAD,
+    OCALL_PWRITE,
     OCALL_FSTAT,
     OCALL_FIONREAD,
     OCALL_FSETNONBLOCK,
     OCALL_FCHMOD,
     OCALL_FSYNC,
     OCALL_FTRUNCATE,
-    OCALL_LSEEK,
     OCALL_MKDIR,
     OCALL_GETDENTS,
     OCALL_RESUME_THREAD,
@@ -106,6 +108,20 @@ typedef struct {
     unsigned int ms_count;
 } ms_ocall_write_t;
 
+typedef struct {
+    int ms_fd;
+    void* ms_buf;
+    size_t ms_count;
+    off_t ms_offset;
+} ms_ocall_pread_t;
+
+typedef struct {
+    int ms_fd;
+    const void* ms_buf;
+    size_t ms_count;
+    off_t ms_offset;
+} ms_ocall_pwrite_t;
+
 typedef struct {
     int ms_fd;
     struct stat ms_stat;
@@ -134,12 +150,6 @@ typedef struct {
     uint64_t ms_length;
 } ms_ocall_ftruncate_t;
 
-typedef struct {
-    int ms_fd;
-    uint64_t ms_offset;
-    int ms_whence;
-} ms_ocall_lseek_t;
-
 typedef struct {
     const char * ms_pathname;
     unsigned short ms_mode;

+ 0 - 1
Pal/src/host/Linux-SGX/pal_host.h

@@ -91,7 +91,6 @@ typedef struct pal_handle
             PAL_IDX fd;
             PAL_STR realpath;
             PAL_NUM total;
-            PAL_NUM offset;
             /* below fields are used only for trusted files */
             PAL_PTR stubs;    /* contains hashes of file chunks */
             PAL_PTR umem;     /* valid only when stubs != NULL */

+ 18 - 9
Pal/src/host/Linux-SGX/sgx_enclave.c

@@ -117,6 +117,22 @@ static long sgx_ocall_write(void * pms)
     return ret;
 }
 
+static long sgx_ocall_pread(void* pms) {
+    ms_ocall_pread_t* ms = (ms_ocall_pread_t*)pms;
+    long ret;
+    ODEBUG(OCALL_PREAD, ms);
+    ret = INLINE_SYSCALL(pread64, 4, ms->ms_fd, ms->ms_buf, ms->ms_count, ms->ms_offset);
+    return ret;
+}
+
+static long sgx_ocall_pwrite(void* pms) {
+    ms_ocall_pwrite_t* ms = (ms_ocall_pwrite_t*)pms;
+    long ret;
+    ODEBUG(OCALL_PWRITE, ms);
+    ret = INLINE_SYSCALL(pwrite64, 4, ms->ms_fd, ms->ms_buf, ms->ms_count, ms->ms_offset);
+    return ret;
+}
+
 static long sgx_ocall_fstat(void * pms)
 {
     ms_ocall_fstat_t * ms = (ms_ocall_fstat_t *) pms;
@@ -187,14 +203,6 @@ static long sgx_ocall_ftruncate(void * pms)
     return ret;
 }
 
-static long sgx_ocall_lseek(void* pms) {
-    ms_ocall_lseek_t* ms = (ms_ocall_lseek_t*)pms;
-    long ret;
-    ODEBUG(OCALL_LSEEK, ms);
-    ret = INLINE_SYSCALL(lseek, 3, ms->ms_fd, ms->ms_offset, ms->ms_whence);
-    return ret;
-}
-
 static long sgx_ocall_mkdir(void * pms)
 {
     ms_ocall_mkdir_t * ms = (ms_ocall_mkdir_t *) pms;
@@ -619,13 +627,14 @@ sgx_ocall_fn_t ocall_table[OCALL_NR] = {
         [OCALL_CLOSE]            = sgx_ocall_close,
         [OCALL_READ]             = sgx_ocall_read,
         [OCALL_WRITE]            = sgx_ocall_write,
+        [OCALL_PREAD]            = sgx_ocall_pread,
+        [OCALL_PWRITE]           = sgx_ocall_pwrite,
         [OCALL_FSTAT]            = sgx_ocall_fstat,
         [OCALL_FIONREAD]         = sgx_ocall_fionread,
         [OCALL_FSETNONBLOCK]     = sgx_ocall_fsetnonblock,
         [OCALL_FCHMOD]           = sgx_ocall_fchmod,
         [OCALL_FSYNC]            = sgx_ocall_fsync,
         [OCALL_FTRUNCATE]        = sgx_ocall_ftruncate,
-        [OCALL_LSEEK]            = sgx_ocall_lseek,
         [OCALL_MKDIR]            = sgx_ocall_mkdir,
         [OCALL_GETDENTS]         = sgx_ocall_getdents,
         [OCALL_RESUME_THREAD]    = sgx_ocall_resume_thread,

+ 2 - 21
Pal/src/host/Linux/db_files.c

@@ -58,7 +58,6 @@ static int file_open (PAL_HANDLE * handle, const char * type, const char * uri,
     SET_HANDLE_TYPE(hdl, file);
     HANDLE_HDR(hdl)->flags |= RFD(0)|WFD(0);
     hdl->file.fd = ret;
-    hdl->file.offset = 0;
     hdl->file.map_start = NULL;
     char * path = (void *) hdl + HANDLE_SIZE(file);
     memcpy(path, uri, len + 1);
@@ -78,20 +77,11 @@ static int64_t file_read (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     int fd = handle->file.fd;
     int64_t ret;
 
-    if (handle->file.offset != offset) {
-        ret = INLINE_SYSCALL(lseek, 3, fd, offset, SEEK_SET);
-        if (IS_ERR(ret))
-            return -PAL_ERROR_DENIED;
-
-        handle->file.offset = offset;
-    }
-
-    ret = INLINE_SYSCALL(read, 3, fd, buffer, count);
+    ret = INLINE_SYSCALL(pread64, 4, fd, buffer, count, offset);
 
     if (IS_ERR(ret))
         return unix_to_pal_error(ERRNO(ret));
 
-    handle->file.offset = offset + ret;
     return ret;
 }
 
@@ -102,20 +92,11 @@ static int64_t file_write (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     int fd = handle->file.fd;
     int64_t ret;
 
-    if (handle->file.offset != offset) {
-        ret = INLINE_SYSCALL(lseek, 3, fd, offset, SEEK_SET);
-        if (IS_ERR(ret))
-            return -PAL_ERROR_DENIED;
-
-        handle->file.offset = offset;
-    }
-
-    ret = INLINE_SYSCALL(write, 3, fd, buffer, count);
+    ret = INLINE_SYSCALL(pwrite64, 4, fd, buffer, count, offset);
 
     if (IS_ERR(ret))
         return unix_to_pal_error(ERRNO(ret));
 
-    handle->file.offset = offset + ret;
     return ret;
 }
 

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

@@ -292,7 +292,6 @@ void pal_linux_main (void * args)
     SET_HANDLE_TYPE(file, file);
     HANDLE_HDR(file)->flags |= RFD(0)|WFD(0);
     file->file.fd = fd;
-    file->file.offset = 0;
     file->file.map_start = NULL;
 
     char * path = (void *) file + HANDLE_SIZE(file);

+ 0 - 1
Pal/src/host/Linux/pal_host.h

@@ -75,7 +75,6 @@ typedef struct pal_handle
 
         struct {
             PAL_IDX fd;
-            PAL_NUM offset;
             PAL_STR realpath;
             /*
              * map_start is to request this file should be mapped to this