Allow MediaCodecs to be created on behalf of other client processes.
Requires the MEDIA_RESOURCE_PID_OVERRIDE permission.
Bug: 217746837
Test: atest MediaCodecResourceTest
Change-Id: Ib6214e42b74666e2959724bb5501ae71205cf11b
diff --git a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
index c81a659..2beb47f 100644
--- a/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
+++ b/media/libmediaplayerservice/tests/DrmSessionManager_test.cpp
@@ -61,7 +61,11 @@
return true;
}
- virtual bool isValidPid(int /* pid */) {
+ virtual bool isPidTrusted(int /* pid */) {
+ return true;
+ }
+
+ virtual bool isPidUidTrusted(int /* pid */, int /* uid */) {
return true;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 1ea3f99..fffe850 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -247,7 +247,7 @@
const std::shared_ptr<IResourceManagerClient> &client);
virtual ~ResourceManagerServiceProxy();
- void init();
+ status_t init();
// implements DeathRecipient
static void BinderDiedCallback(void* cookie);
@@ -276,6 +276,9 @@
pid_t pid, uid_t uid, const std::shared_ptr<IResourceManagerClient> &client)
: mPid(pid), mUid(uid), mClient(client),
mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {
+ if (mUid == MediaCodec::kNoUid) {
+ mUid = AIBinder_getCallingUid();
+ }
if (mPid == MediaCodec::kNoPid) {
mPid = AIBinder_getCallingPid();
}
@@ -294,12 +297,26 @@
}
}
-void MediaCodec::ResourceManagerServiceProxy::init() {
+status_t MediaCodec::ResourceManagerServiceProxy::init() {
::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
mService = IResourceManagerService::fromBinder(binder);
if (mService == nullptr) {
ALOGE("Failed to get ResourceManagerService");
- return;
+ return UNKNOWN_ERROR;
+ }
+
+ int callerPid = AIBinder_getCallingPid();
+ int callerUid = AIBinder_getCallingUid();
+ if (mPid != callerPid || mUid != callerUid) {
+ // Media processes don't need special permissions to act on behalf of other processes.
+ if (callerUid != AID_MEDIA) {
+ char const * permission = "android.permission.MEDIA_RESOURCE_OVERRIDE_PID";
+ if (!checkCallingPermission(String16(permission))) {
+ ALOGW("%s is required to override the caller's PID for media resource management.",
+ permission);
+ return PERMISSION_DENIED;
+ }
+ }
}
// Kill clients pending removal.
@@ -310,6 +327,7 @@
// after this, require mLock whenever using mService
AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
+ return OK;
}
//static
@@ -773,12 +791,7 @@
mInputBufferCounter(0),
mGetCodecBase(getCodecBase),
mGetCodecInfo(getCodecInfo) {
- if (uid == kNoUid) {
- mUid = AIBinder_getCallingUid();
- } else {
- mUid = uid;
- }
- mResourceManagerProxy = new ResourceManagerServiceProxy(pid, mUid,
+ mResourceManagerProxy = new ResourceManagerServiceProxy(pid, uid,
::ndk::SharedRefBase::make<ResourceManagerClient>(this));
if (!mGetCodecBase) {
mGetCodecBase = [](const AString &name, const char *owner) {
@@ -807,7 +820,6 @@
return NAME_NOT_FOUND;
};
}
-
initMediametrics();
}
@@ -1363,7 +1375,11 @@
}
status_t MediaCodec::init(const AString &name) {
- mResourceManagerProxy->init();
+ status_t err = mResourceManagerProxy->init();
+ if (err != OK) {
+ mCodec = NULL; // remove the codec
+ return err;
+ }
// save init parameters for reset
mInitName = name;
@@ -1378,7 +1394,7 @@
bool secureCodec = false;
const char *owner = "";
if (!name.startsWith("android.filter.")) {
- status_t err = mGetCodecInfo(name, &mCodecInfo);
+ err = mGetCodecInfo(name, &mCodecInfo);
if (err != OK) {
mCodec = NULL; // remove the codec.
return err;
@@ -1446,7 +1462,6 @@
mBatteryChecker = new BatteryChecker(new AMessage(kWhatCheckBatteryStats, this));
}
- status_t err;
std::vector<MediaResourceParcel> resources;
resources.push_back(MediaResource::CodecResource(secureCodec, mIsVideo));
for (int i = 0; i <= kMaxRetry; ++i) {
@@ -4599,7 +4614,6 @@
mCSD.erase(mCSD.begin());
std::shared_ptr<C2Buffer> c2Buffer;
sp<hardware::HidlMemory> memory;
- size_t offset = 0;
if (mFlags & kFlagUseBlockModel) {
if (hasCryptoOrDescrambler()) {
@@ -4620,7 +4634,6 @@
memcpy(mem->unsecurePointer(), csd->data(), csd->size());
ssize_t heapOffset;
memory = hardware::fromHeap(mem->getMemory(&heapOffset, nullptr));
- offset += heapOffset;
} else {
std::shared_ptr<C2LinearBlock> block =
FetchLinearBlock(csd->size(), {std::string{mComponentName.c_str()}});
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index d372140..34fb0d8 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -401,7 +401,6 @@
struct ResourceManagerServiceProxy;
State mState;
- uid_t mUid;
bool mReleasedByResourceManager;
sp<ALooper> mLooper;
sp<ALooper> mCodecLooper;
diff --git a/media/libstagefright/include/media/stagefright/ProcessInfo.h b/media/libstagefright/include/media/stagefright/ProcessInfo.h
index b8a3c10..06b9c92 100644
--- a/media/libstagefright/include/media/stagefright/ProcessInfo.h
+++ b/media/libstagefright/include/media/stagefright/ProcessInfo.h
@@ -30,7 +30,8 @@
ProcessInfo();
virtual bool getPriority(int pid, int* priority);
- virtual bool isValidPid(int pid);
+ virtual bool isPidTrusted(int pid);
+ virtual bool isPidUidTrusted(int pid, int uid);
virtual bool overrideProcessInfo(int pid, int procState, int oomScore);
virtual void removeProcessInfoOverride(int pid);
diff --git a/media/libstagefright/include/media/stagefright/ProcessInfoInterface.h b/media/libstagefright/include/media/stagefright/ProcessInfoInterface.h
index 9260181..b7fc858 100644
--- a/media/libstagefright/include/media/stagefright/ProcessInfoInterface.h
+++ b/media/libstagefright/include/media/stagefright/ProcessInfoInterface.h
@@ -23,7 +23,8 @@
struct ProcessInfoInterface : public RefBase {
virtual bool getPriority(int pid, int* priority) = 0;
- virtual bool isValidPid(int pid) = 0;
+ virtual bool isPidTrusted(int pid) = 0;
+ virtual bool isPidUidTrusted(int pid, int uid) = 0;
virtual bool overrideProcessInfo(int pid, int procState, int oomScore);
virtual void removeProcessInfoOverride(int pid);
diff --git a/media/utils/ProcessInfo.cpp b/media/utils/ProcessInfo.cpp
index e212794..da199c4 100644
--- a/media/utils/ProcessInfo.cpp
+++ b/media/utils/ProcessInfo.cpp
@@ -64,11 +64,27 @@
return true;
}
-bool ProcessInfo::isValidPid(int pid) {
+bool ProcessInfo::isPidTrusted(int pid) {
+ return isPidUidTrusted(pid, -1);
+}
+
+bool ProcessInfo::isPidUidTrusted(int pid, int uid) {
int callingPid = IPCThreadState::self()->getCallingPid();
int callingUid = IPCThreadState::self()->getCallingUid();
- // Trust it if this is called from the same process otherwise pid has to match the calling pid.
- return (callingPid == getpid()) || (callingPid == pid) || (callingUid == AID_MEDIA);
+ // Always trust when the caller is acting on their own behalf.
+ if (pid == callingPid && (uid == callingUid || uid == -1)) { // UID can be optional
+ return true;
+ }
+ // Implicitly trust when the caller is our own process.
+ if (callingPid == getpid()) {
+ return true;
+ }
+ // Implicitly trust when a media process is calling.
+ if (callingUid == AID_MEDIA) {
+ return true;
+ }
+ // Otherwise, allow the caller to act as another process when the caller has permissions.
+ return checkCallingPermission(String16("android.permission.MEDIA_RESOURCE_OVERRIDE_PID"));
}
bool ProcessInfo::overrideProcessInfo(int pid, int procState, int oomScore) {
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 953686b..d31baa3 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -422,11 +422,11 @@
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
- if (!mProcessInfo->isValidPid(pid)) {
+ if (!mProcessInfo->isPidUidTrusted(pid, uid)) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
uid_t callingUid = IPCThreadState::self()->getCallingUid();
- ALOGW("%s called with untrusted pid %d, using calling pid %d, uid %d", __FUNCTION__,
- pid, callingPid, callingUid);
+ ALOGW("%s called with untrusted pid %d or uid %d, using calling pid %d, uid %d",
+ __FUNCTION__, pid, uid, callingPid, callingUid);
pid = callingPid;
uid = callingUid;
}
@@ -481,7 +481,7 @@
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
- if (!mProcessInfo->isValidPid(pid)) {
+ if (!mProcessInfo->isPidTrusted(pid)) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
pid, callingPid);
@@ -549,7 +549,7 @@
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
- if (checkValid && !mProcessInfo->isValidPid(pid)) {
+ if (checkValid && !mProcessInfo->isPidTrusted(pid)) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
pid, callingPid);
@@ -607,7 +607,7 @@
Vector<std::shared_ptr<IResourceManagerClient>> clients;
{
Mutex::Autolock lock(mLock);
- if (!mProcessInfo->isValidPid(callingPid)) {
+ if (!mProcessInfo->isPidTrusted(callingPid)) {
pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
callingPid, actualCallingPid);
@@ -846,7 +846,7 @@
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
- if (!mProcessInfo->isValidPid(pid)) {
+ if (!mProcessInfo->isPidTrusted(pid)) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
pid, callingPid);
@@ -878,7 +878,7 @@
Vector<std::shared_ptr<IResourceManagerClient>> clients;
{
Mutex::Autolock lock(mLock);
- if (!mProcessInfo->isValidPid(pid)) {
+ if (!mProcessInfo->isPidTrusted(pid)) {
pid_t callingPid = IPCThreadState::self()->getCallingPid();
ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
pid, callingPid);
diff --git a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
index 6690b16..8f25ee6 100644
--- a/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
+++ b/services/mediaresourcemanager/fuzzer/mediaresourcemanager_fuzzer.cpp
@@ -71,7 +71,8 @@
return true;
}
- virtual bool isValidPid(int /* pid */) { return true; }
+ virtual bool isPidTrusted(int /* pid */) { return true; }
+ virtual bool isPidUidTrusted(int /* pid */, int /* uid */) { return true; }
virtual bool overrideProcessInfo(int /* pid */, int /*procState*/, int /*oomScore*/) {
return true;
}
diff --git a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
index 8e29312..0aa55c9 100644
--- a/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
+++ b/services/mediaresourcemanager/test/ResourceManagerServiceTestUtils.h
@@ -46,7 +46,11 @@
return true;
}
- virtual bool isValidPid(int /* pid */) {
+ virtual bool isPidTrusted(int /* pid */) {
+ return true;
+ }
+
+ virtual bool isPidUidTrusted(int /* pid */, int /* uid */) {
return true;
}