diff --git a/core/shared/platform/linux-sgx/sgx_file.c b/core/shared/platform/linux-sgx/sgx_file.c index 772a8087a..a8ae8d2f9 100644 --- a/core/shared/platform/linux-sgx/sgx_file.c +++ b/core/shared/platform/linux-sgx/sgx_file.c @@ -88,6 +88,8 @@ ocall_linkat(int *p_ret, int olddirfd, const char *oldpath, int newdirfd, int ocall_unlinkat(int *p_ret, int dirfd, const char *pathname, int flags); int +ocall_readlink(ssize_t *p_ret, const char *pathname, char *buf, size_t bufsiz); +int ocall_readlinkat(ssize_t *p_ret, int dirfd, const char *pathname, char *buf, size_t bufsiz); int @@ -190,18 +192,29 @@ openat(int dirfd, const char *pathname, int flags, ...) errno = get_errno(); #if WASM_ENABLE_SGX_IPFS != 0 - // When WAMR uses Intel SGX IPFS to enabled, it opens a second - // file descriptor to interact with the secure file. - // The first file descriptor opened earlier is used to interact - // with the metadata of the file (e.g., time, flags, etc.). - int ret; - void *file_ptr = ipfs_fopen(fd, pathname, flags); - if (file_ptr == NULL) { + struct stat sb; + int ret = fstatat(dirfd, pathname, &sb, 0); + if (ret < 0) { if (ocall_close(&ret, fd) != SGX_SUCCESS) { TRACE_OCALL_FAIL(); } return -1; } + + // Ony files are managed by SGX IPFS + if (S_ISREG(sb.st_mode)) { + // When WAMR uses Intel SGX IPFS to enabled, it opens a second + // file descriptor to interact with the secure file. + // The first file descriptor opened earlier is used to interact + // with the metadata of the file (e.g., time, flags, etc.). + void *file_ptr = ipfs_fopen(fd, flags); + if (file_ptr == NULL) { + if (ocall_close(&ret, fd) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + } + return -1; + } + } #endif return fd; @@ -699,6 +712,24 @@ unlinkat(int dirfd, const char *pathname, int flags) return ret; } +ssize_t +readlink(const char *pathname, char *buf, size_t bufsiz) +{ + ssize_t ret; + + if (buf == NULL) + return -1; + + if (ocall_readlink(&ret, pathname, buf, bufsiz) != SGX_SUCCESS) { + TRACE_OCALL_FAIL(); + return -1; + } + + if (ret == -1) + errno = get_errno(); + return ret; +} + ssize_t readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { diff --git a/core/shared/platform/linux-sgx/sgx_file.h b/core/shared/platform/linux-sgx/sgx_file.h index c35c22469..8690e1f69 100644 --- a/core/shared/platform/linux-sgx/sgx_file.h +++ b/core/shared/platform/linux-sgx/sgx_file.h @@ -219,6 +219,8 @@ linkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int unlinkat(int dirfd, const char *pathname, int flags); ssize_t +readlink(const char *pathname, char *buf, size_t bufsiz); +ssize_t readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz); int symlinkat(const char *target, int newdirfd, const char *linkpath); diff --git a/core/shared/platform/linux-sgx/sgx_ipfs.c b/core/shared/platform/linux-sgx/sgx_ipfs.c index 5abb36876..2b0a38fff 100644 --- a/core/shared/platform/linux-sgx/sgx_ipfs.c +++ b/core/shared/platform/linux-sgx/sgx_ipfs.c @@ -248,7 +248,7 @@ ipfs_close(int fd) } void * -ipfs_fopen(int fd, const char *filename, int flags) +ipfs_fopen(int fd, int flags) { // Mapping back the mode const char *mode; @@ -291,8 +291,29 @@ ipfs_fopen(int fd, const char *filename, int flags) return NULL; } - // Opening the file - void *sgx_file = sgx_fopen_auto_key(filename, mode); + // Determine the symbolic link of the file descriptor, because IPFS does not + // support opening a relative path to a file descriptor (i.e., openat). + // Using the symbolic link in /proc/self allows to retrieve the same path as + // opened by the initial openat and respects the chroot of WAMR. + size_t ret; + char symbolic_path[32]; + ret = + snprintf(symbolic_path, sizeof(symbolic_path), "/proc/self/fd/%d", fd); + if (ret >= sizeof(symbolic_path)) { + errno = ENAMETOOLONG; + return NULL; + } + + // Resolve the symbolic link to real absolute path, because IPFS can only + // open a file with a same file name it was initially created. Otherwise, + // IPFS throws SGX_ERROR_FILE_NAME_MISMATCH. + char real_path[PATH_MAX] = { 0 }; + ret = readlink(symbolic_path, real_path, PATH_MAX - 1); + if (ret == -1) + return NULL; + + // Opening the file using the real path + void *sgx_file = sgx_fopen_auto_key(real_path, mode); if (sgx_file == NULL) { errno = convert_sgx_errno(sgx_ferror(sgx_file)); diff --git a/core/shared/platform/linux-sgx/sgx_ipfs.h b/core/shared/platform/linux-sgx/sgx_ipfs.h index ade40bd56..e4de90274 100644 --- a/core/shared/platform/linux-sgx/sgx_ipfs.h +++ b/core/shared/platform/linux-sgx/sgx_ipfs.h @@ -28,7 +28,7 @@ ipfs_write(int fd, const struct iovec *iov, int iovcnt, bool has_offset, int ipfs_close(int fd); void * -ipfs_fopen(int fd, const char *filename, int flags); +ipfs_fopen(int fd, int flags); int ipfs_fflush(int fd); off_t diff --git a/core/shared/platform/linux-sgx/sgx_wamr.edl b/core/shared/platform/linux-sgx/sgx_wamr.edl index d8b6030d7..7cb4817fd 100644 --- a/core/shared/platform/linux-sgx/sgx_wamr.edl +++ b/core/shared/platform/linux-sgx/sgx_wamr.edl @@ -48,6 +48,9 @@ enclave { int flags); int ocall_unlinkat(int dirfd, [in, string]const char *pathname, int flags); + ssize_t ocall_readlink([in, string]const char *pathname, + [out, size=bufsiz]char *buf, + size_t bufsiz); ssize_t ocall_readlinkat(int dirfd, [in, string]const char *pathname, [out, size=bufsiz]char *buf, diff --git a/core/shared/platform/linux-sgx/untrusted/file.c b/core/shared/platform/linux-sgx/untrusted/file.c index 22abe7d88..cb9bf6a21 100644 --- a/core/shared/platform/linux-sgx/untrusted/file.c +++ b/core/shared/platform/linux-sgx/untrusted/file.c @@ -186,6 +186,12 @@ ocall_unlinkat(int dirfd, const char *pathname, int flags) return unlinkat(dirfd, pathname, flags); } +ssize_t +ocall_readlink(const char *pathname, char *buf, size_t bufsiz) +{ + return readlink(pathname, buf, bufsiz); +} + ssize_t ocall_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { diff --git a/samples/file/wasm-app/main.c b/samples/file/wasm-app/main.c index 9931f3661..caf6436d9 100644 --- a/samples/file/wasm-app/main.c +++ b/samples/file/wasm-app/main.c @@ -12,7 +12,8 @@ #include #include -#define PATH_TEST_FILE "test.txt" +#define PATH_TEST_FOLDER "./test" +#define PATH_TEST_FILE (PATH_TEST_FOLDER "/test.txt") #define FILE_TEXT "Hello, world!" #define WORLD_OFFSET 7 #define NAME_REPLACMENT "James" @@ -28,6 +29,10 @@ main(int argc, char **argv) int ret; long long stat_size; + // Test: Create a folder to store the file, if it does not exist yet + ret = mkdir(PATH_TEST_FOLDER, 777); + assert(ret == 0 || (ret == -1 && errno == EEXIST)); + // Test: File opening (fopen) printf("Opening a file..\n"); file = fopen(PATH_TEST_FILE, "w+");