From f183fdd024bfa87e929219ac537b7090eabae9b1 Mon Sep 17 00:00:00 2001 From: Steven Moreland Date: Tue, 27 Oct 2020 00:12:12 +0000 Subject: libbinder: support TF_CLEAR_BUF This flag instructs the kernel to clear transactions from send/reply buffers for certain transactions which may contain sensitive data, as a security precaution. Bug: 171501998 Test: binderLibTest (only checks there is no error) Change-Id: I69d732e5cc2b15472dc52d47c66716bc1b3be6ae --- libs/binder/Parcel.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'libs/binder/Parcel.cpp') diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 27cf97c945..feeb819a8a 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -49,6 +49,7 @@ #include #include "Static.h" +#include "Utils.h" #define LOG_REFS(...) //#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__) @@ -502,6 +503,11 @@ bool Parcel::hasFileDescriptors() const return mHasFds; } +void Parcel::markSensitive() const +{ + mDeallocZero = true; +} + void Parcel::updateWorkSourceRequestHeaderPosition() const { // Only update the request headers once. We only want to point // to the first headers read/written. @@ -2627,6 +2633,9 @@ void Parcel::freeDataNoInit() LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity); gParcelGlobalAllocSize -= mDataCapacity; gParcelGlobalAllocCount--; + if (mDeallocZero) { + zeroMemory(mData, mDataSize); + } free(mData); } if (mObjects) free(mObjects); @@ -2649,6 +2658,21 @@ status_t Parcel::growData(size_t len) : continueWrite(std::max(newSize, (size_t) 128)); } +static uint8_t* reallocZeroFree(uint8_t* data, size_t oldCapacity, size_t newCapacity, bool zero) { + if (!zero) { + return (uint8_t*)realloc(data, newCapacity); + } + uint8_t* newData = (uint8_t*)malloc(newCapacity); + if (!newData) { + return nullptr; + } + + memcpy(newData, data, std::min(oldCapacity, newCapacity)); + zeroMemory(data, oldCapacity); + free(data); + return newData; +} + status_t Parcel::restartWrite(size_t desired) { if (desired > INT32_MAX) { @@ -2662,7 +2686,7 @@ status_t Parcel::restartWrite(size_t desired) return continueWrite(desired); } - uint8_t* data = (uint8_t*)realloc(mData, desired); + uint8_t* data = reallocZeroFree(mData, mDataCapacity, desired, mDeallocZero); if (!data && desired > mDataCapacity) { mError = NO_MEMORY; return NO_MEMORY; @@ -2813,7 +2837,7 @@ status_t Parcel::continueWrite(size_t desired) // We own the data, so we can just do a realloc(). if (desired > mDataCapacity) { - uint8_t* data = (uint8_t*)realloc(mData, desired); + uint8_t* data = reallocZeroFree(mData, mDataCapacity, desired, mDeallocZero); if (data) { LOG_ALLOC("Parcel %p: continue from %zu to %zu capacity", this, mDataCapacity, desired); @@ -2881,6 +2905,7 @@ void Parcel::initState() mHasFds = false; mFdsKnown = true; mAllowFds = true; + mDeallocZero = false; mOwner = nullptr; mOpenAshmemSize = 0; mWorkSourceRequestHeaderPosition = 0; -- cgit v1.2.3-59-g8ed1b