mirror of
				https://github.com/bytecodealliance/wasm-micro-runtime.git
				synced 2025-10-31 13:17:31 +00:00 
			
		
		
		
	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).
This commit is contained in:
		
							parent
							
								
									45c003e6e4
								
							
						
					
					
						commit
						0435acdd43
					
				|  | @ -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; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jämes Ménétrey
						Jämes Ménétrey