Merge branch 'dev/11/fp3/security-aosp-rvc-release' into int/11/fp3
* dev/11/fp3/security-aosp-rvc-release:
Update uid state based on capability field
httplive: fix use-after-free
Fix heap-use-after-free issue flagged by fuzzer test.
Fix for heap buffer overflow issue flagged by fuzzer test.
Change-Id: I8429f9786cf09d61376da8f13984f297cefb1d89
diff --git a/media/libstagefright/foundation/MetaDataBase.cpp b/media/libstagefright/foundation/MetaDataBase.cpp
index 4b439c6..bb32385 100644
--- a/media/libstagefright/foundation/MetaDataBase.cpp
+++ b/media/libstagefright/foundation/MetaDataBase.cpp
@@ -23,6 +23,8 @@
#include <stdlib.h>
#include <string.h>
+#include <mutex>
+
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/hexdump.h>
@@ -78,6 +80,7 @@
struct MetaDataBase::MetaDataInternal {
+ std::mutex mLock;
KeyedVector<uint32_t, MetaDataBase::typed_data> mItems;
};
@@ -102,10 +105,12 @@
}
void MetaDataBase::clear() {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
mInternalData->mItems.clear();
}
bool MetaDataBase::remove(uint32_t key) {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -252,6 +257,7 @@
uint32_t key, uint32_t type, const void *data, size_t size) {
bool overwrote_existing = true;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
typed_data item;
@@ -269,6 +275,7 @@
bool MetaDataBase::findData(uint32_t key, uint32_t *type,
const void **data, size_t *size) const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -283,6 +290,7 @@
}
bool MetaDataBase::hasData(uint32_t key) const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
ssize_t i = mInternalData->mItems.indexOfKey(key);
if (i < 0) {
@@ -429,6 +437,7 @@
String8 MetaDataBase::toString() const {
String8 s;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
for (int i = mInternalData->mItems.size(); --i >= 0;) {
int32_t key = mInternalData->mItems.keyAt(i);
char cc[5];
@@ -443,6 +452,7 @@
}
void MetaDataBase::dumpToLog() const {
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
for (int i = mInternalData->mItems.size(); --i >= 0;) {
int32_t key = mInternalData->mItems.keyAt(i);
char cc[5];
@@ -455,6 +465,7 @@
#ifndef __ANDROID_VNDK__
status_t MetaDataBase::writeToParcel(Parcel &parcel) {
status_t ret;
+ std::lock_guard<std::mutex> guard(mInternalData->mLock);
size_t numItems = mInternalData->mItems.size();
ret = parcel.writeUint32(uint32_t(numItems));
if (ret) {
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index bd6a6c6..09eb96a 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -296,6 +296,10 @@
}
void MtpFfsHandle::close() {
+ auto timeout = std::chrono::seconds(2);
+ std::unique_lock lk(m);
+ cv.wait_for(lk, timeout ,[this]{return child_threads==0;});
+
io_destroy(mCtx);
closeEndpoints();
closeConfig();
@@ -662,6 +666,11 @@
char *temp = new char[me.length];
memcpy(temp, me.data, me.length);
me.data = temp;
+
+ std::unique_lock lk(m);
+ child_threads++;
+ lk.unlock();
+
std::thread t([this, me]() { return this->doSendEvent(me); });
t.detach();
return 0;
@@ -673,6 +682,11 @@
if (static_cast<unsigned>(ret) != length)
PLOG(ERROR) << "Mtp error sending event thread!";
delete[] reinterpret_cast<char*>(me.data);
+
+ std::unique_lock lk(m);
+ child_threads--;
+ lk.unlock();
+ cv.notify_one();
}
} // namespace android
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index fe343f7..ae78db2 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -58,6 +58,10 @@
bool mCanceled;
+ std::mutex m;
+ std::condition_variable cv;
+ std::atomic<int> child_threads{0};
+
android::base::unique_fd mControl;
// "in" from the host's perspective => sink for mtp server
android::base::unique_fd mBulkIn;
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index 3b298a9..e4467bb 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -92,24 +92,46 @@
}
uint16_t MtpPacket::getUInt16(int offset) const {
- return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
+ if ((unsigned long)(offset+2) <= mBufferSize) {
+ return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
+ }
+ else {
+ ALOGE("offset for buffer read is greater than buffer size!");
+ abort();
+ }
}
uint32_t MtpPacket::getUInt32(int offset) const {
- return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
- ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
+ if ((unsigned long)(offset+4) <= mBufferSize) {
+ return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
+ ((uint32_t)mBuffer[offset + 1] << 8) | (uint32_t)mBuffer[offset];
+ }
+ else {
+ ALOGE("offset for buffer read is greater than buffer size!");
+ abort();
+ }
}
void MtpPacket::putUInt16(int offset, uint16_t value) {
- mBuffer[offset++] = (uint8_t)(value & 0xFF);
- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+ if ((unsigned long)(offset+2) <= mBufferSize) {
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+ }
+ else {
+ ALOGE("offset for buffer write is greater than buffer size!");
+ }
}
void MtpPacket::putUInt32(int offset, uint32_t value) {
- mBuffer[offset++] = (uint8_t)(value & 0xFF);
- mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
- mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
- mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
+ if ((unsigned long)(offset+4) <= mBufferSize) {
+ mBuffer[offset++] = (uint8_t)(value & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
+ mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
+ }
+ else {
+ ALOGE("offset for buffer write is greater than buffer size!");
+ }
}
uint16_t MtpPacket::getContainerCode() const {
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index a511617..846d50a 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -21,9 +21,11 @@
#undef __STRICT_ANSI__
#define __STDINT_LIMITS
#define __STDC_LIMIT_MACROS
+#include <map>
#include <stdint.h>
#include <sys/time.h>
+#include <android/content/pm/IPackageManagerNative.h>
#include <audio_utils/clock.h>
#include <binder/IServiceManager.h>
#include <utils/Log.h>
@@ -54,6 +56,37 @@
static const String16 sManageAudioPolicyPermission("android.permission.MANAGE_AUDIO_POLICY");
+namespace {
+int getTargetSdkForPackageName(String16 packageName) {
+ const auto binder = defaultServiceManager()->checkService(String16{"package_native"});
+ int targetSdk = -1;
+ if (binder != nullptr) {
+ const auto pm = interface_cast<content::pm::IPackageManagerNative>(binder);
+ if (pm != nullptr) {
+ const auto status = pm->getTargetSdkVersionForPackage(packageName, &targetSdk);
+ ALOGI("Capy check package %s, sdk %d", String8(packageName).string(), targetSdk);
+ return status.isOk() ? targetSdk : -1;
+ }
+ }
+ return targetSdk;
+}
+
+bool doesUidTargetAtLeastU(uid_t uid) {
+ Vector<String16> packages;
+ PermissionController pc;
+ pc.getPackagesForUid(uid, packages);
+ constexpr int ANDROID_API_U = 34;
+ return packages.empty() || (getTargetSdkForPackageName(packages[0]) >= ANDROID_API_U);
+}
+
+bool doesUidTargetAtLeastUCached(uid_t uid) {
+ static std::map<uid_t, bool> cache;
+ const auto it = cache.find(uid);
+ return it == cache.end() ? (cache[uid] = doesUidTargetAtLeastU(uid)) : it->second;
+}
+
+
+} // anonymous
// ----------------------------------------------------------------------------
AudioPolicyService::AudioPolicyService()
@@ -1070,9 +1103,29 @@
void AudioPolicyService::UidPolicy::onUidStateChanged(uid_t uid,
int32_t procState,
int64_t procStateSeq __unused,
- int32_t capability __unused) {
+ int32_t capability) {
if (procState != ActivityManager::PROCESS_STATE_UNKNOWN) {
- updateUid(&mCachedUids, uid, true, procState, true);
+ if (doesUidTargetAtLeastUCached(uid)) {
+ // See ActivityManager.java
+ constexpr int32_t PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 1 << 2;
+ if (capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) {
+ // The implementation relies on the assumption that this callback is preceded by
+ // onUidActive. This may not be the case if we have lost and then regained the
+ // capability, since we simulate onUidIdle below. So, we simulate onUidActive.
+ // In the typical case where we haven't regained capability, this is a no-op, since
+ // we should've been preceded by an onUidActive callback anyway.
+ updateUid(&mCachedUids, uid, true /* active */,
+ ActivityManager::PROCESS_STATE_UNKNOWN, true /* insert */);
+ updateUid(&mCachedUids, uid, true /* active */, procState, true /* insert */);
+ } else {
+ // If we have lost the capability (e.g. moving to background), treat as-if we have
+ // gotten onUidIdle.
+ updateUid(&mCachedUids, uid, false /* active */,
+ ActivityManager::PROCESS_STATE_UNKNOWN, true /* insert */);
+ }
+ } else {
+ updateUid(&mCachedUids, uid, true, procState, true);
+ }
}
}