Skip to content

Commit 0435acd

Browse files
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).
1 parent 45c003e commit 0435acd

File tree

2 files changed

+89
-18
lines changed

2 files changed

+89
-18
lines changed

core/shared/platform/linux-sgx/sgx_ipfs.c

Lines changed: 60 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
#define SGX_ERROR_FILE_LOWEST_ERROR_ID SGX_ERROR_FILE_BAD_STATUS
1717
#define SGX_ERROR_FILE_HIGHEST_ERROR_ID SGX_ERROR_FILE_CLOSE_FAILED
1818

19+
// Internal buffer filled with zeroes and used when extending the size of
20+
// protected files.
21+
#define ZEROES_PADDING_LENGTH 32 * 1024
22+
char zeroes_padding[ZEROES_PADDING_LENGTH] = { 0 };
23+
1924
// The mapping between file descriptors and IPFS file pointers.
2025
static HashMap *ipfs_file_list;
2126

@@ -78,6 +83,27 @@ ipfs_file_destroy(void *sgx_file)
7883
sgx_fclose(sgx_file);
7984
}
8085

86+
// Writes a given number of zeroes in file at the current offset.
87+
// The return value is zero if successful; otherwise non-zero.
88+
static int
89+
ipfs_write_zeroes(void *sgx_file, size_t len)
90+
{
91+
int min_count;
92+
93+
while (len > 0) {
94+
min_count = len < ZEROES_PADDING_LENGTH ? len : ZEROES_PADDING_LENGTH;
95+
96+
if (sgx_fwrite(zeroes_padding, 1, min_count, sgx_file) == 0) {
97+
errno = convert_sgx_errno(sgx_ferror(sgx_file));
98+
return -1;
99+
}
100+
101+
len -= min_count;
102+
}
103+
104+
return 0;
105+
}
106+
81107
int
82108
ipfs_init()
83109
{
@@ -104,7 +130,7 @@ ipfs_posix_fallocate(int fd, off_t offset, size_t len)
104130

105131
// The wrapper for fseek takes care of extending the file if sought beyond
106132
// the end
107-
if (ipfs_lseek(fd, offset + len, SEEK_CUR) == -1) {
133+
if (ipfs_lseek(fd, offset + len, SEEK_SET) == -1) {
108134
return errno;
109135
}
110136

@@ -354,7 +380,7 @@ ipfs_fflush(int fd)
354380
off_t
355381
ipfs_lseek(int fd, off_t offset, int nwhence)
356382
{
357-
off_t new_offset;
383+
off_t cursor_current_location;
358384
void *sgx_file = fd2file(fd);
359385
if (!sgx_file) {
360386
errno = EBADF;
@@ -364,20 +390,20 @@ ipfs_lseek(int fd, off_t offset, int nwhence)
364390
// Optimization: if the offset is 0 and the whence is SEEK_CUR,
365391
// this is equivalent of a call to ftell.
366392
if (offset == 0 && nwhence == SEEK_CUR) {
367-
int64_t ftell_result = (off_t)sgx_ftell(sgx_file);
393+
cursor_current_location = (off_t)sgx_ftell(sgx_file);
368394

369-
if (ftell_result == -1) {
395+
if (cursor_current_location == -1) {
370396
errno = convert_sgx_errno(sgx_ferror(sgx_file));
371397
return -1;
372398
}
373399

374-
return ftell_result;
400+
return cursor_current_location;
375401
}
376402

377403
int fseek_result = sgx_fseek(sgx_file, offset, nwhence);
378404

379405
if (fseek_result == 0) {
380-
new_offset = (__wasi_filesize_t)sgx_ftell(sgx_file);
406+
off_t new_offset = (off_t)sgx_ftell(sgx_file);
381407

382408
if (new_offset == -1) {
383409
errno = convert_sgx_errno(sgx_ferror(sgx_file));
@@ -405,17 +431,39 @@ ipfs_lseek(int fd, off_t offset, int nwhence)
405431
// manually.
406432

407433
// Assume the error is raised because the cursor is moved beyond the end
408-
// of the file. Try to move the cursor at the end of the file.
434+
// of the file.
435+
436+
// If the whence is the current cursor location, retrieve it
437+
if (nwhence == SEEK_CUR) {
438+
cursor_current_location = (off_t)sgx_ftell(sgx_file);
439+
}
440+
441+
// Move the cursor at the end of the file
409442
if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) {
410443
errno = convert_sgx_errno(sgx_ferror(sgx_file));
411444
return -1;
412445
}
413446

447+
// Compute the number of zeroes to append.
448+
int64_t number_of_zeroes;
449+
switch (nwhence) {
450+
case SEEK_SET:
451+
number_of_zeroes = offset - sgx_ftell(sgx_file);
452+
break;
453+
case SEEK_END:
454+
number_of_zeroes = offset;
455+
break;
456+
case SEEK_CUR:
457+
number_of_zeroes =
458+
cursor_current_location + offset - sgx_ftell(sgx_file);
459+
break;
460+
default:
461+
errno = EINVAL;
462+
return -1;
463+
}
464+
414465
// Write the missing zeroes
415-
char zero = 0;
416-
int64_t number_of_zeroes = offset - sgx_ftell(sgx_file);
417-
if (sgx_fwrite(&zero, 1, number_of_zeroes, sgx_file) == 0) {
418-
errno = convert_sgx_errno(sgx_ferror(sgx_file));
466+
if (ipfs_write_zeroes(sgx_file, number_of_zeroes) != 0) {
419467
return -1;
420468
}
421469

@@ -468,9 +516,7 @@ ipfs_ftruncate(int fd, off_t len)
468516

469517
// Increasing the size is equal to writing from the end of the file
470518
// with null bytes.
471-
char null_byte = 0;
472-
if (sgx_fwrite(&null_byte, 1, len - file_size, sgx_file) == 0) {
473-
errno = convert_sgx_errno(sgx_ferror(sgx_file));
519+
if (ipfs_write_zeroes(sgx_file, len - file_size) != 0) {
474520
return -1;
475521
}
476522

samples/file/wasm-app/main.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#define WORLD_OFFSET 7
1919
#define NAME_REPLACMENT "James"
2020
#define NAME_REPLACMENT_LEN (sizeof(NAME_REPLACMENT) - 1)
21-
#define ADDITIONAL_SPACE 10
21+
#define ADDITIONAL_SPACE 1 * 1024 * 1024
2222

2323
int
2424
main(int argc, char **argv)
@@ -100,7 +100,7 @@ main(int argc, char **argv)
100100
printf("[Test] Reading at specified offset passed.\n");
101101

102102
// Test: allocate more space to the file (posix_fallocate)
103-
printf("Allocate more space to the file..\n");
103+
printf("Allocate more space to the file (posix_fallocate)..\n");
104104
posix_fallocate(fileno(file), ftell(file), ADDITIONAL_SPACE);
105105
printf("File current offset: %ld\n", ftell(file));
106106
printf("Moving to the end..\n");
@@ -110,8 +110,8 @@ main(int argc, char **argv)
110110
printf("[Test] Allocation or more space passed.\n");
111111

112112
// Test: allocate more space to the file (ftruncate)
113-
printf("Extend the file size of 10 bytes using ftruncate..\n");
114-
ftruncate(fileno(file), ftell(file) + 10);
113+
printf("Allocate more space to the file (ftruncate)..\n");
114+
ftruncate(fileno(file), ftell(file) + ADDITIONAL_SPACE);
115115
assert(ftell(file) == strlen(text) + ADDITIONAL_SPACE);
116116
printf("File current offset: %ld\n", ftell(file));
117117
printf("Moving to the end..\n");
@@ -120,6 +120,31 @@ main(int argc, char **argv)
120120
assert(ftell(file) == strlen(text) + 2 * ADDITIONAL_SPACE);
121121
printf("[Test] Extension of the file size passed.\n");
122122

123+
// Test: allocate more space to the file (fseek)
124+
printf("Allocate more space to the file (fseek) from the start..\n");
125+
printf("File current offset: %ld\n", ftell(file));
126+
fseek(file, 3 * ADDITIONAL_SPACE, SEEK_SET);
127+
printf("File current offset: %ld\n", ftell(file));
128+
assert(ftell(file) == 3 * ADDITIONAL_SPACE);
129+
printf("[Test] Extension of the file size passed.\n");
130+
131+
// Test: allocate more space to the file (fseek)
132+
printf("Allocate more space to the file (fseek) from the end..\n");
133+
printf("File current offset: %ld\n", ftell(file));
134+
fseek(file, ADDITIONAL_SPACE, SEEK_END);
135+
printf("File current offset: %ld\n", ftell(file));
136+
assert(ftell(file) == 4 * ADDITIONAL_SPACE);
137+
printf("[Test] Extension of the file size passed.\n");
138+
139+
// Test: allocate more space to the file (fseek)
140+
printf("Allocate more space to the file (fseek) from the middle..\n");
141+
fseek(file, 3 * ADDITIONAL_SPACE, SEEK_SET);
142+
printf("File current offset: %ld\n", ftell(file));
143+
fseek(file, 2 * ADDITIONAL_SPACE, SEEK_CUR);
144+
printf("File current offset: %ld\n", ftell(file));
145+
assert(ftell(file) == 5 * ADDITIONAL_SPACE);
146+
printf("[Test] Extension of the file size passed.\n");
147+
123148
// Display some debug information
124149
printf("Getting the size of the file on disk..\n");
125150
struct stat st;

0 commit comments

Comments
 (0)