summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrtmitchell@google.com <rtmitchell@google.com>2018-04-05 17:57:27 -0700
committerTim Schumacher <timschumi@gmx.de>2018-06-19 19:33:06 +0200
commit59941bdc226a2b779613701f221f76d65ffa40ba (patch)
treed4487aa2a0b7c189d102f3a6cdea6cbf888ad797
parentf625911138d99203939ae256a48619b4883bb9cc (diff)
downloadframeworks_base-59941bdc226a2b779613701f221f76d65ffa40ba.tar.gz
frameworks_base-59941bdc226a2b779613701f221f76d65ffa40ba.tar.bz2
frameworks_base-59941bdc226a2b779613701f221f76d65ffa40ba.zip
ResStringPool: Fix security vulnerability
Adds detection of attacker-modified size and data fields passed to ResStringPool::setTo(). These attacks are modified apks that AAPT would not normally generate. In the rare case this occurs, the installation cannot be allowed to continue. Bug: 71361168 Bug: 71360999 Test: run cts -m CtsAppSecurityHostTestCases \ -t android.appsecurity.cts.CorruptApkTests Change-Id: If7eb93a9e723b16c8a0556fc4e20006aa0391d57 Merged-In: If7eb93a9e723b16c8a0556fc4e20006aa0391d57 (cherry picked from commit 7e54c3f261d81316b75cb734075319108d8bc1d1) CVE-2018-9338, CVE-2018-9340
-rw-r--r--libs/androidfw/ResourceTypes.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 5b04eb9f05c..109619bf84a 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -464,6 +464,22 @@ status_t ResStringPool::setTo(const void* data, size_t size, bool copyData)
uninit();
+ // The chunk must be at least the size of the string pool header.
+ if (size < sizeof(ResStringPool_header)) {
+ LOG_ALWAYS_FATAL("Bad string block: data size %zu is too small to be a string block", size);
+ return (mError=BAD_TYPE);
+ }
+
+ // The data is at least as big as a ResChunk_header, so we can safely validate the other
+ // header fields.
+ // `data + size` is safe because the source of `size` comes from the kernel/filesystem.
+ if (validate_chunk(reinterpret_cast<const ResChunk_header*>(data), sizeof(ResStringPool_header),
+ reinterpret_cast<const uint8_t*>(data) + size,
+ "ResStringPool_header") != NO_ERROR) {
+ LOG_ALWAYS_FATAL("Bad string block: malformed block dimensions");
+ return (mError=BAD_TYPE);
+ }
+
const bool notDeviceEndian = htods(0xf0) != 0xf0;
if (copyData || notDeviceEndian) {
@@ -475,6 +491,8 @@ status_t ResStringPool::setTo(const void* data, size_t size, bool copyData)
data = mOwnedData;
}
+ // The size has been checked, so it is safe to read the data in the ResStringPool_header
+ // data structure.
mHeader = (const ResStringPool_header*)data;
if (notDeviceEndian) {