mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 06:55:07 +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