From 10b7123bd6ce29fe756422aeedc5cfe469c4309f Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 13 Apr 2018 18:14:44 -0700 Subject: [PATCH] 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 --- media/libaudioclient/IAudioPolicyService.cpp | 4 +- .../service/AudioPolicyInterfaceImpl.cpp | 73 ++++++++++++++----- .../service/AudioPolicyService.cpp | 2 + .../audiopolicy/service/AudioPolicyService.h | 16 ++++ 4 files changed, 76 insertions(+), 19 deletions(-) diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index a49b2cbb52..3cde9a8d12 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -872,7 +872,9 @@ status_t BnAudioPolicyService::onTransact( 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 8f0c8468b9..cf24c13ad5 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -44,6 +44,7 @@ status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device, ALOGV("setDeviceConnectionState()"); Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->setDeviceConnectionState(device, state, device_address, device_name); } @@ -55,6 +56,7 @@ audio_policy_dev_state_t AudioPolicyService::getDeviceConnectionState( if (mAudioPolicyManager == NULL) { return AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE; } + AutoCallerClear acc; return mAudioPolicyManager->getDeviceConnectionState(device, device_address); } @@ -72,6 +74,7 @@ status_t AudioPolicyService::handleDeviceConfigChange(audio_devices_t device, ALOGV("handleDeviceConfigChange()"); Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->handleDeviceConfigChange(device, device_address, device_name); } @@ -94,10 +97,10 @@ status_t AudioPolicyService::setPhoneState(audio_mode_t state) // 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 @@ status_t AudioPolicyService::setForceUse(audio_policy_force_use_t usage, } ALOGV("setForceUse()"); Mutex::Autolock _l(mLock); + AutoCallerClear acc; mAudioPolicyManager->setForceUse(usage, config); return NO_ERROR; } @@ -138,6 +142,7 @@ audio_policy_forced_cfg_t AudioPolicyService::getForceUse(audio_policy_force_use if (usage < 0 || usage >= AUDIO_POLICY_FORCE_USE_CNT) { return AUDIO_POLICY_FORCE_NONE; } + AutoCallerClear acc; return mAudioPolicyManager->getForceUse(usage); } @@ -151,6 +156,7 @@ audio_io_handle_t AudioPolicyService::getOutput(audio_stream_type_t stream) } ALOGV("getOutput()"); Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->getOutput(stream); } @@ -178,6 +184,7 @@ status_t AudioPolicyService::getOutputForAttr(const audio_attributes_t *attr, 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 @@ status_t AudioPolicyService::startOutput(audio_io_handle_t output, } } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->startOutput(output, stream, session); } @@ -259,6 +267,7 @@ status_t AudioPolicyService::doStopOutput(audio_io_handle_t output, } } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->stopOutput(output, stream, session); } @@ -279,6 +288,7 @@ void AudioPolicyService::doReleaseOutput(audio_io_handle_t output, { 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 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, 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 @@ status_t AudioPolicyService::getInputForAttr(const audio_attributes_t *attr, if (status != NO_ERROR) { if (status == PERMISSION_DENIED) { + AutoCallerClear acc; mAudioPolicyManager->releaseInput(*input, session); } return status; @@ -425,8 +439,12 @@ status_t AudioPolicyService::startInput(audio_port_handle_t portId, bool *silenc 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 @@ status_t AudioPolicyService::stopInput(audio_port_handle_t portId) // finish the recording app op finishRecording(client->opPackageName, client->uid); - + AutoCallerClear acc; return mAudioPolicyManager->stopInput(client->input, client->session); } @@ -494,6 +512,7 @@ void AudioPolicyService::releaseInput(audio_port_handle_t portId) } { Mutex::Autolock _l(mLock); + AutoCallerClear acc; mAudioPolicyManager->releaseInput(client->input, client->session); } } @@ -512,6 +531,7 @@ status_t AudioPolicyService::initStreamVolume(audio_stream_type_t stream, return BAD_VALUE; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; mAudioPolicyManager->initStreamVolume(stream, indexMin, indexMax); return NO_ERROR; } @@ -530,6 +550,7 @@ status_t AudioPolicyService::setStreamVolumeIndex(audio_stream_type_t stream, return BAD_VALUE; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->setStreamVolumeIndex(stream, index, device); @@ -546,6 +567,7 @@ status_t AudioPolicyService::getStreamVolumeIndex(audio_stream_type_t stream, return BAD_VALUE; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->getStreamVolumeIndex(stream, index, device); @@ -559,6 +581,7 @@ uint32_t AudioPolicyService::getStrategyForStream(audio_stream_type_t stream) if (mAudioPolicyManager == NULL) { return 0; } + AutoCallerClear acc; return mAudioPolicyManager->getStrategyForStream(stream); } @@ -573,6 +596,7 @@ audio_devices_t AudioPolicyService::getDevicesForStream(audio_stream_type_t stre return AUDIO_DEVICE_NONE; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->getDevicesForStream(stream); } @@ -583,6 +607,7 @@ audio_io_handle_t AudioPolicyService::getOutputForEffect(const effect_descriptor return 0; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->getOutputForEffect(desc); } @@ -596,6 +621,7 @@ status_t AudioPolicyService::registerEffect(const effect_descriptor_t *desc, return NO_INIT; } Mutex::Autolock _l(mEffectsLock); + AutoCallerClear acc; return mAudioPolicyManager->registerEffect(desc, io, strategy, session, id); } @@ -605,6 +631,7 @@ status_t AudioPolicyService::unregisterEffect(int id) return NO_INIT; } Mutex::Autolock _l(mEffectsLock); + AutoCallerClear acc; return mAudioPolicyManager->unregisterEffect(id); } @@ -614,6 +641,7 @@ status_t AudioPolicyService::setEffectEnabled(int id, bool enabled) return NO_INIT; } Mutex::Autolock _l(mEffectsLock); + AutoCallerClear acc; return mAudioPolicyManager->setEffectEnabled(id, enabled); } @@ -626,6 +654,7 @@ bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inP return false; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->isStreamActive(stream, inPastMs); } @@ -638,6 +667,7 @@ bool AudioPolicyService::isStreamActiveRemotely(audio_stream_type_t stream, uint return false; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->isStreamActiveRemotely(stream, inPastMs); } @@ -647,6 +677,7 @@ bool AudioPolicyService::isSourceActive(audio_source_t source) const return false; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->isSourceActive(source); } @@ -680,6 +711,7 @@ bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info) Mutex::Autolock _l(mLock); Mutex::Autolock _le(mEffectsLock); // isOffloadSupported queries for // non-offloadable effects + AutoCallerClear acc; return mAudioPolicyManager->isOffloadSupported(info); } @@ -693,7 +725,7 @@ status_t AudioPolicyService::listAudioPorts(audio_port_role_t role, if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->listAudioPorts(role, type, num_ports, ports, generation); } @@ -703,7 +735,7 @@ status_t AudioPolicyService::getAudioPort(struct audio_port *port) if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->getAudioPort(port); } @@ -717,6 +749,7 @@ status_t AudioPolicyService::createAudioPatch(const struct audio_patch *patch, if (mAudioPolicyManager == NULL) { return NO_INIT; } + AutoCallerClear acc; return mAudioPolicyManager->createAudioPatch(patch, handle, IPCThreadState::self()->getCallingUid()); } @@ -730,7 +763,7 @@ status_t AudioPolicyService::releaseAudioPatch(audio_patch_handle_t handle) if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->releaseAudioPatch(handle, IPCThreadState::self()->getCallingUid()); } @@ -743,7 +776,7 @@ status_t AudioPolicyService::listAudioPatches(unsigned int *num_patches, if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->listAudioPatches(num_patches, patches, generation); } @@ -756,7 +789,7 @@ status_t AudioPolicyService::setAudioPortConfig(const struct audio_port_config * if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->setAudioPortConfig(config); } @@ -768,7 +801,7 @@ status_t AudioPolicyService::acquireSoundTriggerSession(audio_session_t *session if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->acquireSoundTriggerSession(session, ioHandle, device); } @@ -778,7 +811,7 @@ status_t AudioPolicyService::releaseSoundTriggerSession(audio_session_t session) if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->releaseSoundTriggerSession(session); } @@ -791,6 +824,7 @@ status_t AudioPolicyService::registerPolicyMixes(const Vector& mixes, if (mAudioPolicyManager == NULL) { return NO_INIT; } + AutoCallerClear acc; if (registration) { return mAudioPolicyManager->registerPolicyMixes(mixes); } else { @@ -806,7 +840,7 @@ status_t AudioPolicyService::startAudioSource(const struct audio_port_config *so if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->startAudioSource(source, attributes, handle, IPCThreadState::self()->getCallingUid()); } @@ -817,7 +851,7 @@ status_t AudioPolicyService::stopAudioSource(audio_patch_handle_t handle) if (mAudioPolicyManager == NULL) { return NO_INIT; } - + AutoCallerClear acc; return mAudioPolicyManager->stopAudioSource(handle); } @@ -830,6 +864,7 @@ status_t AudioPolicyService::setMasterMono(bool mono) return PERMISSION_DENIED; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->setMasterMono(mono); } @@ -839,6 +874,7 @@ status_t AudioPolicyService::getMasterMono(bool *mono) return NO_INIT; } Mutex::Autolock _l(mLock); + AutoCallerClear acc; return mAudioPolicyManager->getMasterMono(mono); } @@ -850,6 +886,7 @@ float AudioPolicyService::getStreamVolumeDB( 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 082923ad6e..13bf60589a 100644 --- a/services/audiopolicy/service/AudioPolicyService.cpp +++ b/services/audiopolicy/service/AudioPolicyService.cpp @@ -151,6 +151,7 @@ void AudioPolicyService::removeNotificationClient(uid_t uid) { Mutex::Autolock _l(mLock); if (mAudioPolicyManager) { + // called from binder death notification: no need to clear caller identity mAudioPolicyManager->releaseResourcesForUid(uid); } } @@ -335,6 +336,7 @@ void AudioPolicyService::setRecordSilenced(uid_t uid, bool silenced) { 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 b3bc12b052..d8dd797277 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -640,6 +640,22 @@ private: 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);