Loading include/utils/ZipFileRO.h +17 −7 Original line number Original line Diff line number Diff line Loading @@ -14,13 +14,19 @@ * limitations under the License. * limitations under the License. */ */ // /* // Read-only access to Zip archives, with minimal heap allocation. * Read-only access to Zip archives, with minimal heap allocation. // * // This is similar to the more-complete ZipFile class, but no attempt * This is similar to the more-complete ZipFile class, but no attempt // has been made to make them interchangeable. This class operates under * has been made to make them interchangeable. This class operates under // a very different set of assumptions and constraints. * a very different set of assumptions and constraints. // * * One such assumption is that if you're getting file descriptors for * use with this class as a child of a fork() operation, you must be on * a pread() to guarantee correct operation. This is because pread() can * atomically read at a file offset without worrying about a lock around an * lseek() + read() pair. */ #ifndef __LIBS_ZIPFILERO_H #ifndef __LIBS_ZIPFILERO_H #define __LIBS_ZIPFILERO_H #define __LIBS_ZIPFILERO_H Loading Loading @@ -55,6 +61,10 @@ typedef void* ZipEntryRO; * the record structure. However, this requires a private mapping of * the record structure. However, this requires a private mapping of * every page that the Central Directory touches. Easier to tuck a copy * every page that the Central Directory touches. Easier to tuck a copy * of the string length into the hash table entry. * of the string length into the hash table entry. * * NOTE: If this is used on file descriptors inherited from a fork() operation, * you must be on a platform that implements pread() to guarantee correctness * on the shared file descriptors. */ */ class ZipFileRO { class ZipFileRO { public: public: Loading libs/utils/ZipFileRO.cpp +32 −1 Original line number Original line Diff line number Diff line Loading @@ -508,6 +508,36 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, unsigned char lfhBuf[kLFHLen]; unsigned char lfhBuf[kLFHLen]; #ifdef HAVE_PREAD /* * This file descriptor might be from zygote's preloaded assets, * so we need to do an pread() instead of a lseek() + read() to * guarantee atomicity across the processes with the shared file * descriptors. */ ssize_t actual = TEMP_FAILURE_RETRY(pread(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset)); if (actual != sizeof(lfhBuf)) { LOGW("failed reading lfh from offset %ld\n", localHdrOffset); return false; } if (get4LE(lfhBuf) != kLFHSignature) { LOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; " "got: data=0x%08lx\n", localHdrOffset, kLFHSignature, get4LE(lfhBuf)); return false; } #else /* HAVE_PREAD */ /* * For hosts don't have pread() we cannot guarantee atomic reads from * an offset in a file. Android should never run on those platforms. * File descriptors inherited from a fork() share file offsets and * there would be nothing to protect from two different processes * calling lseek() concurrently. */ { { AutoMutex _l(mFdLock); AutoMutex _l(mFdLock); Loading @@ -531,6 +561,7 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, return false; return false; } } } } #endif /* HAVE_PREAD */ off_t dataOffset = localHdrOffset + kLFHLen off_t dataOffset = localHdrOffset + kLFHLen + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen); + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen); Loading Loading
include/utils/ZipFileRO.h +17 −7 Original line number Original line Diff line number Diff line Loading @@ -14,13 +14,19 @@ * limitations under the License. * limitations under the License. */ */ // /* // Read-only access to Zip archives, with minimal heap allocation. * Read-only access to Zip archives, with minimal heap allocation. // * // This is similar to the more-complete ZipFile class, but no attempt * This is similar to the more-complete ZipFile class, but no attempt // has been made to make them interchangeable. This class operates under * has been made to make them interchangeable. This class operates under // a very different set of assumptions and constraints. * a very different set of assumptions and constraints. // * * One such assumption is that if you're getting file descriptors for * use with this class as a child of a fork() operation, you must be on * a pread() to guarantee correct operation. This is because pread() can * atomically read at a file offset without worrying about a lock around an * lseek() + read() pair. */ #ifndef __LIBS_ZIPFILERO_H #ifndef __LIBS_ZIPFILERO_H #define __LIBS_ZIPFILERO_H #define __LIBS_ZIPFILERO_H Loading Loading @@ -55,6 +61,10 @@ typedef void* ZipEntryRO; * the record structure. However, this requires a private mapping of * the record structure. However, this requires a private mapping of * every page that the Central Directory touches. Easier to tuck a copy * every page that the Central Directory touches. Easier to tuck a copy * of the string length into the hash table entry. * of the string length into the hash table entry. * * NOTE: If this is used on file descriptors inherited from a fork() operation, * you must be on a platform that implements pread() to guarantee correctness * on the shared file descriptors. */ */ class ZipFileRO { class ZipFileRO { public: public: Loading
libs/utils/ZipFileRO.cpp +32 −1 Original line number Original line Diff line number Diff line Loading @@ -508,6 +508,36 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, unsigned char lfhBuf[kLFHLen]; unsigned char lfhBuf[kLFHLen]; #ifdef HAVE_PREAD /* * This file descriptor might be from zygote's preloaded assets, * so we need to do an pread() instead of a lseek() + read() to * guarantee atomicity across the processes with the shared file * descriptors. */ ssize_t actual = TEMP_FAILURE_RETRY(pread(mFd, lfhBuf, sizeof(lfhBuf), localHdrOffset)); if (actual != sizeof(lfhBuf)) { LOGW("failed reading lfh from offset %ld\n", localHdrOffset); return false; } if (get4LE(lfhBuf) != kLFHSignature) { LOGW("didn't find signature at start of lfh; wanted: offset=%ld data=0x%08x; " "got: data=0x%08lx\n", localHdrOffset, kLFHSignature, get4LE(lfhBuf)); return false; } #else /* HAVE_PREAD */ /* * For hosts don't have pread() we cannot guarantee atomic reads from * an offset in a file. Android should never run on those platforms. * File descriptors inherited from a fork() share file offsets and * there would be nothing to protect from two different processes * calling lseek() concurrently. */ { { AutoMutex _l(mFdLock); AutoMutex _l(mFdLock); Loading @@ -531,6 +561,7 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen, return false; return false; } } } } #endif /* HAVE_PREAD */ off_t dataOffset = localHdrOffset + kLFHLen off_t dataOffset = localHdrOffset + kLFHLen + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen); + get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen); Loading