Skip to content

Commit bf25270

Browse files
devinmoore-googAndroid (Google) Code Review
authored andcommitted
Merge "Protect objects in Parcel::appendFrom" into main
2 parents 68f65ad + 28e7af0 commit bf25270

2 files changed

Lines changed: 39 additions & 12 deletions

File tree

libs/binder/Parcel.cpp

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,11 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) {
542542
return BAD_VALUE;
543543
}
544544

545+
// Make sure we aren't appending over objects.
546+
if (status_t status = validateReadData(mDataPos + len); status != OK) {
547+
return status;
548+
}
549+
545550
if ((mDataPos + len) > mDataCapacity) {
546551
// grow data
547552
err = growData(len);
@@ -565,17 +570,13 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) {
565570
const binder_size_t* objects = otherKernelFields->mObjects;
566571
size_t size = otherKernelFields->mObjectsSize;
567572
// Count objects in range
568-
int firstIndex = -1, lastIndex = -2;
573+
int numObjects = 0;
569574
for (int i = 0; i < (int)size; i++) {
570-
size_t off = objects[i];
571-
if ((off >= offset) && (off + sizeof(flat_binder_object) <= offset + len)) {
572-
if (firstIndex == -1) {
573-
firstIndex = i;
574-
}
575-
lastIndex = i;
575+
size_t pos = objects[i];
576+
if ((pos >= offset) && (pos + sizeof(flat_binder_object) <= offset + len)) {
577+
numObjects++;
576578
}
577579
}
578-
int numObjects = lastIndex - firstIndex + 1;
579580
if (numObjects > 0) {
580581
const sp<ProcessState> proc(ProcessState::self());
581582
// grow objects
@@ -597,8 +598,12 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) {
597598

598599
// append and acquire objects
599600
int idx = kernelFields->mObjectsSize;
600-
for (int i = firstIndex; i <= lastIndex; i++) {
601-
size_t off = objects[i] - offset + startPos;
601+
for (int i = 0; i < (int)size; i++) {
602+
size_t pos = objects[i];
603+
if (!(pos >= offset) || !(pos + sizeof(flat_binder_object) <= offset + len)) {
604+
continue;
605+
}
606+
size_t off = pos - offset + startPos;
602607
kernelFields->mObjects[idx++] = off;
603608
kernelFields->mObjectsSize++;
604609

@@ -618,6 +623,9 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) {
618623

619624
acquire_object(proc, *flat, this, true /*tagFds*/);
620625
}
626+
// Always clear sorted flag. It is tricky to infer if the append
627+
// result maintains the sort or not.
628+
kernelFields->mObjectsSorted = false;
621629
}
622630
#else
623631
LOG_ALWAYS_FATAL("Binder kernel driver disabled at build time");
@@ -649,7 +657,10 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) {
649657
const binder_size_t objPos = otherRpcFields->mObjectPositions[i];
650658
if (offset <= objPos && objPos < offset + len) {
651659
size_t newDataPos = objPos - offset + startPos;
652-
rpcFields->mObjectPositions.push_back(newDataPos);
660+
rpcFields->mObjectPositions
661+
.insert(std::upper_bound(rpcFields->mObjectPositions.begin(),
662+
rpcFields->mObjectPositions.end(), newDataPos),
663+
newDataPos);
653664

654665
mDataPos = newDataPos;
655666
int32_t objectType;
@@ -1594,7 +1605,10 @@ status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership) {
15941605
if (status_t err = writeInt32(rpcFields->mFds->size()); err != OK) {
15951606
return err;
15961607
}
1597-
rpcFields->mObjectPositions.push_back(dataPos);
1608+
rpcFields->mObjectPositions
1609+
.insert(std::upper_bound(rpcFields->mObjectPositions.begin(),
1610+
rpcFields->mObjectPositions.end(), dataPos),
1611+
dataPos);
15981612
rpcFields->mFds->push_back(std::move(fdVariant));
15991613
return OK;
16001614
}
@@ -1802,6 +1816,8 @@ status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
18021816
kernelFields->mObjects[kernelFields->mObjectsSize] = mDataPos;
18031817
acquire_object(ProcessState::self(), val, this, true /*tagFds*/);
18041818
kernelFields->mObjectsSize++;
1819+
// Clear sorted flag if we aren't appending to the end.
1820+
kernelFields->mObjectsSorted &= mDataPos == mDataSize;
18051821
}
18061822

18071823
return finishWrite(sizeof(flat_binder_object));

libs/binder/tests/binderParcelUnitTest.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ using android::IPCThreadState;
2626
using android::NO_ERROR;
2727
using android::OK;
2828
using android::Parcel;
29+
using android::PERMISSION_DENIED;
2930
using android::sp;
3031
using android::status_t;
3132
using android::String16;
@@ -356,6 +357,16 @@ TEST(Parcel, AppendWithFdPartial) {
356357
ASSERT_NE(-1, p1.readFileDescriptor());
357358
}
358359

360+
TEST(Parcel, AppendOverObject) {
361+
Parcel p1;
362+
p1.writeDupFileDescriptor(0);
363+
Parcel p2;
364+
p2.writeInt32(2);
365+
366+
p1.setDataPosition(8);
367+
ASSERT_EQ(PERMISSION_DENIED, p1.appendFrom(&p2, 0, p2.dataSize()));
368+
}
369+
359370
// Tests a second operation results in a parcel at the same location as it
360371
// started.
361372
void parcelOpSameLength(const std::function<void(Parcel*)>& a, const std::function<void(Parcel*)>& b) {

0 commit comments

Comments
 (0)