Merge cherrypicks of [4314173, 4314174, 4314175, 4314176, 4314471, 4314472, 4314473, 4314474, 4314475, 4314645, 4314646, 4314193, 4314476, 4314477, 4315350, 4315351, 4315352, 4315353, 4315354, 4314478, 4315430, 4314194, 4314195, 4314196, 4314197, 4314198, 4314199, 4314200, 4315093, 4315094, 4315095, 4315096, 4315097, 4315098, 4315099, 4315100, 4315501, 4315502, 4315503, 4314177, 4315431, 4315432, 4315433, 4315434, 4314178, 4314179, 4315355, 4315435, 4315382, 4315403, 4315404, 4315436, 4315437, 4315438, 4315439, 4315440, 4315521, 4315522, 4315523, 4315524, 4315525, 4315526, 4315527, 4315528, 4315529, 4314035, 4314230, 4315356, 4315530, 4315531, 4315471, 4315357, 4315358, 4314479, 4315532, 4315533, 4315534, 4315535, 4315536] into sparse-4732991-L06700000181398573
Change-Id: If6ff4bc272249db1c1b04500a071078febfd87a7
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index e22179b..460bbe2 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -433,6 +433,7 @@
mDataPos = pos;
mNextObjectHint = 0;
+ mObjectsSorted = false;
}
status_t Parcel::setDataCapacity(size_t size)
@@ -1276,7 +1277,7 @@
if (err) return err;
// payload
- void* const buf = this->writeInplace(pad_size(len));
+ void* const buf = this->writeInplace(len);
if (buf == NULL)
return BAD_VALUE;
@@ -1469,6 +1470,59 @@
LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!");
}
+status_t Parcel::validateReadData(size_t upperBound) const
+{
+ // Don't allow non-object reads on object data
+ if (mObjectsSorted || mObjectsSize <= 1) {
+data_sorted:
+ // Expect to check only against the next object
+ if (mNextObjectHint < mObjectsSize && upperBound > mObjects[mNextObjectHint]) {
+ // For some reason the current read position is greater than the next object
+ // hint. Iterate until we find the right object
+ size_t nextObject = mNextObjectHint;
+ do {
+ if (mDataPos < mObjects[nextObject] + sizeof(flat_binder_object)) {
+ // Requested info overlaps with an object
+ ALOGE("Attempt to read from protected data in Parcel %p", this);
+ return PERMISSION_DENIED;
+ }
+ nextObject++;
+ } while (nextObject < mObjectsSize && upperBound > mObjects[nextObject]);
+ mNextObjectHint = nextObject;
+ }
+ return NO_ERROR;
+ }
+ // Quickly determine if mObjects is sorted.
+ binder_size_t* currObj = mObjects + mObjectsSize - 1;
+ binder_size_t* prevObj = currObj;
+ while (currObj > mObjects) {
+ prevObj--;
+ if(*prevObj > *currObj) {
+ goto data_unsorted;
+ }
+ currObj--;
+ }
+ mObjectsSorted = true;
+ goto data_sorted;
+
+data_unsorted:
+ // Insertion Sort mObjects
+ // Great for mostly sorted lists. If randomly sorted or reverse ordered mObjects become common,
+ // switch to std::sort(mObjects, mObjects + mObjectsSize);
+ for (binder_size_t* iter0 = mObjects + 1; iter0 < mObjects + mObjectsSize; iter0++) {
+ binder_size_t temp = *iter0;
+ binder_size_t* iter1 = iter0 - 1;
+ while (iter1 >= mObjects && *iter1 > temp) {
+ *(iter1 + 1) = *iter1;
+ iter1--;
+ }
+ *(iter1 + 1) = temp;
+ }
+ mNextObjectHint = 0;
+ mObjectsSorted = true;
+ goto data_sorted;
+}
+
status_t Parcel::read(void* outData, size_t len) const
{
if (len > INT32_MAX) {
@@ -1479,6 +1533,15 @@
if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
&& len <= pad_size(len)) {
+ if (mObjectsSize > 0) {
+ status_t err = validateReadData(mDataPos + pad_size(len));
+ if(err != NO_ERROR) {
+ // Still increment the data position by the expected length
+ mDataPos += pad_size(len);
+ ALOGV("read Setting data pos of %p to %zu", this, mDataPos);
+ return err;
+ }
+ }
memcpy(outData, mData+mDataPos, len);
mDataPos += pad_size(len);
ALOGV("read Setting data pos of %p to %zu", this, mDataPos);
@@ -1497,6 +1560,16 @@
if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
&& len <= pad_size(len)) {
+ if (mObjectsSize > 0) {
+ status_t err = validateReadData(mDataPos + pad_size(len));
+ if(err != NO_ERROR) {
+ // Still increment the data position by the expected length
+ mDataPos += pad_size(len);
+ ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
+ return NULL;
+ }
+ }
+
const void* data = mData+mDataPos;
mDataPos += pad_size(len);
ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
@@ -1510,6 +1583,15 @@
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
if ((mDataPos+sizeof(T)) <= mDataSize) {
+ if (mObjectsSize > 0) {
+ status_t err = validateReadData(mDataPos + sizeof(T));
+ if(err != NO_ERROR) {
+ // Still increment the data position by the expected length
+ mDataPos += sizeof(T);
+ return err;
+ }
+ }
+
const void* data = mData+mDataPos;
mDataPos += sizeof(T);
*pArg = *reinterpret_cast<const T*>(data);
@@ -2366,6 +2448,7 @@
mObjects = const_cast<binder_size_t*>(objects);
mObjectsSize = mObjectsCapacity = objectsCount;
mNextObjectHint = 0;
+ mObjectsSorted = false;
mOwner = relFunc;
mOwnerCookie = relCookie;
for (size_t i = 0; i < mObjectsSize; i++) {
@@ -2524,6 +2607,7 @@
mObjects = NULL;
mObjectsSize = mObjectsCapacity = 0;
mNextObjectHint = 0;
+ mObjectsSorted = false;
mHasFds = false;
mFdsKnown = true;
mAllowFds = true;
@@ -2610,6 +2694,7 @@
mDataCapacity = desired;
mObjectsSize = mObjectsCapacity = objectsSize;
mNextObjectHint = 0;
+ mObjectsSorted = false;
} else if (mData) {
if (objectsSize < mObjectsSize) {
@@ -2631,6 +2716,7 @@
}
mObjectsSize = objectsSize;
mNextObjectHint = 0;
+ mObjectsSorted = false;
}
// We own the data, so we can just do a realloc().
@@ -2703,6 +2789,7 @@
mObjectsSize = 0;
mObjectsCapacity = 0;
mNextObjectHint = 0;
+ mObjectsSorted = false;
mHasFds = false;
mFdsKnown = true;
mAllowFds = true;
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 5d36526..dede78f 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -417,6 +417,7 @@
void freeDataNoInit();
void initState();
void scanForFds() const;
+ status_t validateReadData(size_t len) const;
template<class T>
status_t readAligned(T *pArg) const;
@@ -463,6 +464,7 @@
size_t mObjectsSize;
size_t mObjectsCapacity;
mutable size_t mNextObjectHint;
+ mutable bool mObjectsSorted;
mutable bool mFdsKnown;
mutable bool mHasFds;