[RESTRICT AUTOMERGE] Fix potential out of bounds writes in LogEvent. am: 53251a491f
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13321771 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I1da4a9159e5611d80c618913f728defb5399d927
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <android-base/stringprintf.h>
|
#include <android-base/stringprintf.h>
|
||||||
#include <android/binder_ibinder.h>
|
#include <android/binder_ibinder.h>
|
||||||
|
#include <log/log.h>
|
||||||
#include <private/android_filesystem_config.h>
|
#include <private/android_filesystem_config.h>
|
||||||
|
|
||||||
#include "annotations.h"
|
#include "annotations.h"
|
||||||
@@ -216,13 +217,18 @@ void LogEvent::parseAttributionChain(int32_t* pos, int32_t depth, bool* last,
|
|||||||
last[2] = true;
|
last[2] = true;
|
||||||
parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
|
parseString(pos, /*depth=*/2, last, /*numAnnotations=*/0);
|
||||||
}
|
}
|
||||||
// Check if at least one node was successfully parsed.
|
|
||||||
if (mValues.size() - 1 > firstUidInChainIndex) {
|
if (mValues.size() - 1 > INT8_MAX) {
|
||||||
|
mValid = false;
|
||||||
|
} else if (mValues.size() - 1 > firstUidInChainIndex) {
|
||||||
|
// At least one node was successfully parsed.
|
||||||
mAttributionChainStartIndex = static_cast<int8_t>(firstUidInChainIndex);
|
mAttributionChainStartIndex = static_cast<int8_t>(firstUidInChainIndex);
|
||||||
mAttributionChainEndIndex = static_cast<int8_t>(mValues.size() - 1);
|
mAttributionChainEndIndex = static_cast<int8_t>(mValues.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseAnnotations(numAnnotations, firstUidInChainIndex);
|
if (mValid) {
|
||||||
|
parseAnnotations(numAnnotations, firstUidInChainIndex);
|
||||||
|
}
|
||||||
|
|
||||||
pos[1] = pos[2] = 1;
|
pos[1] = pos[2] = 1;
|
||||||
last[1] = last[2] = false;
|
last[1] = last[2] = false;
|
||||||
@@ -234,7 +240,8 @@ bool LogEvent::checkPreviousValueType(Type expected) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LogEvent::parseIsUidAnnotation(uint8_t annotationType) {
|
void LogEvent::parseIsUidAnnotation(uint8_t annotationType) {
|
||||||
if (mValues.empty() || !checkPreviousValueType(INT) || annotationType != BOOL_TYPE) {
|
if (mValues.empty() || mValues.size() - 1 > INT8_MAX || !checkPreviousValueType(INT)
|
||||||
|
|| annotationType != BOOL_TYPE) {
|
||||||
mValid = false;
|
mValid = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -270,6 +277,12 @@ void LogEvent::parsePrimaryFieldFirstUidAnnotation(uint8_t annotationType,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (static_cast<int>(mValues.size() - 1) < firstUidInChainIndex) { // AttributionChain is empty.
|
||||||
|
mValid = false;
|
||||||
|
android_errorWriteLog(0x534e4554, "174485572");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const bool primaryField = readNextValue<uint8_t>();
|
const bool primaryField = readNextValue<uint8_t>();
|
||||||
mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(primaryField);
|
mValues[firstUidInChainIndex].mAnnotations.setPrimaryField(primaryField);
|
||||||
}
|
}
|
||||||
@@ -280,6 +293,12 @@ void LogEvent::parseExclusiveStateAnnotation(uint8_t annotationType) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mValues.size() - 1 > INT8_MAX) {
|
||||||
|
android_errorWriteLog(0x534e4554, "174488848");
|
||||||
|
mValid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const bool exclusiveState = readNextValue<uint8_t>();
|
const bool exclusiveState = readNextValue<uint8_t>();
|
||||||
mExclusiveStateFieldIndex = static_cast<int8_t>(mValues.size() - 1);
|
mExclusiveStateFieldIndex = static_cast<int8_t>(mValues.size() - 1);
|
||||||
mValues[getExclusiveStateFieldIndex()].mAnnotations.setExclusiveState(exclusiveState);
|
mValues[getExclusiveStateFieldIndex()].mAnnotations.setExclusiveState(exclusiveState);
|
||||||
|
|||||||
@@ -363,6 +363,116 @@ TEST(LogEventTest, TestResetStateAnnotation) {
|
|||||||
EXPECT_EQ(event.getResetState(), resetState);
|
EXPECT_EQ(event.getResetState(), resetState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(LogEventTest, TestExclusiveStateAnnotationAfterTooManyFields) {
|
||||||
|
AStatsEvent* event = AStatsEvent_obtain();
|
||||||
|
AStatsEvent_setAtomId(event, 100);
|
||||||
|
|
||||||
|
const unsigned int numAttributionNodes = 64;
|
||||||
|
|
||||||
|
uint32_t uids[numAttributionNodes];
|
||||||
|
const char* tags[numAttributionNodes];
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i <= numAttributionNodes; i++) {
|
||||||
|
uids[i-1] = i;
|
||||||
|
tags[i-1] = std::to_string(i).c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
|
||||||
|
AStatsEvent_writeInt32(event, 1);
|
||||||
|
AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_EXCLUSIVE_STATE, true);
|
||||||
|
|
||||||
|
AStatsEvent_build(event);
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
|
||||||
|
|
||||||
|
LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
|
||||||
|
EXPECT_FALSE(logEvent.parseBuffer(buf, size));
|
||||||
|
EXPECT_EQ(-1, logEvent.getExclusiveStateFieldIndex());
|
||||||
|
|
||||||
|
AStatsEvent_release(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LogEventTest, TestUidAnnotationAfterTooManyFields) {
|
||||||
|
AStatsEvent* event = AStatsEvent_obtain();
|
||||||
|
AStatsEvent_setAtomId(event, 100);
|
||||||
|
|
||||||
|
const unsigned int numAttributionNodes = 64;
|
||||||
|
|
||||||
|
uint32_t uids[numAttributionNodes];
|
||||||
|
const char* tags[numAttributionNodes];
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i <= numAttributionNodes; i++) {
|
||||||
|
uids[i-1] = i;
|
||||||
|
tags[i-1] = std::to_string(i).c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
|
||||||
|
AStatsEvent_writeInt32(event, 1);
|
||||||
|
AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_IS_UID, true);
|
||||||
|
|
||||||
|
AStatsEvent_build(event);
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
|
||||||
|
|
||||||
|
LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
|
||||||
|
EXPECT_FALSE(logEvent.parseBuffer(buf, size));
|
||||||
|
EXPECT_EQ(-1, logEvent.getUidFieldIndex());
|
||||||
|
|
||||||
|
AStatsEvent_release(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LogEventTest, TestAttributionChainEndIndexAfterTooManyFields) {
|
||||||
|
AStatsEvent* event = AStatsEvent_obtain();
|
||||||
|
AStatsEvent_setAtomId(event, 100);
|
||||||
|
|
||||||
|
const unsigned int numAttributionNodes = 65;
|
||||||
|
|
||||||
|
uint32_t uids[numAttributionNodes];
|
||||||
|
const char* tags[numAttributionNodes];
|
||||||
|
|
||||||
|
for (unsigned int i = 1; i <= numAttributionNodes; i++) {
|
||||||
|
uids[i-1] = i;
|
||||||
|
tags[i-1] = std::to_string(i).c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
AStatsEvent_writeAttributionChain(event, uids, tags, numAttributionNodes);
|
||||||
|
|
||||||
|
AStatsEvent_build(event);
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
|
||||||
|
|
||||||
|
LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
|
||||||
|
EXPECT_FALSE(logEvent.parseBuffer(buf, size));
|
||||||
|
EXPECT_FALSE(logEvent.hasAttributionChain());
|
||||||
|
|
||||||
|
AStatsEvent_release(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(LogEventTest, TestEmptyAttributionChainWithPrimaryFieldFirstUidAnnotation) {
|
||||||
|
AStatsEvent* event = AStatsEvent_obtain();
|
||||||
|
AStatsEvent_setAtomId(event, 100);
|
||||||
|
|
||||||
|
uint32_t uids[] = {};
|
||||||
|
const char* tags[] = {};
|
||||||
|
|
||||||
|
AStatsEvent_writeInt32(event, 10);
|
||||||
|
AStatsEvent_writeAttributionChain(event, uids, tags, 0);
|
||||||
|
AStatsEvent_addBoolAnnotation(event, ANNOTATION_ID_PRIMARY_FIELD_FIRST_UID, true);
|
||||||
|
|
||||||
|
AStatsEvent_build(event);
|
||||||
|
|
||||||
|
size_t size;
|
||||||
|
uint8_t* buf = AStatsEvent_getBuffer(event, &size);
|
||||||
|
|
||||||
|
LogEvent logEvent(/*uid=*/1000, /*pid=*/1001);
|
||||||
|
EXPECT_FALSE(logEvent.parseBuffer(buf, size));
|
||||||
|
|
||||||
|
AStatsEvent_release(event);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace statsd
|
} // namespace statsd
|
||||||
} // namespace os
|
} // namespace os
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|||||||
Reference in New Issue
Block a user