瀏覽代碼

SGX IPFS: Fix a segfault and support seeking beyond the end of files while using SEEK_CUR/SEEK_END (#1916)

The current implementation throws a segmentation fault when padding
files using a large range, because the writing operation overflows the
source buffer, which was a single char.

IPFS previously assumed that the offset for the seek operation was related
to the start of the file (SEEK_SET). It now correctly checks the parameter
'whence' and computes the offset for SEEK_CUR (middle of the file) and
SEEK_END (end of the file).
Jämes Ménétrey 2 年之前
父節點
當前提交
0435acdd43
共有 2 個文件被更改,包括 89 次插入18 次删除
  1. 60 14
      core/shared/platform/linux-sgx/sgx_ipfs.c
  2. 29 4
      samples/file/wasm-app/main.c

+ 60 - 14
core/shared/platform/linux-sgx/sgx_ipfs.c

@@ -16,6 +16,11 @@
 #define SGX_ERROR_FILE_LOWEST_ERROR_ID SGX_ERROR_FILE_BAD_STATUS
 #define SGX_ERROR_FILE_HIGHEST_ERROR_ID SGX_ERROR_FILE_CLOSE_FAILED
 
+// Internal buffer filled with zeroes and used when extending the size of
+// protected files.
+#define ZEROES_PADDING_LENGTH 32 * 1024
+char zeroes_padding[ZEROES_PADDING_LENGTH] = { 0 };
+
 // The mapping between file descriptors and IPFS file pointers.
 static HashMap *ipfs_file_list;
 
@@ -78,6 +83,27 @@ ipfs_file_destroy(void *sgx_file)
     sgx_fclose(sgx_file);
 }
 
+// Writes a given number of zeroes in file at the current offset.
+// The return value is zero if successful; otherwise non-zero.
+static int
+ipfs_write_zeroes(void *sgx_file, size_t len)
+{
+    int min_count;
+
+    while (len > 0) {
+        min_count = len < ZEROES_PADDING_LENGTH ? len : ZEROES_PADDING_LENGTH;
+
+        if (sgx_fwrite(zeroes_padding, 1, min_count, sgx_file) == 0) {
+            errno = convert_sgx_errno(sgx_ferror(sgx_file));
+            return -1;
+        }
+
+        len -= min_count;
+    }
+
+    return 0;
+}
+
 int
 ipfs_init()
 {
@@ -104,7 +130,7 @@ ipfs_posix_fallocate(int fd, off_t offset, size_t len)
 
     // The wrapper for fseek takes care of extending the file if sought beyond
     // the end
-    if (ipfs_lseek(fd, offset + len, SEEK_CUR) == -1) {
+    if (ipfs_lseek(fd, offset + len, SEEK_SET) == -1) {
         return errno;
     }
 
@@ -354,7 +380,7 @@ ipfs_fflush(int fd)
 off_t
 ipfs_lseek(int fd, off_t offset, int nwhence)
 {
-    off_t new_offset;
+    off_t cursor_current_location;
     void *sgx_file = fd2file(fd);
     if (!sgx_file) {
         errno = EBADF;
@@ -364,20 +390,20 @@ ipfs_lseek(int fd, off_t offset, int nwhence)
     // Optimization: if the offset is 0 and the whence is SEEK_CUR,
     // this is equivalent of a call to ftell.
     if (offset == 0 && nwhence == SEEK_CUR) {
-        int64_t ftell_result = (off_t)sgx_ftell(sgx_file);
+        cursor_current_location = (off_t)sgx_ftell(sgx_file);
 
-        if (ftell_result == -1) {
+        if (cursor_current_location == -1) {
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
             return -1;
         }
 
-        return ftell_result;
+        return cursor_current_location;
     }
 
     int fseek_result = sgx_fseek(sgx_file, offset, nwhence);
 
     if (fseek_result == 0) {
-        new_offset = (__wasi_filesize_t)sgx_ftell(sgx_file);
+        off_t new_offset = (off_t)sgx_ftell(sgx_file);
 
         if (new_offset == -1) {
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
@@ -405,17 +431,39 @@ ipfs_lseek(int fd, off_t offset, int nwhence)
         // manually.
 
         // Assume the error is raised because the cursor is moved beyond the end
-        // of the file. Try to move the cursor at the end of the file.
+        // of the file.
+
+        // If the whence is the current cursor location, retrieve it
+        if (nwhence == SEEK_CUR) {
+            cursor_current_location = (off_t)sgx_ftell(sgx_file);
+        }
+
+        // Move the cursor at the end of the file
         if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) {
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
             return -1;
         }
 
+        // Compute the number of zeroes to append.
+        int64_t number_of_zeroes;
+        switch (nwhence) {
+            case SEEK_SET:
+                number_of_zeroes = offset - sgx_ftell(sgx_file);
+                break;
+            case SEEK_END:
+                number_of_zeroes = offset;
+                break;
+            case SEEK_CUR:
+                number_of_zeroes =
+                    cursor_current_location + offset - sgx_ftell(sgx_file);
+                break;
+            default:
+                errno = EINVAL;
+                return -1;
+        }
+
         // Write the missing zeroes
-        char zero = 0;
-        int64_t number_of_zeroes = offset - sgx_ftell(sgx_file);
-        if (sgx_fwrite(&zero, 1, number_of_zeroes, sgx_file) == 0) {
-            errno = convert_sgx_errno(sgx_ferror(sgx_file));
+        if (ipfs_write_zeroes(sgx_file, number_of_zeroes) != 0) {
             return -1;
         }
 
@@ -468,9 +516,7 @@ ipfs_ftruncate(int fd, off_t len)
 
     // Increasing the size is equal to writing from the end of the file
     // with null bytes.
-    char null_byte = 0;
-    if (sgx_fwrite(&null_byte, 1, len - file_size, sgx_file) == 0) {
-        errno = convert_sgx_errno(sgx_ferror(sgx_file));
+    if (ipfs_write_zeroes(sgx_file, len - file_size) != 0) {
         return -1;
     }
 

+ 29 - 4
samples/file/wasm-app/main.c

@@ -18,7 +18,7 @@
 #define WORLD_OFFSET 7
 #define NAME_REPLACMENT "James"
 #define NAME_REPLACMENT_LEN (sizeof(NAME_REPLACMENT) - 1)
-#define ADDITIONAL_SPACE 10
+#define ADDITIONAL_SPACE 1 * 1024 * 1024
 
 int
 main(int argc, char **argv)
@@ -100,7 +100,7 @@ main(int argc, char **argv)
     printf("[Test] Reading at specified offset passed.\n");
 
     // Test: allocate more space to the file (posix_fallocate)
-    printf("Allocate more space to the file..\n");
+    printf("Allocate more space to the file (posix_fallocate)..\n");
     posix_fallocate(fileno(file), ftell(file), ADDITIONAL_SPACE);
     printf("File current offset: %ld\n", ftell(file));
     printf("Moving to the end..\n");
@@ -110,8 +110,8 @@ main(int argc, char **argv)
     printf("[Test] Allocation or more space passed.\n");
 
     // Test: allocate more space to the file (ftruncate)
-    printf("Extend the file size of 10 bytes using ftruncate..\n");
-    ftruncate(fileno(file), ftell(file) + 10);
+    printf("Allocate more space to the file (ftruncate)..\n");
+    ftruncate(fileno(file), ftell(file) + ADDITIONAL_SPACE);
     assert(ftell(file) == strlen(text) + ADDITIONAL_SPACE);
     printf("File current offset: %ld\n", ftell(file));
     printf("Moving to the end..\n");
@@ -120,6 +120,31 @@ main(int argc, char **argv)
     assert(ftell(file) == strlen(text) + 2 * ADDITIONAL_SPACE);
     printf("[Test] Extension of the file size passed.\n");
 
+    // Test: allocate more space to the file (fseek)
+    printf("Allocate more space to the file (fseek) from the start..\n");
+    printf("File current offset: %ld\n", ftell(file));
+    fseek(file, 3 * ADDITIONAL_SPACE, SEEK_SET);
+    printf("File current offset: %ld\n", ftell(file));
+    assert(ftell(file) == 3 * ADDITIONAL_SPACE);
+    printf("[Test] Extension of the file size passed.\n");
+
+    // Test: allocate more space to the file (fseek)
+    printf("Allocate more space to the file (fseek) from the end..\n");
+    printf("File current offset: %ld\n", ftell(file));
+    fseek(file, ADDITIONAL_SPACE, SEEK_END);
+    printf("File current offset: %ld\n", ftell(file));
+    assert(ftell(file) == 4 * ADDITIONAL_SPACE);
+    printf("[Test] Extension of the file size passed.\n");
+
+    // Test: allocate more space to the file (fseek)
+    printf("Allocate more space to the file (fseek) from the middle..\n");
+    fseek(file, 3 * ADDITIONAL_SPACE, SEEK_SET);
+    printf("File current offset: %ld\n", ftell(file));
+    fseek(file, 2 * ADDITIONAL_SPACE, SEEK_CUR);
+    printf("File current offset: %ld\n", ftell(file));
+    assert(ftell(file) == 5 * ADDITIONAL_SPACE);
+    printf("[Test] Extension of the file size passed.\n");
+
     // Display some debug information
     printf("Getting the size of the file on disk..\n");
     struct stat st;