summaryrefslogtreecommitdiffstats
path: root/libziparchive
diff options
context:
space:
mode:
authorƁukasz Szymczyk <lukasz.szymczyk@sonymobile.com>2015-01-15 14:21:54 +0100
committerNarayan Kamath <narayan@google.com>2015-04-20 09:49:26 +0000
commite1d5a6aa5c4fc150c990bd160548aa8738bc51dc (patch)
tree179ec28c64a68b0944fffa77615f4f64b924cf81 /libziparchive
parent34c91eddb09ab86ffe6c965b25c5253c37ded227 (diff)
downloadsystem_core-e1d5a6aa5c4fc150c990bd160548aa8738bc51dc.tar.gz
system_core-e1d5a6aa5c4fc150c990bd160548aa8738bc51dc.tar.bz2
system_core-e1d5a6aa5c4fc150c990bd160548aa8738bc51dc.zip
Reserve space on disk using fallocate
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) #01 pc 000000000002e5b8 /system/lib64/libandroidfw.so #02 pc 000000000002f488 /system/lib64/libandroidfw.so (ExtractToMemory+328) #03 pc 000000000002f5c8 /system/lib64/libandroidfw.so (ExtractEntryToFile+268) #04 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
Diffstat (limited to 'libziparchive')
-rw-r--r--libziparchive/zip_archive.cc17
1 files changed, 16 insertions, 1 deletions
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 57c46a3c3..858234446 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -1131,7 +1131,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",
static_cast<int64_t>(declared_length + current_offset), strerror(errno));