Skip to content

Commit

Permalink
Reserve space on disk using fallocate
Browse files Browse the repository at this point in the history
There were crashes when android failed to extract
zip archives due to out of free space on disk, with stacks like:

  #00 pc 00000000000156b0 /system/lib64/libc.so (memcpy+176)
  #1 pc 000000000002e5b8 /system/lib64/libandroidfw.so
  #2 pc 000000000002f488 /system/lib64/libandroidfw.so (ExtractToMemory+328)
  #3 pc 000000000002f5c8 /system/lib64/libandroidfw.so (ExtractEntryToFile+268)
  #4 pc 00000000000287d8 /system/lib64/libandroidfw.so (android::ZipFileRO::\
  uncompressEntry(void*, int) const+12)

Space for the file is now allocated using fallocate rather than
ftruncate, since ftruncate dont actually reserve space on disk. When writes
to the mmaped pointer fails to be realized due to out of space SIGBUS
is the result. With this change we make sure that there is space available
before mmaping the pointer.

Change-Id: Ic5e8c33dbe729edb57919dacff73811b34cc2dc2
  • Loading branch information
Łukasz Szymczyk authored and rmcc committed Dec 10, 2015
1 parent b3e3a63 commit 2e94933
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion libziparchive/zip_archive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1124,7 +1124,22 @@ int32_t ExtractEntryToFile(ZipArchiveHandle handle,
return kIoError;
}

int result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
int result = 0;
#if defined(__linux__)
// Make sure we have enough space on the volume to extract the compressed
// entry. Note that the call to ftruncate below will change the file size but
// will not allocate space on disk.
if (declared_length > 0) {
result = TEMP_FAILURE_RETRY(fallocate(fd, 0, current_offset, declared_length));
if (result == -1) {
ALOGW("Zip: unable to allocate space for file to %" PRId64 ": %s",
static_cast<int64_t>(declared_length + current_offset), strerror(errno));
return kIoError;
}
}
#endif // defined(__linux__)

result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
if (result == -1) {
ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
(int64_t)(declared_length + current_offset), strerror(errno));
Expand Down

0 comments on commit 2e94933

Please sign in to comment.