audiopolicy: clear caller identity before calling audio policy manager
Audio policy manager methods must always be executed with the
level of priviledge of audioserver process.
After checking calling permissions, audio policy service will
clear binder caller identity before calling into audio policy manager.
Also add restrictions for start source and stop source binder
transactions.
Bug: 77869640
Test: manual audio smoke tests
Change-Id: I993d4fddcea9bfa3f44093c38406b85d69ca8890
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index a49b2cb..3cde9a8 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -872,7 +872,9 @@
case INIT_STREAM_VOLUME:
case SET_STREAM_VOLUME:
case REGISTER_POLICY_MIXES:
- case SET_MASTER_MONO: {
+ case SET_MASTER_MONO:
+ case START_AUDIO_SOURCE:
+ case STOP_AUDIO_SOURCE: {
uid_t multiUserClientUid = IPCThreadState::self()->getCallingUid() % AID_USER_OFFSET;
if (multiUserClientUid >= AID_APP_START) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 8f0c846..cf24c13 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -44,6 +44,7 @@
ALOGV("setDeviceConnectionState()");
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->setDeviceConnectionState(device, state,
device_address, device_name);
}
@@ -55,6 +56,7 @@
if (mAudioPolicyManager == NULL) {
return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE;
}
+ AutoCallerClear acc;
return mAudioPolicyManager->getDeviceConnectionState(device,
device_address);
}
@@ -72,6 +74,7 @@
ALOGV("handleDeviceConfigChange()");
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->handleDeviceConfigChange(device, device_address,
device_name);
}
@@ -94,10 +97,10 @@
// operation from policy manager standpoint (no other operation (e.g track start or stop)
// can be interleaved).
Mutex::Autolock _l(mLock);
-
// TODO: check if it is more appropriate to do it in platform specific policy manager
AudioSystem::setMode(state);
+ AutoCallerClear acc;
mAudioPolicyManager->setPhoneState(state);
mPhoneState = state;
return NO_ERROR;
@@ -126,6 +129,7 @@
}
ALOGV("setForceUse()");
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
mAudioPolicyManager->setForceUse(usage, config);
return NO_ERROR;
}
@@ -138,6 +142,7 @@
if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) {
return AUDIO_POLICY_FORCE_NONE;
}
+ AutoCallerClear acc;
return mAudioPolicyManager->getForceUse(usage);
}
@@ -151,6 +156,7 @@
}
ALOGV("getOutput()");
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getOutput(stream);
}
@@ -178,6 +184,7 @@
uid = callingUid;
}
audio_output_flags_t originalFlags = flags;
+ AutoCallerClear acc;
status_t result = mAudioPolicyManager->getOutputForAttr(attr, output, session, stream, uid,
config,
&flags, selectedDeviceId, portId);
@@ -223,6 +230,7 @@
}
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->startOutput(output, stream, session);
}
@@ -259,6 +267,7 @@
}
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->stopOutput(output, stream, session);
}
@@ -279,6 +288,7 @@
{
ALOGV("doReleaseOutput from tid %d", gettid());
Mutex::Autolock _l(mLock);
+ // called from internal thread: no need to clear caller identity
mAudioPolicyManager->releaseOutput(output, stream, session);
}
@@ -337,11 +347,14 @@
AudioPolicyInterface::input_type_t inputType;
Mutex::Autolock _l(mLock);
- // the audio_in_acoustics_t parameter is ignored by get_input()
- status = mAudioPolicyManager->getInputForAttr(attr, input, session, uid,
- config,
- flags, selectedDeviceId,
- &inputType, portId);
+ {
+ AutoCallerClear acc;
+ // the audio_in_acoustics_t parameter is ignored by get_input()
+ status = mAudioPolicyManager->getInputForAttr(attr, input, session, uid,
+ config,
+ flags, selectedDeviceId,
+ &inputType, portId);
+ }
audioPolicyEffects = mAudioPolicyEffects;
if (status == NO_ERROR) {
@@ -372,6 +385,7 @@
if (status != NO_ERROR) {
if (status == PERMISSION_DENIED) {
+ AutoCallerClear acc;
mAudioPolicyManager->releaseInput(*input, session);
}
return status;
@@ -425,8 +439,12 @@
AudioPolicyInterface::concurrency_type__mask_t concurrency =
AudioPolicyInterface::API_INPUT_CONCURRENCY_NONE;
- status_t status = mAudioPolicyManager->startInput(
- client->input, client->session, *silenced, &concurrency);
+ status_t status;
+ {
+ AutoCallerClear acc;
+ status = mAudioPolicyManager->startInput(
+ client->input, client->session, *silenced, &concurrency);
+ }
if (status == NO_ERROR) {
LOG_ALWAYS_FATAL_IF(concurrency & ~AudioPolicyInterface::API_INPUT_CONCURRENCY_ALL,
@@ -461,7 +479,7 @@
// finish the recording app op
finishRecording(client->opPackageName, client->uid);
-
+ AutoCallerClear acc;
return mAudioPolicyManager->stopInput(client->input, client->session);
}
@@ -494,6 +512,7 @@
}
{
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
mAudioPolicyManager->releaseInput(client->input, client->session);
}
}
@@ -512,6 +531,7 @@
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
mAudioPolicyManager->initStreamVolume(stream, indexMin, indexMax);
return NO_ERROR;
}
@@ -530,6 +550,7 @@
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->setStreamVolumeIndex(stream,
index,
device);
@@ -546,6 +567,7 @@
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getStreamVolumeIndex(stream,
index,
device);
@@ -559,6 +581,7 @@
if (mAudioPolicyManager == NULL) {
return 0;
}
+ AutoCallerClear acc;
return mAudioPolicyManager->getStrategyForStream(stream);
}
@@ -573,6 +596,7 @@
return AUDIO_DEVICE_NONE;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getDevicesForStream(stream);
}
@@ -583,6 +607,7 @@
return 0;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getOutputForEffect(desc);
}
@@ -596,6 +621,7 @@
return NO_INIT;
}
Mutex::Autolock _l(mEffectsLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->registerEffect(desc, io, strategy, session, id);
}
@@ -605,6 +631,7 @@
return NO_INIT;
}
Mutex::Autolock _l(mEffectsLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->unregisterEffect(id);
}
@@ -614,6 +641,7 @@
return NO_INIT;
}
Mutex::Autolock _l(mEffectsLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->setEffectEnabled(id, enabled);
}
@@ -626,6 +654,7 @@
return false;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->isStreamActive(stream, inPastMs);
}
@@ -638,6 +667,7 @@
return false;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->isStreamActiveRemotely(stream, inPastMs);
}
@@ -647,6 +677,7 @@
return false;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->isSourceActive(source);
}
@@ -680,6 +711,7 @@
Mutex::Autolock _l(mLock);
Mutex::Autolock _le(mEffectsLock); // isOffloadSupported queries for
// non-offloadable effects
+ AutoCallerClear acc;
return mAudioPolicyManager->isOffloadSupported(info);
}
@@ -693,7 +725,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation);
}
@@ -703,7 +735,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->getAudioPort(port);
}
@@ -717,6 +749,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
+ AutoCallerClear acc;
return mAudioPolicyManager->createAudioPatch(patch, handle,
IPCThreadState::self()->getCallingUid());
}
@@ -730,7 +763,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->releaseAudioPatch(handle,
IPCThreadState::self()->getCallingUid());
}
@@ -743,7 +776,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->listAudioPatches(num_patches, patches, generation);
}
@@ -756,7 +789,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->setAudioPortConfig(config);
}
@@ -768,7 +801,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->acquireSoundTriggerSession(session, ioHandle, device);
}
@@ -778,7 +811,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->releaseSoundTriggerSession(session);
}
@@ -791,6 +824,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
+ AutoCallerClear acc;
if (registration) {
return mAudioPolicyManager->registerPolicyMixes(mixes);
} else {
@@ -806,7 +840,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->startAudioSource(source, attributes, handle,
IPCThreadState::self()->getCallingUid());
}
@@ -817,7 +851,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
-
+ AutoCallerClear acc;
return mAudioPolicyManager->stopAudioSource(handle);
}
@@ -830,6 +864,7 @@
return PERMISSION_DENIED;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->setMasterMono(mono);
}
@@ -839,6 +874,7 @@
return NO_INIT;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getMasterMono(mono);
}
@@ -850,6 +886,7 @@
return NAN;
}
Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
return mAudioPolicyManager->getStreamVolumeDB(stream, index, device);
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 082923a..13bf605 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -151,6 +151,7 @@
{
Mutex::Autolock _l(mLock);
if (mAudioPolicyManager) {
+ // called from binder death notification: no need to clear caller identity
mAudioPolicyManager->releaseResourcesForUid(uid);
}
}
@@ -335,6 +336,7 @@
{
Mutex::Autolock _l(mLock);
if (mAudioPolicyManager) {
+ AutoCallerClear acc;
mAudioPolicyManager->setRecordSilenced(uid, silenced);
}
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index b3bc12b..d8dd797 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -640,6 +640,22 @@
bool isVirtualDevice; // uses vitual device: updated by APM::getInputForAttr()
};
+ // A class automatically clearing and restoring binder caller identity inside
+ // a code block (scoped variable)
+ // Declare one systematically before calling AudioPolicyManager methods so that they are
+ // executed with the same level of privilege as audioserver process.
+ class AutoCallerClear {
+ public:
+ AutoCallerClear() :
+ mToken(IPCThreadState::self()->clearCallingIdentity()) {}
+ ~AutoCallerClear() {
+ IPCThreadState::self()->restoreCallingIdentity(mToken);
+ }
+
+ private:
+ const int64_t mToken;
+ };
+
// Internal dump utilities.
status_t dumpPermissionDenial(int fd);