Commit message: None
CVE: CVE-2015-3845
CWE: CWE-264
Vulnerability description: The Parcel::appendFrom function in libs/binder/Parcel.cpp in Binder in Android before 5.1.1 LMY48M does not consider parcel boundaries during identification of binder objects in an append operation, which allows attackers to obtain a different application's privileges via a crafted application, aka internal bug 17312693.

Project: Android

Parcel::Blob::Blob() :
        mMapped(false), mData(NULL), mSize(0) {
}

Project: Android

Parcel::Parcel()
{
    LOG_ALLOC("Parcel %p: constructing", this);
    initState();
}

Project: Android

size_t Parcel::dataAvail() const
{
 return dataSize() - dataPosition();
}

Project: Android

int32_t Parcel::readInt32() const
{
 return readAligned<int32_t>();
}

Project: Android

status_t Parcel::readInt64(int64_t *pArg) const
{
 return readAligned(pArg);
}

Project: Android

int64_t Parcel::readInt64() const
{
 return readAligned<int64_t>();
}

Project: Android

void Parcel::releaseObjects()
{
 const sp<ProcessState> proc(ProcessState::self());
 size_t i = mObjectsSize;
 uint8_t* const data = mData;
 binder_size_t* const objects = mObjects;
 while (i > 0) {
        i--;
 const flat_binder_object* flat
 = reinterpret_cast<flat_binder_object*>(data+objects[i]);
        release_object(proc, *flat, this);
 }
}

Project: Android

void release_object(const sp<ProcessState>& proc,
 const flat_binder_object& obj, const void* who)
{
 switch (obj.type) {
 case BINDER_TYPE_BINDER:
 if (obj.binder) {
                LOG_REFS("Parcel %p releasing reference on local %p", who, obj.cookie);
 reinterpret_cast<IBinder*>(obj.cookie)->decStrong(who);
 }
 return;
 case BINDER_TYPE_WEAK_BINDER:
 if (obj.binder)
 reinterpret_cast<RefBase::weakref_type*>(obj.binder)->decWeak(who);
 return;
 case BINDER_TYPE_HANDLE: {
 const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);
 if (b != NULL) {
                LOG_REFS("Parcel %p releasing reference on remote %p", who, b.get());
                b->decStrong(who);
 }
 return;
 }
 case BINDER_TYPE_WEAK_HANDLE: {
 const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle);
 if (b != NULL) b.get_refs()->decWeak(who);
 return;
 }
 case BINDER_TYPE_FD: {
 if (obj.cookie != 0) close(obj.handle);
 return;
 }
 }

    ALOGE("Invalid object type 0x%08x", obj.type);
}

Project: Android

status_t Parcel::writeDouble(double val)
{
 union {
 double d;
 unsigned long long ll;
 } u;
    u.d = val;
 return writeAligned(u.ll);
}

Project: Android

status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership)
{
    flat_binder_object obj;
    obj.type = BINDER_TYPE_FD;
    obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */
    obj.handle = fd;
    obj.cookie = takeOwnership ? 1 : 0;
 return writeObject(obj, true);
}

Project: Android

status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
{
 const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;
 const bool enoughObjects = mObjectsSize < mObjectsCapacity;
 if (enoughData && enoughObjects) {
restart_write:
 *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;

 if (nullMetaData || val.binder != 0) {
            mObjects[mObjectsSize] = mDataPos;
            acquire_object(ProcessState::self(), val, this);
            mObjectsSize++;
 }

 if (val.type == BINDER_TYPE_FD) {
 if (!mAllowFds) {
 return FDS_NOT_ALLOWED;
 }
            mHasFds = mFdsKnown = true;
 }

 return finishWrite(sizeof(flat_binder_object));
 }

 if (!enoughData) {
 const status_t err = growData(sizeof(val));
 if (err != NO_ERROR) return err;
 }
 if (!enoughObjects) {
 size_t newSize = ((mObjectsSize+2)*3)/2;
 binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
 if (objects == NULL) return NO_MEMORY;
        mObjects = objects;
        mObjectsCapacity = newSize;
 }

 goto restart_write;
}

Project: Android

status_t Parcel::writeString16(const String16& str)
{
 return writeString16(str.string(), str.size());
}

Project: Android

status_t Parcel::writeWeakBinder(const wp<IBinder>& val)
{
 return flatten_binder(ProcessState::self(), val, this);
}