Bug 1391268 - 1. Add call to verify CRC; r=glandium

To reliably detect corrupt APK, this patch adds a GeckoLoader.verifyCRC
call to enable verification of CRC before extracting libs.

MozReview-Commit-ID: 5EpIfwREGIv
This commit is contained in:
Jim Chen 2018-02-14 16:56:54 -05:00
parent b9be133138
commit 589e7e1a01
4 changed files with 83 additions and 0 deletions

View File

@ -491,6 +491,7 @@ public final class GeckoLoader {
// These methods are implemented in mozglue/android/nsGeckoUtils.cpp
private static native void putenv(String map);
public static native boolean verifyCRCs(String apkName);
// These methods are implemented in mozglue/android/APKOpen.cpp
public static native void nativeRun(String[] args, int crashFd, int ipcFd, int crashAnnotationFd);

View File

@ -26,6 +26,22 @@ Java_org_mozilla_gecko_mozglue_GeckoLoader_putenv(JNIEnv *jenv, jclass, jstring
jenv->ReleaseStringUTFChars(map, str);
}
extern "C" APKOPEN_EXPORT jboolean MOZ_JNICALL
Java_org_mozilla_gecko_mozglue_GeckoLoader_verifyCRCs(JNIEnv *jenv, jclass, jstring jApkName) {
const char* str;
// XXX: java doesn't give us true UTF8, we should figure out something
// better to do here
str = jenv->GetStringUTFChars(jApkName, nullptr);
if (str == nullptr) {
return false;
}
RefPtr<Zip> zip = Zip::Create(str);
const bool valid = zip->VerifyCRCs();
jenv->ReleaseStringUTFChars(jApkName, str);
return jboolean(valid);
}
extern "C"
__attribute__ ((visibility("default")))
jobject MOZ_JNICALL

View File

@ -184,6 +184,67 @@ Zip::GetFirstEntry() const
return entries;
}
bool
Zip::VerifyCRCs() const
{
AutoLock lock(&mutex);
for (const DirectoryEntry *entry = GetFirstEntry();
entry; entry = entry->GetNext()) {
const LocalFile *file = LocalFile::validate(
static_cast<const char *>(mapped) + entry->offset);
uint32_t crc = crc32(0, nullptr, 0);
DEBUG_LOG("%.*s: crc=%08x", int(entry->filenameSize),
reinterpret_cast<const char *>(entry) + sizeof(*entry),
uint32_t(entry->CRC32));
if (entry->compression == Stream::Type::STORE) {
crc = crc32(crc, static_cast<const uint8_t*>(file->GetData()),
entry->compressedSize);
DEBUG_LOG(" STORE size=%d crc=%08x", int(entry->compressedSize), crc);
} else if (entry->compression == Stream::Type::DEFLATE) {
zxx_stream zstream;
Bytef buffer[1024];
zstream.avail_in = entry->compressedSize;
zstream.next_in = reinterpret_cast<Bytef *>(
const_cast<void *>(file->GetData()));
if (inflateInit2(&zstream, -MAX_WBITS) != Z_OK) {
return false;
}
for (;;) {
zstream.avail_out = sizeof(buffer);
zstream.next_out = buffer;
int ret = inflate(&zstream, Z_SYNC_FLUSH);
crc = crc32(crc, buffer, sizeof(buffer) - zstream.avail_out);
if (ret == Z_STREAM_END) {
break;
} else if (ret != Z_OK) {
return false;
}
}
inflateEnd(&zstream);
DEBUG_LOG(" DEFLATE size=%d crc=%08x", int(zstream.total_out), crc);
} else {
MOZ_ASSERT_UNREACHABLE("Unexpected stream type");
continue;
}
if (entry->CRC32 != crc) {
return false;
}
}
return true;
}
ZipCollection ZipCollection::Singleton;
static pthread_mutex_t sZipCollectionMutex = PTHREAD_MUTEX_INITIALIZER;

View File

@ -263,6 +263,11 @@ public:
return name;
}
/**
* Returns whether all files have correct CRC checksum.
*/
bool VerifyCRCs() const;
private:
/* File name of the archive */
char *name;