diff options
Diffstat (limited to 'libs/binder/Parcel.cpp')
-rw-r--r-- | libs/binder/Parcel.cpp | 811 |
1 files changed, 493 insertions, 318 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index ee834ea43c..efcc042b3c 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -20,7 +20,6 @@ #include <errno.h> #include <fcntl.h> #include <inttypes.h> -#include <linux/sched.h> #include <pthread.h> #include <stdint.h> #include <stdio.h> @@ -41,17 +40,15 @@ #include <binder/TextOutput.h> #include <cutils/ashmem.h> -#include <cutils/compiler.h> +#include <utils/Debug.h> #include <utils/Flattenable.h> #include <utils/Log.h> -#include <utils/String16.h> -#include <utils/String8.h> #include <utils/misc.h> +#include <utils/String8.h> +#include <utils/String16.h> -#include "RpcState.h" +#include <private/binder/binder_module.h> #include "Static.h" -#include "Utils.h" -#include "binder_module.h" #define LOG_REFS(...) //#define LOG_REFS(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__) @@ -78,14 +75,11 @@ static size_t pad_size(size_t s) { namespace android { // many things compile this into prebuilts on the stack -#ifdef __LP64__ -static_assert(sizeof(Parcel) == 120); -#else -static_assert(sizeof(Parcel) == 60); -#endif +static_assert(sizeof(Parcel) == 60 || sizeof(Parcel) == 120); -static std::atomic<size_t> gParcelGlobalAllocCount; -static std::atomic<size_t> gParcelGlobalAllocSize; +static pthread_mutex_t gParcelGlobalAllocSizeLock = PTHREAD_MUTEX_INITIALIZER; +static size_t gParcelGlobalAllocSize = 0; +static size_t gParcelGlobalAllocCount = 0; static size_t gMaxFds = 0; @@ -170,11 +164,14 @@ static void release_object(const sp<ProcessState>& proc, ALOGE("Invalid object type 0x%08x", obj.hdr.type); } -status_t Parcel::finishFlattenBinder(const sp<IBinder>& binder) +status_t Parcel::finishFlattenBinder( + const sp<IBinder>& binder, const flat_binder_object& flat) { + status_t status = writeObject(flat, false); + if (status != OK) return status; + internal::Stability::tryMarkCompilationUnit(binder.get()); - auto category = internal::Stability::getCategory(binder.get()); - return writeInt32(category.repr()); + return writeInt32(internal::Stability::get(binder.get())); } status_t Parcel::finishUnflattenBinder( @@ -184,41 +181,23 @@ status_t Parcel::finishUnflattenBinder( status_t status = readInt32(&stability); if (status != OK) return status; - status = internal::Stability::setRepr(binder.get(), stability, true /*log*/); + status = internal::Stability::set(binder.get(), stability, true /*log*/); if (status != OK) return status; *out = binder; return OK; } -static constexpr inline int schedPolicyMask(int policy, int priority) { - return (priority & FLAT_BINDER_FLAG_PRIORITY_MASK) | ((policy & 3) << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT); -} - status_t Parcel::flattenBinder(const sp<IBinder>& binder) { - if (isForRpc()) { - if (binder) { - status_t status = writeInt32(1); // non-null - if (status != OK) return status; - RpcAddress address = RpcAddress::zero(); - status = mSession->state()->onBinderLeaving(mSession, binder, &address); - if (status != OK) return status; - status = address.writeToParcel(this); - if (status != OK) return status; - } else { - status_t status = writeInt32(0); // null - if (status != OK) return status; - } - return finishFlattenBinder(binder); - } - flat_binder_object obj; - obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS; - int schedBits = 0; - if (!IPCThreadState::self()->backgroundSchedulingDisabled()) { - schedBits = schedPolicyMask(SCHED_NORMAL, 19); + if (IPCThreadState::self()->backgroundSchedulingDisabled()) { + /* minimum priority for all nodes is nice 0 */ + obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS; + } else { + /* minimum priority for all nodes is MAX_NICE(19) */ + obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS; } if (binder != nullptr) { @@ -227,31 +206,16 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) BpBinder *proxy = binder->remoteBinder(); if (proxy == nullptr) { ALOGE("null proxy"); - } else { - if (proxy->isRpcBinder()) { - ALOGE("Sending a socket binder over RPC is prohibited"); - return INVALID_OPERATION; - } } - const int32_t handle = proxy ? proxy->getPrivateAccessorForId().binderHandle() : 0; + const int32_t handle = proxy ? proxy->handle() : 0; obj.hdr.type = BINDER_TYPE_HANDLE; obj.binder = 0; /* Don't pass uninitialized stack data to a remote process */ obj.handle = handle; obj.cookie = 0; } else { - int policy = local->getMinSchedulerPolicy(); - int priority = local->getMinSchedulerPriority(); - - if (policy != 0 || priority != 0) { - // override value, since it is set explicitly - schedBits = schedPolicyMask(policy, priority); - } if (local->isRequestingSid()) { obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX; } - if (local->isInheritRt()) { - obj.flags |= FLAT_BINDER_FLAG_INHERIT_RT; - } obj.hdr.type = BINDER_TYPE_BINDER; obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs()); obj.cookie = reinterpret_cast<uintptr_t>(local); @@ -262,42 +226,17 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) obj.cookie = 0; } - obj.flags |= schedBits; - - status_t status = writeObject(obj, false); - if (status != OK) return status; - - return finishFlattenBinder(binder); + return finishFlattenBinder(binder, obj); } status_t Parcel::unflattenBinder(sp<IBinder>* out) const { - if (isForRpc()) { - LOG_ALWAYS_FATAL_IF(mSession == nullptr, "RpcSession required to read from remote parcel"); - - int32_t isNull; - status_t status = readInt32(&isNull); - if (status != OK) return status; - - sp<IBinder> binder; - - if (isNull & 1) { - auto addr = RpcAddress::zero(); - status_t status = addr.readFromParcel(*this); - if (status != OK) return status; - binder = mSession->state()->onBinderEntering(mSession, addr); - } - - return finishUnflattenBinder(binder, out); - } - const flat_binder_object* flat = readObject(false); if (flat) { switch (flat->hdr.type) { case BINDER_TYPE_BINDER: { - sp<IBinder> binder = - sp<IBinder>::fromExisting(reinterpret_cast<IBinder*>(flat->cookie)); + sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie); return finishUnflattenBinder(binder, out); } case BINDER_TYPE_HANDLE: { @@ -325,11 +264,17 @@ Parcel::~Parcel() } size_t Parcel::getGlobalAllocSize() { - return gParcelGlobalAllocSize.load(); + pthread_mutex_lock(&gParcelGlobalAllocSizeLock); + size_t size = gParcelGlobalAllocSize; + pthread_mutex_unlock(&gParcelGlobalAllocSizeLock); + return size; } size_t Parcel::getGlobalAllocCount() { - return gParcelGlobalAllocCount.load(); + pthread_mutex_lock(&gParcelGlobalAllocSizeLock); + size_t count = gParcelGlobalAllocCount; + pthread_mutex_unlock(&gParcelGlobalAllocSizeLock); + return count; } const uint8_t* Parcel::data() const @@ -422,11 +367,6 @@ status_t Parcel::setData(const uint8_t* buffer, size_t len) status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len) { - if (parcel->isForRpc() != isForRpc()) { - ALOGE("Cannot append Parcel of one format to another."); - return BAD_TYPE; - } - status_t err; const uint8_t *data = parcel->mData; const binder_size_t *objects = parcel->mObjects; @@ -558,31 +498,6 @@ bool Parcel::hasFileDescriptors() const return mHasFds; } -void Parcel::markSensitive() const -{ - mDeallocZero = true; -} - -void Parcel::markForBinder(const sp<IBinder>& binder) { - LOG_ALWAYS_FATAL_IF(mData != nullptr, "format must be set before data is written"); - - if (binder && binder->remoteBinder() && binder->remoteBinder()->isRpcBinder()) { - markForRpc(binder->remoteBinder()->getPrivateAccessorForId().rpcSession()); - } -} - -void Parcel::markForRpc(const sp<RpcSession>& session) { - LOG_ALWAYS_FATAL_IF(mData != nullptr && mOwner == nullptr, - "format must be set before data is written OR on IPC data"); - - LOG_ALWAYS_FATAL_IF(session == nullptr, "markForRpc requires session"); - mSession = session; -} - -bool Parcel::isForRpc() const { - return mSession != nullptr; -} - void Parcel::updateWorkSourceRequestHeaderPosition() const { // Only update the request headers once. We only want to point // to the first headers read/written. @@ -592,7 +507,7 @@ void Parcel::updateWorkSourceRequestHeaderPosition() const { } } -#if defined(__ANDROID_VNDK__) +#if defined(__ANDROID_VNDK__) && !defined(__ANDROID_APEX__) constexpr int32_t kHeader = B_PACK_CHARS('V', 'N', 'D', 'R'); #else constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T'); @@ -601,21 +516,14 @@ constexpr int32_t kHeader = B_PACK_CHARS('S', 'Y', 'S', 'T'); // Write RPC headers. (previously just the interface token) status_t Parcel::writeInterfaceToken(const String16& interface) { - return writeInterfaceToken(interface.string(), interface.size()); -} - -status_t Parcel::writeInterfaceToken(const char16_t* str, size_t len) { - if (CC_LIKELY(!isForRpc())) { - const IPCThreadState* threadState = IPCThreadState::self(); - writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER); - updateWorkSourceRequestHeaderPosition(); - writeInt32(threadState->shouldPropagateWorkSource() ? threadState->getCallingWorkSourceUid() - : IPCThreadState::kUnsetWorkSource); - writeInt32(kHeader); - } - + const IPCThreadState* threadState = IPCThreadState::self(); + writeInt32(threadState->getStrictModePolicy() | STRICT_MODE_PENALTY_GATHER); + updateWorkSourceRequestHeaderPosition(); + writeInt32(threadState->shouldPropagateWorkSource() ? + threadState->getCallingWorkSourceUid() : IPCThreadState::kUnsetWorkSource); + writeInt32(kHeader); // currently the interface identification token is just its name as a string - return writeString16(str, len); + return writeString16(interface); } bool Parcel::replaceCallingWorkSourceUid(uid_t uid) @@ -659,34 +567,31 @@ bool Parcel::enforceInterface(const char16_t* interface, size_t len, IPCThreadState* threadState) const { - if (CC_LIKELY(!isForRpc())) { - // StrictModePolicy. - int32_t strictPolicy = readInt32(); - if (threadState == nullptr) { - threadState = IPCThreadState::self(); - } - if ((threadState->getLastTransactionBinderFlags() & IBinder::FLAG_ONEWAY) != 0) { - // For one-way calls, the callee is running entirely - // disconnected from the caller, so disable StrictMode entirely. - // Not only does disk/network usage not impact the caller, but - // there's no way to communicate back violations anyway. - threadState->setStrictModePolicy(0); - } else { - threadState->setStrictModePolicy(strictPolicy); - } - // WorkSource. - updateWorkSourceRequestHeaderPosition(); - int32_t workSource = readInt32(); - threadState->setCallingWorkSourceUidWithoutPropagation(workSource); - // vendor header - int32_t header = readInt32(); - if (header != kHeader) { - ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, - header); - return false; - } + // StrictModePolicy. + int32_t strictPolicy = readInt32(); + if (threadState == nullptr) { + threadState = IPCThreadState::self(); + } + if ((threadState->getLastTransactionBinderFlags() & + IBinder::FLAG_ONEWAY) != 0) { + // For one-way calls, the callee is running entirely + // disconnected from the caller, so disable StrictMode entirely. + // Not only does disk/network usage not impact the caller, but + // there's no way to commuicate back any violations anyway. + threadState->setStrictModePolicy(0); + } else { + threadState->setStrictModePolicy(strictPolicy); + } + // WorkSource. + updateWorkSourceRequestHeaderPosition(); + int32_t workSource = readInt32(); + threadState->setCallingWorkSourceUidWithoutPropagation(workSource); + // vendor header + int32_t header = readInt32(); + if (header != kHeader) { + ALOGE("Expecting header 0x%x but found 0x%x. Mixing copies of libbinder?", kHeader, header); + return false; } - // Interface descriptor. size_t parcel_interface_len; const char16_t* parcel_interface = readString16Inplace(&parcel_interface_len); @@ -846,116 +751,135 @@ status_t Parcel::writeUtf8AsUtf16(const std::string& str) { return NO_ERROR; } +status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) { + if (!str) { + return writeInt32(-1); + } + return writeUtf8AsUtf16(*str); +} -status_t Parcel::writeUtf8AsUtf16(const std::optional<std::string>& str) { return writeData(str); } -status_t Parcel::writeUtf8AsUtf16(const std::unique_ptr<std::string>& str) { return writeData(str); } - -status_t Parcel::writeString16(const std::optional<String16>& str) { return writeData(str); } -status_t Parcel::writeString16(const std::unique_ptr<String16>& str) { return writeData(str); } - -status_t Parcel::writeByteVector(const std::vector<int8_t>& val) { return writeData(val); } -status_t Parcel::writeByteVector(const std::optional<std::vector<int8_t>>& val) { return writeData(val); } -status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) { return writeData(val); } -status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) { return writeData(val); } -status_t Parcel::writeByteVector(const std::optional<std::vector<uint8_t>>& val) { return writeData(val); } -status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val){ return writeData(val); } -status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val) { return writeData(val); } -status_t Parcel::writeInt32Vector(const std::optional<std::vector<int32_t>>& val) { return writeData(val); } -status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) { return writeData(val); } -status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val) { return writeData(val); } -status_t Parcel::writeInt64Vector(const std::optional<std::vector<int64_t>>& val) { return writeData(val); } -status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) { return writeData(val); } -status_t Parcel::writeUint64Vector(const std::vector<uint64_t>& val) { return writeData(val); } -status_t Parcel::writeUint64Vector(const std::optional<std::vector<uint64_t>>& val) { return writeData(val); } -status_t Parcel::writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) { return writeData(val); } -status_t Parcel::writeFloatVector(const std::vector<float>& val) { return writeData(val); } -status_t Parcel::writeFloatVector(const std::optional<std::vector<float>>& val) { return writeData(val); } -status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val) { return writeData(val); } -status_t Parcel::writeDoubleVector(const std::vector<double>& val) { return writeData(val); } -status_t Parcel::writeDoubleVector(const std::optional<std::vector<double>>& val) { return writeData(val); } -status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) { return writeData(val); } -status_t Parcel::writeBoolVector(const std::vector<bool>& val) { return writeData(val); } -status_t Parcel::writeBoolVector(const std::optional<std::vector<bool>>& val) { return writeData(val); } -status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) { return writeData(val); } -status_t Parcel::writeCharVector(const std::vector<char16_t>& val) { return writeData(val); } -status_t Parcel::writeCharVector(const std::optional<std::vector<char16_t>>& val) { return writeData(val); } -status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) { return writeData(val); } - -status_t Parcel::writeString16Vector(const std::vector<String16>& val) { return writeData(val); } -status_t Parcel::writeString16Vector( - const std::optional<std::vector<std::optional<String16>>>& val) { return writeData(val); } -status_t Parcel::writeString16Vector( - const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) { return writeData(val); } -status_t Parcel::writeUtf8VectorAsUtf16Vector( - const std::optional<std::vector<std::optional<std::string>>>& val) { return writeData(val); } -status_t Parcel::writeUtf8VectorAsUtf16Vector( - const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) { return writeData(val); } -status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) { return writeData(val); } - -status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) { return writeData(val); } -status_t Parcel::writeUniqueFileDescriptorVector(const std::optional<std::vector<base::unique_fd>>& val) { return writeData(val); } -status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) { return writeData(val); } - -status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val) { return writeData(val); } -status_t Parcel::writeStrongBinderVector(const std::optional<std::vector<sp<IBinder>>>& val) { return writeData(val); } -status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) { return writeData(val); } - -status_t Parcel::writeParcelable(const Parcelable& parcelable) { return writeData(parcelable); } - -status_t Parcel::readUtf8FromUtf16(std::optional<std::string>* str) const { return readData(str); } -status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const { return readData(str); } - -status_t Parcel::readString16(std::optional<String16>* pArg) const { return readData(pArg); } -status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const { return readData(pArg); } - -status_t Parcel::readByteVector(std::vector<int8_t>* val) const { return readData(val); } -status_t Parcel::readByteVector(std::vector<uint8_t>* val) const { return readData(val); } -status_t Parcel::readByteVector(std::optional<std::vector<int8_t>>* val) const { return readData(val); } -status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const { return readData(val); } -status_t Parcel::readByteVector(std::optional<std::vector<uint8_t>>* val) const { return readData(val); } -status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const { return readData(val); } -status_t Parcel::readInt32Vector(std::optional<std::vector<int32_t>>* val) const { return readData(val); } -status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const { return readData(val); } -status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const { return readData(val); } -status_t Parcel::readInt64Vector(std::optional<std::vector<int64_t>>* val) const { return readData(val); } -status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const { return readData(val); } -status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const { return readData(val); } -status_t Parcel::readUint64Vector(std::optional<std::vector<uint64_t>>* val) const { return readData(val); } -status_t Parcel::readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const { return readData(val); } -status_t Parcel::readUint64Vector(std::vector<uint64_t>* val) const { return readData(val); } -status_t Parcel::readFloatVector(std::optional<std::vector<float>>* val) const { return readData(val); } -status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const { return readData(val); } -status_t Parcel::readFloatVector(std::vector<float>* val) const { return readData(val); } -status_t Parcel::readDoubleVector(std::optional<std::vector<double>>* val) const { return readData(val); } -status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const { return readData(val); } -status_t Parcel::readDoubleVector(std::vector<double>* val) const { return readData(val); } -status_t Parcel::readBoolVector(std::optional<std::vector<bool>>* val) const { return readData(val); } -status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { return readData(val); } -status_t Parcel::readBoolVector(std::vector<bool>* val) const { return readData(val); } -status_t Parcel::readCharVector(std::optional<std::vector<char16_t>>* val) const { return readData(val); } -status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const { return readData(val); } -status_t Parcel::readCharVector(std::vector<char16_t>* val) const { return readData(val); } +status_t Parcel::writeByteVectorInternal(const int8_t* data, size_t size) { + if (size > std::numeric_limits<int32_t>::max()) { + return BAD_VALUE; + } -status_t Parcel::readString16Vector( - std::optional<std::vector<std::optional<String16>>>* val) const { return readData(val); } -status_t Parcel::readString16Vector( - std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const { return readData(val); } -status_t Parcel::readString16Vector(std::vector<String16>* val) const { return readData(val); } -status_t Parcel::readUtf8VectorFromUtf16Vector( - std::optional<std::vector<std::optional<std::string>>>* val) const { return readData(val); } -status_t Parcel::readUtf8VectorFromUtf16Vector( - std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const { return readData(val); } -status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const { return readData(val); } + status_t status = writeInt32(size); + if (status != OK) { + return status; + } + + return write(data, size); +} + +status_t Parcel::writeByteVector(const std::vector<int8_t>& val) { + return writeByteVectorInternal(val.data(), val.size()); +} + +status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val) +{ + if (!val) return writeInt32(-1); + return writeByteVectorInternal(val->data(), val->size()); +} + +status_t Parcel::writeByteVector(const std::vector<uint8_t>& val) { + return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val.data()), val.size()); +} + +status_t Parcel::writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val) +{ + if (!val) return writeInt32(-1); + return writeByteVectorInternal(reinterpret_cast<const int8_t*>(val->data()), val->size()); +} + +status_t Parcel::writeInt32Vector(const std::vector<int32_t>& val) +{ + return writeTypedVector(val, &Parcel::writeInt32); +} + +status_t Parcel::writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeInt32); +} + +status_t Parcel::writeInt64Vector(const std::vector<int64_t>& val) +{ + return writeTypedVector(val, &Parcel::writeInt64); +} + +status_t Parcel::writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeInt64); +} + +status_t Parcel::writeUint64Vector(const std::vector<uint64_t>& val) +{ + return writeTypedVector(val, &Parcel::writeUint64); +} + +status_t Parcel::writeUint64Vector(const std::unique_ptr<std::vector<uint64_t>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeUint64); +} + +status_t Parcel::writeFloatVector(const std::vector<float>& val) +{ + return writeTypedVector(val, &Parcel::writeFloat); +} + +status_t Parcel::writeFloatVector(const std::unique_ptr<std::vector<float>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeFloat); +} -status_t Parcel::readUniqueFileDescriptorVector(std::optional<std::vector<base::unique_fd>>* val) const { return readData(val); } -status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const { return readData(val); } -status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const { return readData(val); } +status_t Parcel::writeDoubleVector(const std::vector<double>& val) +{ + return writeTypedVector(val, &Parcel::writeDouble); +} + +status_t Parcel::writeDoubleVector(const std::unique_ptr<std::vector<double>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeDouble); +} + +status_t Parcel::writeBoolVector(const std::vector<bool>& val) +{ + return writeTypedVector(val, &Parcel::writeBool); +} + +status_t Parcel::writeBoolVector(const std::unique_ptr<std::vector<bool>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeBool); +} -status_t Parcel::readStrongBinderVector(std::optional<std::vector<sp<IBinder>>>* val) const { return readData(val); } -status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const { return readData(val); } -status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const { return readData(val); } +status_t Parcel::writeCharVector(const std::vector<char16_t>& val) +{ + return writeTypedVector(val, &Parcel::writeChar); +} -status_t Parcel::readParcelable(Parcelable* parcelable) const { return readData(parcelable); } +status_t Parcel::writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeChar); +} + +status_t Parcel::writeString16Vector(const std::vector<String16>& val) +{ + return writeTypedVector(val, &Parcel::writeString16); +} + +status_t Parcel::writeString16Vector( + const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeString16); +} + +status_t Parcel::writeUtf8VectorAsUtf16Vector( + const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val) { + return writeNullableTypedVector(val, &Parcel::writeUtf8AsUtf16); +} + +status_t Parcel::writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val) { + return writeTypedVector(val, &Parcel::writeUtf8AsUtf16); +} status_t Parcel::writeInt32(int32_t val) { @@ -1070,7 +994,6 @@ status_t Parcel::writeString8(const char* str, size_t len) { if (str == nullptr) return writeInt32(-1); - // NOTE: Keep this logic in sync with android_os_Parcel.cpp status_t err = writeInt32(len); if (err == NO_ERROR) { uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char)); @@ -1084,6 +1007,15 @@ status_t Parcel::writeString8(const char* str, size_t len) return err; } +status_t Parcel::writeString16(const std::unique_ptr<String16>& str) +{ + if (!str) { + return writeInt32(-1); + } + + return writeString16(*str); +} + status_t Parcel::writeString16(const String16& str) { return writeString16(str.string(), str.size()); @@ -1093,7 +1025,6 @@ status_t Parcel::writeString16(const char16_t* str, size_t len) { if (str == nullptr) return writeInt32(-1); - // NOTE: Keep this logic in sync with android_os_Parcel.cpp status_t err = writeInt32(len); if (err == NO_ERROR) { len *= sizeof(char16_t); @@ -1113,6 +1044,23 @@ status_t Parcel::writeStrongBinder(const sp<IBinder>& val) return flattenBinder(val); } +status_t Parcel::writeStrongBinderVector(const std::vector<sp<IBinder>>& val) +{ + return writeTypedVector(val, &Parcel::writeStrongBinder); +} + +status_t Parcel::writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val) +{ + return writeNullableTypedVector(val, &Parcel::writeStrongBinder); +} + +status_t Parcel::readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const { + return readNullableTypedVector(val, &Parcel::readNullableStrongBinder); +} + +status_t Parcel::readStrongBinderVector(std::vector<sp<IBinder>>* val) const { + return readTypedVector(val, &Parcel::readStrongBinder); +} status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) { if (!parcelable) { @@ -1122,6 +1070,14 @@ status_t Parcel::writeRawNullableParcelable(const Parcelable* parcelable) { return writeParcelable(*parcelable); } +status_t Parcel::writeParcelable(const Parcelable& parcelable) { + status_t status = writeInt32(1); // parcelable is not null. + if (status != OK) { + return status; + } + return parcelable.writeToParcel(this); +} + status_t Parcel::writeNativeHandle(const native_handle* handle) { if (!handle || handle->version != sizeof(native_handle)) @@ -1147,11 +1103,6 @@ status_t Parcel::writeNativeHandle(const native_handle* handle) status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership) { - if (isForRpc()) { - ALOGE("Cannot write file descriptor to remote binder."); - return BAD_TYPE; - } - flat_binder_object obj; obj.hdr.type = BINDER_TYPE_FD; obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; @@ -1197,6 +1148,14 @@ status_t Parcel::writeUniqueFileDescriptor(const base::unique_fd& fd) { return writeDupFileDescriptor(fd.get()); } +status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<base::unique_fd>& val) { + return writeTypedVector(val, &Parcel::writeUniqueFileDescriptor); +} + +status_t Parcel::writeUniqueFileDescriptorVector(const std::unique_ptr<std::vector<base::unique_fd>>& val) { + return writeNullableTypedVector(val, &Parcel::writeUniqueFileDescriptor); +} + status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob) { if (len > INT32_MAX) { @@ -1468,7 +1427,7 @@ const void* Parcel::readInplace(size_t len) const template<class T> status_t Parcel::readAligned(T *pArg) const { - static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); + COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); if ((mDataPos+sizeof(T)) <= mDataSize) { if (mObjectsSize > 0) { @@ -1501,7 +1460,7 @@ T Parcel::readAligned() const { template<class T> status_t Parcel::writeAligned(T val) { - static_assert(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); + COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); if ((mDataPos+sizeof(val)) <= mDataCapacity) { restart_write: @@ -1514,6 +1473,158 @@ restart_write: return err; } +status_t Parcel::readByteVector(std::vector<int8_t>* val) const { + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; + return readByteVectorInternal(val, size); +} + +status_t Parcel::readByteVector(std::vector<uint8_t>* val) const { + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; + return readByteVectorInternal(val, size); +} + +status_t Parcel::readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const { + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; + if (val->get() == nullptr) { + // reserveOutVector does not create the out vector if size is < 0. + // This occurs when writing a null byte vector. + return OK; + } + return readByteVectorInternal(val->get(), size); +} + +status_t Parcel::readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const { + size_t size; + if (status_t status = reserveOutVector(val, &size); status != OK) return status; + if (val->get() == nullptr) { + // reserveOutVector does not create the out vector if size is < 0. + // This occurs when writing a null byte vector. + return OK; + } + return readByteVectorInternal(val->get(), size); +} + +status_t Parcel::readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const { + return readNullableTypedVector(val, &Parcel::readInt32); +} + +status_t Parcel::readInt32Vector(std::vector<int32_t>* val) const { + return readTypedVector(val, &Parcel::readInt32); +} + +status_t Parcel::readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const { + return readNullableTypedVector(val, &Parcel::readInt64); +} + +status_t Parcel::readInt64Vector(std::vector<int64_t>* val) const { + return readTypedVector(val, &Parcel::readInt64); +} + +status_t Parcel::readUint64Vector(std::unique_ptr<std::vector<uint64_t>>* val) const { + return readNullableTypedVector(val, &Parcel::readUint64); +} + +status_t Parcel::readUint64Vector(std::vector<uint64_t>* val) const { + return readTypedVector(val, &Parcel::readUint64); +} + +status_t Parcel::readFloatVector(std::unique_ptr<std::vector<float>>* val) const { + return readNullableTypedVector(val, &Parcel::readFloat); +} + +status_t Parcel::readFloatVector(std::vector<float>* val) const { + return readTypedVector(val, &Parcel::readFloat); +} + +status_t Parcel::readDoubleVector(std::unique_ptr<std::vector<double>>* val) const { + return readNullableTypedVector(val, &Parcel::readDouble); +} + +status_t Parcel::readDoubleVector(std::vector<double>* val) const { + return readTypedVector(val, &Parcel::readDouble); +} + +status_t Parcel::readBoolVector(std::unique_ptr<std::vector<bool>>* val) const { + const int32_t start = dataPosition(); + int32_t size; + status_t status = readInt32(&size); + val->reset(); + + if (status != OK || size < 0) { + return status; + } + + setDataPosition(start); + val->reset(new (std::nothrow) std::vector<bool>()); + + status = readBoolVector(val->get()); + + if (status != OK) { + val->reset(); + } + + return status; +} + +status_t Parcel::readBoolVector(std::vector<bool>* val) const { + int32_t size; + status_t status = readInt32(&size); + + if (status != OK) { + return status; + } + + if (size < 0) { + return UNEXPECTED_NULL; + } + + val->resize(size); + + /* C++ bool handling means a vector of bools isn't necessarily addressable + * (we might use individual bits) + */ + bool data; + for (int32_t i = 0; i < size; ++i) { + status = readBool(&data); + (*val)[i] = data; + + if (status != OK) { + return status; + } + } + + return OK; +} + +status_t Parcel::readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const { + return readNullableTypedVector(val, &Parcel::readChar); +} + +status_t Parcel::readCharVector(std::vector<char16_t>* val) const { + return readTypedVector(val, &Parcel::readChar); +} + +status_t Parcel::readString16Vector( + std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const { + return readNullableTypedVector(val, &Parcel::readString16); +} + +status_t Parcel::readString16Vector(std::vector<String16>* val) const { + return readTypedVector(val, &Parcel::readString16); +} + +status_t Parcel::readUtf8VectorFromUtf16Vector( + std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const { + return readNullableTypedVector(val, &Parcel::readUtf8FromUtf16); +} + +status_t Parcel::readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const { + return readTypedVector(val, &Parcel::readUtf8FromUtf16); +} + status_t Parcel::readInt32(int32_t *pArg) const { return readAligned(pArg); @@ -1621,6 +1732,17 @@ double Parcel::readDouble() const #endif +status_t Parcel::readIntPtr(intptr_t *pArg) const +{ + return readAligned(pArg); +} + + +intptr_t Parcel::readIntPtr() const +{ + return readAligned<intptr_t>(); +} + status_t Parcel::readBool(bool *pArg) const { int32_t tmp = 0; @@ -1686,6 +1808,21 @@ status_t Parcel::readUtf8FromUtf16(std::string* str) const { return NO_ERROR; } +status_t Parcel::readUtf8FromUtf16(std::unique_ptr<std::string>* str) const { + const int32_t start = dataPosition(); + int32_t size; + status_t status = readInt32(&size); + str->reset(); + + if (status != OK || size < 0) { + return status; + } + + setDataPosition(start); + str->reset(new (std::nothrow) std::string()); + return readUtf8FromUtf16(str->get()); +} + const char* Parcel::readCString() const { if (mDataPos < mDataSize) { @@ -1752,6 +1889,28 @@ String16 Parcel::readString16() const return String16(); } +status_t Parcel::readString16(std::unique_ptr<String16>* pArg) const +{ + const int32_t start = dataPosition(); + int32_t size; + status_t status = readInt32(&size); + pArg->reset(); + + if (status != OK || size < 0) { + return status; + } + + setDataPosition(start); + pArg->reset(new (std::nothrow) String16()); + + status = readString16(pArg->get()); + + if (status != OK) { + pArg->reset(); + } + + return status; +} status_t Parcel::readString16(String16* pArg) const { @@ -1808,6 +1967,18 @@ sp<IBinder> Parcel::readStrongBinder() const return val; } +status_t Parcel::readParcelable(Parcelable* parcelable) const { + int32_t have_parcelable = 0; + status_t status = readInt32(&have_parcelable); + if (status != OK) { + return status; + } + if (!have_parcelable) { + return UNEXPECTED_NULL; + } + return parcelable->readFromParcel(this); +} + int32_t Parcel::readExceptionCode() const { binder::Status status; @@ -1883,7 +2054,7 @@ int Parcel::readParcelFileDescriptor() const ssize_t written = TEMP_FAILURE_RETRY( ::write(comm, &message, sizeof(message))); - if (written != sizeof(message)) { + if (written == -1 || written != sizeof(message)) { ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s", written, strerror(errno)); return BAD_TYPE; @@ -1926,6 +2097,14 @@ status_t Parcel::readUniqueParcelFileDescriptor(base::unique_fd* val) const return OK; } +status_t Parcel::readUniqueFileDescriptorVector(std::unique_ptr<std::vector<base::unique_fd>>* val) const { + return readNullableTypedVector(val, &Parcel::readUniqueFileDescriptor); +} + +status_t Parcel::readUniqueFileDescriptorVector(std::vector<base::unique_fd>* val) const { + return readTypedVector(val, &Parcel::readUniqueFileDescriptor); +} + status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const { int32_t blobType; @@ -2112,20 +2291,22 @@ size_t Parcel::ipcObjectsCount() const } void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, - const binder_size_t* objects, size_t objectsCount, release_func relFunc) + const binder_size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie) { - // this code uses 'mOwner == nullptr' to understand whether it owns memory - LOG_ALWAYS_FATAL_IF(relFunc == nullptr, "must provide cleanup function"); - - freeData(); - + binder_size_t minOffset = 0; + freeDataNoInit(); + mError = NO_ERROR; mData = const_cast<uint8_t*>(data); mDataSize = mDataCapacity = dataSize; + //ALOGI("setDataReference Setting data size of %p to %lu (pid=%d)", this, mDataSize, getpid()); + mDataPos = 0; + ALOGV("setDataReference Setting data pos of %p to %zu", this, mDataPos); mObjects = const_cast<binder_size_t*>(objects); mObjectsSize = mObjectsCapacity = objectsCount; + mNextObjectHint = 0; + mObjectsSorted = false; mOwner = relFunc; - - binder_size_t minOffset = 0; + mOwnerCookie = relCookie; for (size_t i = 0; i < mObjectsSize; i++) { binder_size_t offset = mObjects[i]; if (offset < minOffset) { @@ -2141,12 +2322,14 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, type == BINDER_TYPE_FD)) { // We should never receive other types (eg BINDER_TYPE_FDA) as long as we don't support // them in libbinder. If we do receive them, it probably means a kernel bug; try to - // recover gracefully by clearing out the objects, and releasing the objects we do - // know about. + // recover gracefully by clearing out the objects. android_errorWriteLog(0x534e4554, "135930648"); + android_errorWriteLog(0x534e4554, "203847542"); ALOGE("%s: unsupported type object (%" PRIu32 ") at offset %" PRIu64 "\n", __func__, type, (uint64_t)offset); - releaseObjects(); + + // WARNING: callers of ipcSetDataReference need to make sure they + // don't rely on mObjectsSize in their release_func. mObjectsSize = 0; break; } @@ -2226,17 +2409,22 @@ void Parcel::freeDataNoInit() if (mOwner) { LOG_ALLOC("Parcel %p: freeing other owner data", this); //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid()); - mOwner(this, mData, mDataSize, mObjects, mObjectsSize); + mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie); } else { LOG_ALLOC("Parcel %p: freeing allocated data", this); releaseObjects(); if (mData) { LOG_ALLOC("Parcel %p: freeing with %zu capacity", this, mDataCapacity); - gParcelGlobalAllocSize -= mDataCapacity; - gParcelGlobalAllocCount--; - if (mDeallocZero) { - zeroMemory(mData, mDataSize); + pthread_mutex_lock(&gParcelGlobalAllocSizeLock); + if (mDataCapacity <= gParcelGlobalAllocSize) { + gParcelGlobalAllocSize = gParcelGlobalAllocSize - mDataCapacity; + } else { + gParcelGlobalAllocSize = 0; + } + if (gParcelGlobalAllocCount > 0) { + gParcelGlobalAllocCount--; } + pthread_mutex_unlock(&gParcelGlobalAllocSizeLock); free(mData); } if (mObjects) free(mObjects); @@ -2256,22 +2444,7 @@ status_t Parcel::growData(size_t len) size_t newSize = ((mDataSize+len)*3)/2; return (newSize <= mDataSize) ? (status_t) NO_MEMORY - : 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; + : continueWrite(newSize); } status_t Parcel::restartWrite(size_t desired) @@ -2287,7 +2460,7 @@ status_t Parcel::restartWrite(size_t desired) return continueWrite(desired); } - uint8_t* data = reallocZeroFree(mData, mDataCapacity, desired, mDeallocZero); + uint8_t* data = (uint8_t*)realloc(mData, desired); if (!data && desired > mDataCapacity) { mError = NO_MEMORY; return NO_MEMORY; @@ -2295,17 +2468,15 @@ status_t Parcel::restartWrite(size_t desired) releaseObjects(); - if (data || desired == 0) { + if (data) { LOG_ALLOC("Parcel %p: restart from %zu to %zu capacity", this, mDataCapacity, desired); - if (mDataCapacity > desired) { - gParcelGlobalAllocSize -= (mDataCapacity - desired); - } else { - gParcelGlobalAllocSize += (desired - mDataCapacity); - } - + pthread_mutex_lock(&gParcelGlobalAllocSizeLock); + gParcelGlobalAllocSize += desired; + gParcelGlobalAllocSize -= mDataCapacity; if (!mData) { gParcelGlobalAllocCount++; } + pthread_mutex_unlock(&gParcelGlobalAllocSizeLock); mData = data; mDataCapacity = desired; } @@ -2389,12 +2560,14 @@ status_t Parcel::continueWrite(size_t desired) memcpy(objects, mObjects, objectsSize*sizeof(binder_size_t)); } //ALOGI("Freeing data ref of %p (pid=%d)", this, getpid()); - mOwner(this, mData, mDataSize, mObjects, mObjectsSize); + mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie); mOwner = nullptr; LOG_ALLOC("Parcel %p: taking ownership of %zu capacity", this, desired); + pthread_mutex_lock(&gParcelGlobalAllocSizeLock); gParcelGlobalAllocSize += desired; gParcelGlobalAllocCount++; + pthread_mutex_unlock(&gParcelGlobalAllocSizeLock); mData = data; mObjects = objects; @@ -2438,12 +2611,14 @@ status_t Parcel::continueWrite(size_t desired) // We own the data, so we can just do a realloc(). if (desired > mDataCapacity) { - uint8_t* data = reallocZeroFree(mData, mDataCapacity, desired, mDeallocZero); + uint8_t* data = (uint8_t*)realloc(mData, desired); if (data) { LOG_ALLOC("Parcel %p: continue from %zu to %zu capacity", this, mDataCapacity, desired); + pthread_mutex_lock(&gParcelGlobalAllocSizeLock); gParcelGlobalAllocSize += desired; gParcelGlobalAllocSize -= mDataCapacity; + pthread_mutex_unlock(&gParcelGlobalAllocSizeLock); mData = data; mDataCapacity = desired; } else { @@ -2475,8 +2650,10 @@ status_t Parcel::continueWrite(size_t desired) } LOG_ALLOC("Parcel %p: allocating with %zu capacity", this, desired); + pthread_mutex_lock(&gParcelGlobalAllocSizeLock); gParcelGlobalAllocSize += desired; gParcelGlobalAllocCount++; + pthread_mutex_unlock(&gParcelGlobalAllocSizeLock); mData = data; mDataSize = mDataPos = 0; @@ -2498,7 +2675,6 @@ void Parcel::initState() mDataPos = 0; ALOGV("initState Setting data size of %p to %zu", this, mDataSize); ALOGV("initState Setting data pos of %p to %zu", this, mDataPos); - mSession = nullptr; mObjects = nullptr; mObjectsSize = 0; mObjectsCapacity = 0; @@ -2507,7 +2683,6 @@ void Parcel::initState() mHasFds = false; mFdsKnown = true; mAllowFds = true; - mDeallocZero = false; mOwner = nullptr; mOpenAshmemSize = 0; mWorkSourceRequestHeaderPosition = 0; |