diff --git a/core/shared/platform/linux-sgx/sgx_ipfs.c b/core/shared/platform/linux-sgx/sgx_ipfs.c index 2b0a38ff..32268898 100644 --- a/core/shared/platform/linux-sgx/sgx_ipfs.c +++ b/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; } diff --git a/samples/file/wasm-app/main.c b/samples/file/wasm-app/main.c index caf6436d..f4363475 100644 --- a/samples/file/wasm-app/main.c +++ b/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;