Преглед изворни кода

[LibOS] Fix bug of long relative paths (more than 256B)

Previously, Graphene had a bug when dentry's rel_path was not initialized
to actual relative path if parent + filename length was longer than
256B. The problem was that rel_path was a shim_qstr which could contain
maximum 256 chars. This commit increases the limit to 4096B and adds
checks to fail explicitly if rel_path is still too large. Also, it adds
LibOS regression test.

Note that relative paths greater than 256 chars in length are not
uncommon. Most OSes impose the limit of 4096 chars or no limit at all.
Dmitrii Kuvaiskii пре 4 година
родитељ
комит
7327aa62ab

+ 1 - 1
LibOS/shim/include/shim_types.h

@@ -482,7 +482,7 @@ typedef struct shim_aevent {
     PAL_HANDLE event;
 } AEVENTTYPE;
 
-#define STR_SIZE    256
+#define STR_SIZE    4096
 
 struct shim_str {
     char str[STR_SIZE];

+ 1 - 0
LibOS/shim/src/fs/shim_dcache.c

@@ -198,6 +198,7 @@ struct shim_dentry * get_new_dentry (struct shim_mount *mount,
         if (!qstrempty(&parent->rel_path)) {
             const char * strs[] = { qstrgetstr(&parent->rel_path), "/", name };
             size_t lens[] = { parent->rel_path.len, 1, namelen };
+            assert(lens[0] + lens[1] + lens[2] < STR_SIZE);
             qstrsetstrs(&dent->rel_path, 3, strs, lens);
         } else
             qstrsetstr(&dent->rel_path, name, namelen);

+ 10 - 0
LibOS/shim/src/fs/shim_fs.c

@@ -419,6 +419,16 @@ int mount_fs (const char * type, const char * uri, const char * mount_point,
         }
     }
 
+    if (parent && last_len > 0) {
+        /* Newly created dentry's relative path will be a concatenation of parent
+         * + last strings (see get_new_dentry), make sure it fits into qstr */
+        if (parent->rel_path.len + 1 + last_len >= STR_SIZE) {  /* +1 for '/' */
+            debug("Relative path exceeds the limit %d\n", STR_SIZE);
+            ret = -ENAMETOOLONG;
+            goto out;
+        }
+    }
+
     lock(&dcache_lock);
 
     struct shim_mount * mount = alloc_mount();

+ 9 - 0
LibOS/shim/src/fs/shim_namei.c

@@ -163,6 +163,15 @@ int lookup_dentry (struct shim_dentry * parent, const char * name, int namelen,
     dent = __lookup_dcache(parent, name, namelen, NULL);
 
     if (!dent) {
+        if (parent) {
+            /* Newly created dentry's relative path will be a concatenation of parent
+             * + name strings (see get_new_dentry), make sure it fits into qstr */
+            if (parent->rel_path.len + 1 + namelen >= STR_SIZE) {  /* +1 for '/' */
+                debug("Relative path exceeds the limit %d\n", STR_SIZE);
+                return -ENAMETOOLONG;
+            }
+        }
+
         dent = get_new_dentry(fs, parent, name, namelen, NULL);
         if (!dent)
             return -ENOMEM;

+ 13 - 0
LibOS/shim/test/regression/30_fs_longpath.py

@@ -0,0 +1,13 @@
+import os, sys, mmap
+from regression import Regression
+
+loader = sys.argv[1]
+
+# Running Long Filepath Example
+regression = Regression(loader, "fs_long_path")
+
+regression.add_check(name="FS Long Paths",
+        check=lambda res: "Successfully read from file: Hello World" in res[0].out)
+
+rv = regression.run_checks()
+if rv: sys.exit(rv)

+ 69 - 0
LibOS/shim/test/regression/fs_long_path.c

@@ -0,0 +1,69 @@
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define FILENAME_MAX_LENGTH 255
+#define PATH "tmp/"
+#define MSG "Hello World"
+
+int main(int argc, char** argv) {
+    size_t rets;
+    int reti;
+    char filename[FILENAME_MAX_LENGTH];
+    memset(filename, 'a', sizeof(filename));
+    filename[FILENAME_MAX_LENGTH-1] = '\0';
+
+    char filepath[sizeof(PATH) + sizeof(filename) - 1];
+    strcpy(filepath, PATH);
+    strcat(filepath, filename);
+
+    printf("filepath = %s (len = %lu)\n", filepath, strlen(filepath));
+
+    /* write to file */
+    FILE* fp = fopen(filepath, "w");
+    if (fp == NULL) {
+        perror("fopen failed");
+        return 1;
+    }
+
+    rets = fwrite(MSG, sizeof(MSG), 1, fp); /* with NULL byte for later printf */
+    if (rets != 1) {
+        perror("fwrite failed");
+        return 1;
+    }
+
+    reti = fclose(fp);
+    if (reti) {
+        perror("fclose failed");
+        return 1;
+    }
+
+    /* read from same file */
+    fp = fopen(filepath, "r");
+    if (fp == NULL) {
+        perror("fopen failed");
+        return 1;
+    }
+
+    char buf[256];
+    clearerr(fp);
+    rets = fread(buf, sizeof(buf), 1, fp);
+    if (rets != 1 && ferror(fp)) {
+        perror("fread failed");
+        return 1;
+    }
+
+    reti = fclose(fp);
+    if (reti) {
+        perror("fclose failed");
+        return 1;
+    }
+
+    reti = printf("Successfully read from file: %s\n", buf);
+    if (reti < 0) {
+        perror("printf failed");
+        return 1;
+    }
+
+    return 0;
+}

+ 3 - 0
LibOS/shim/test/regression/manifest.template

@@ -34,3 +34,6 @@ sgx.trusted_files.libstdcxx = file:/usr/lib/x86_64-linux-gnu/libstdc++.so.6
 
 sgx.trusted_files.victim = file:exec_victim
 sgx.trusted_children.victim = file:exec_victim.sig
+
+sgx.allowed_files.tmp_dir = file:tmp/
+sgx.allowed_files.tmp_longname_file = file:tmp/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

+ 0 - 0
LibOS/shim/test/regression/tmp/.dummy


+ 1 - 1
Pal/src/host/Linux-SGX/pal_linux_defs.h

@@ -4,7 +4,7 @@
 #define ENCLAVE_HIGH_ADDRESS    0x800000000
 #define SSAFRAMENUM         2
 #define MEMORY_GAP          PRESET_PAGESIZE
-#define ENCLAVE_STACK_SIZE  (PRESET_PAGESIZE * 16)
+#define ENCLAVE_STACK_SIZE  (PRESET_PAGESIZE * 64)
 #define DEAFULT_HEAP_MIN    0x10000
 #define TRACE_ECALL         1
 #define TRACE_OCALL         1

+ 1 - 1
Pal/src/pal_defs.h

@@ -8,7 +8,7 @@
 #define STATIC_SLAB              1
 
 /* maximum length of URIs */
-#define URI_MAX                  256
+#define URI_MAX                  4096
 
 /* allow binding sockets to ANY addresses (e.g., 0.0.0.0:0) */
 #define ALLOW_BIND_ANY           1