Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f78993f authored by Atneya Nair's avatar Atneya Nair
Browse files

Audioflinger permission migration

Migrate audioflinger permission checks to new permission utilities.

Test: Cts and smoke tests
Bug: 338089555
Flag: com.android.media.audio.audioserver_permissions
Change-Id: I0c520484cf2b83d200353a68832e5ec1e4968de1
parent 3359e92c
Loading
Loading
Loading
Loading
+102 −25
Original line number Original line Diff line number Diff line
@@ -95,9 +95,12 @@ using media::audio::common::AudioMMapPolicyType;
using media::audio::common::AudioMode;
using media::audio::common::AudioMode;
using android::content::AttributionSourceState;
using android::content::AttributionSourceState;
using android::detail::AudioHalVersionInfo;
using android::detail::AudioHalVersionInfo;
using com::android::media::audio::audioserver_permissions;
using com::android::media::permission::INativePermissionController;
using com::android::media::permission::INativePermissionController;
using com::android::media::permission::IPermissionProvider;
using com::android::media::permission::IPermissionProvider;
using com::android::media::permission::NativePermissionController;
using com::android::media::permission::NativePermissionController;
using com::android::media::permission::PermissionEnum;
using com::android::media::permission::PermissionEnum::MODIFY_AUDIO_SETTINGS;
using com::android::media::permission::ValidatedAttributionSourceState;
using com::android::media::permission::ValidatedAttributionSourceState;


static const AudioHalVersionInfo kMaxAAudioPropertyDeviceHalVersion =
static const AudioHalVersionInfo kMaxAAudioPropertyDeviceHalVersion =
@@ -580,7 +583,7 @@ status_t AudioFlinger::openMmapStream(MmapStreamInterface::stream_direction_t di


    // TODO b/182392553: refactor or make clearer
    // TODO b/182392553: refactor or make clearer
    AttributionSourceState adjAttributionSource;
    AttributionSourceState adjAttributionSource;
    if (!com::android::media::audio::audioserver_permissions()) {
    if (!audioserver_permissions()) {
        pid_t clientPid =
        pid_t clientPid =
            VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(client.attributionSource.pid));
            VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(client.attributionSource.pid));
        bool updatePid = (clientPid == (pid_t)-1);
        bool updatePid = (clientPid == (pid_t)-1);
@@ -750,6 +753,20 @@ AudioHwDevice* AudioFlinger::findSuitableHwDev_l(
    return NULL;
    return NULL;
}
}


error::BinderResult<std::monostate> AudioFlinger::enforceCallingPermission(PermissionEnum perm) {
    const uid_t uid = IPCThreadState::self()->getCallingUid();
    // Due to a complicated start-up sequence, we could get a call from ourselves before APS
    // populates the permission provider (done immediately following its construction). So,
    // bail before calling into the permission provider, even though it also does this check.
    if (uid == getuid()) return {};
    const bool hasPerm = VALUE_OR_RETURN(getPermissionProvider().checkPermission(perm, uid));
    if (hasPerm) {
        return {};
    } else {
        return error::unexpectedExceptionCode(EX_SECURITY, "");
    }
}

void AudioFlinger::dumpClients_ll(int fd, bool dumpAllocators) {
void AudioFlinger::dumpClients_ll(int fd, bool dumpAllocators) {
    String8 result;
    String8 result;


@@ -1129,7 +1146,7 @@ status_t AudioFlinger::createTrack(const media::CreateTrackRequest& _input,


    AttributionSourceState adjAttributionSource;
    AttributionSourceState adjAttributionSource;
    pid_t callingPid = IPCThreadState::self()->getCallingPid();
    pid_t callingPid = IPCThreadState::self()->getCallingPid();
    if (!com::android::media::audio::audioserver_permissions()) {
    if (!audioserver_permissions()) {
        adjAttributionSource = input.clientInfo.attributionSource;
        adjAttributionSource = input.clientInfo.attributionSource;
        const uid_t callingUid = IPCThreadState::self()->getCallingUid();
        const uid_t callingUid = IPCThreadState::self()->getCallingUid();
        uid_t clientUid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(
        uid_t clientUid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(
@@ -1410,9 +1427,13 @@ status_t AudioFlinger::setMasterVolume(float value)
    }
    }


    // check calling permissions
    // check calling permissions
    if (audioserver_permissions()) {
        VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    audio_utils::lock_guard _l(mutex());
    audio_utils::lock_guard _l(mutex());
    mMasterVolume = value;
    mMasterVolume = value;
@@ -1452,9 +1473,13 @@ status_t AudioFlinger::setMasterBalance(float balance)
    }
    }


    // check calling permissions
    // check calling permissions
    if (audioserver_permissions()) {
        VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    // check range
    // check range
    if (isnan(balance) || fabs(balance) > 1.f) {
    if (isnan(balance) || fabs(balance) > 1.f) {
@@ -1486,9 +1511,13 @@ status_t AudioFlinger::setMode(audio_mode_t mode)
    }
    }


    // check calling permissions
    // check calling permissions
    if (audioserver_permissions()) {
        VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }
    if (uint32_t(mode) >= AUDIO_MODE_CNT) {
    if (uint32_t(mode) >= AUDIO_MODE_CNT) {
        ALOGW("Illegal value: setMode(%d)", mode);
        ALOGW("Illegal value: setMode(%d)", mode);
        return BAD_VALUE;
        return BAD_VALUE;
@@ -1528,9 +1557,13 @@ status_t AudioFlinger::setMicMute(bool state)
    }
    }


    // check calling permissions
    // check calling permissions
     if (audioserver_permissions()) {
         VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    audio_utils::lock_guard lock(hardwareMutex());
    audio_utils::lock_guard lock(hardwareMutex());
    if (mPrimaryHardwareDev == nullptr) {
    if (mPrimaryHardwareDev == nullptr) {
@@ -1598,9 +1631,13 @@ status_t AudioFlinger::setMasterMute(bool muted)
    }
    }


    // check calling permissions
    // check calling permissions
    if (audioserver_permissions()) {
        VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    audio_utils::lock_guard _l(mutex());
    audio_utils::lock_guard _l(mutex());
    mMasterMute = muted;
    mMasterMute = muted;
@@ -1685,9 +1722,13 @@ status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
        bool muted, audio_io_handle_t output)
        bool muted, audio_io_handle_t output)
{
{
    // check calling permissions
    // check calling permissions
    if (audioserver_permissions()) {
        VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    status_t status = checkStreamType(stream);
    status_t status = checkStreamType(stream);
    if (status != NO_ERROR) {
    if (status != NO_ERROR) {
@@ -1813,9 +1854,13 @@ status_t AudioFlinger::getSoundDoseInterface(const sp<media::ISoundDoseCallback>
status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
{
{
    // check calling permissions
    // check calling permissions
    if (audioserver_permissions()) {
        VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    status_t status = checkStreamType(stream);
    status_t status = checkStreamType(stream);
    if (status != NO_ERROR) {
    if (status != NO_ERROR) {
@@ -1946,9 +1991,13 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8&
            IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
            IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());


    // check calling permissions
    // check calling permissions
    if (audioserver_permissions()) {
        VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    String8 filteredKeyValuePairs = keyValuePairs;
    String8 filteredKeyValuePairs = keyValuePairs;
    filterReservedParameters(filteredKeyValuePairs, IPCThreadState::self()->getCallingUid());
    filterReservedParameters(filteredKeyValuePairs, IPCThreadState::self()->getCallingUid());
@@ -2188,9 +2237,13 @@ status_t AudioFlinger::setVoiceVolume(float value)
    }
    }


    // check calling permissions
    // check calling permissions
    if (audioserver_permissions()) {
        VALUE_OR_RETURN_CONVERTED(enforceCallingPermission(MODIFY_AUDIO_SETTINGS));
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    audio_utils::lock_guard lock(hardwareMutex());
    audio_utils::lock_guard lock(hardwareMutex());
    if (mPrimaryHardwareDev == nullptr) {
    if (mPrimaryHardwareDev == nullptr) {
@@ -2458,7 +2511,7 @@ status_t AudioFlinger::createRecord(const media::CreateRecordRequest& _input,


    AttributionSourceState adjAttributionSource;
    AttributionSourceState adjAttributionSource;
    pid_t callingPid = IPCThreadState::self()->getCallingPid();
    pid_t callingPid = IPCThreadState::self()->getCallingPid();
    if (!com::android::media::audio::audioserver_permissions()) {
    if (!audioserver_permissions()) {
        adjAttributionSource = input.clientInfo.attributionSource;
        adjAttributionSource = input.clientInfo.attributionSource;
        bool updatePid = (adjAttributionSource.pid == -1);
        bool updatePid = (adjAttributionSource.pid == -1);
        const uid_t callingUid = IPCThreadState::self()->getCallingUid();
        const uid_t callingUid = IPCThreadState::self()->getCallingUid();
@@ -2689,9 +2742,19 @@ audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
    if (name == NULL) {
    if (name == NULL) {
        return AUDIO_MODULE_HANDLE_NONE;
        return AUDIO_MODULE_HANDLE_NONE;
    }
    }
    if (audioserver_permissions()) {
        const auto res = enforceCallingPermission(MODIFY_AUDIO_SETTINGS);
        if (!res.ok()) {
            ALOGE("Function: %s perm check result (%s)", __FUNCTION__,
                  errorToString(res.error()).c_str());
            return AUDIO_MODULE_HANDLE_NONE;
        }
    } else {
        if (!settingsAllowed()) {
        if (!settingsAllowed()) {
            return AUDIO_MODULE_HANDLE_NONE;
            return AUDIO_MODULE_HANDLE_NONE;
        }
        }
    }

    audio_utils::lock_guard _l(mutex());
    audio_utils::lock_guard _l(mutex());
    audio_utils::lock_guard lock(hardwareMutex());
    audio_utils::lock_guard lock(hardwareMutex());
    AudioHwDevice* module = loadHwModule_ll(name);
    AudioHwDevice* module = loadHwModule_ll(name);
@@ -4297,7 +4360,7 @@ status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request,
    status_t lStatus = NO_ERROR;
    status_t lStatus = NO_ERROR;
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    uid_t callingUid = IPCThreadState::self()->getCallingUid();
    pid_t currentPid;
    pid_t currentPid;
    if (!com::android::media::audio::audioserver_permissions()) {
    if (!audioserver_permissions()) {
        adjAttributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
        adjAttributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
        currentPid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(adjAttributionSource.pid));
        currentPid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_pid_t(adjAttributionSource.pid));
        if (currentPid == -1 || !isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
        if (currentPid == -1 || !isAudioServerOrMediaServerOrSystemServerOrRootUid(callingUid)) {
@@ -4331,9 +4394,23 @@ status_t AudioFlinger::createEffect(const media::CreateEffectRequest& request,
        goto Exit;
        goto Exit;
    }
    }


    bool isSettingsAllowed;
    if (audioserver_permissions()) {
        const auto res = getPermissionProvider().checkPermission(
                MODIFY_AUDIO_SETTINGS,
                IPCThreadState::self()->getCallingUid());
        if (!res.ok()) {
            lStatus = statusTFromBinderStatus(res.error());
            goto Exit;
        }
        isSettingsAllowed = res.value();
    } else {
        isSettingsAllowed = settingsAllowed();
    }

    // check audio settings permission for global effects
    // check audio settings permission for global effects
    if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
    if (sessionId == AUDIO_SESSION_OUTPUT_MIX) {
        if (!settingsAllowed()) {
        if (!isSettingsAllowed) {
            ALOGE("%s: no permission for AUDIO_SESSION_OUTPUT_MIX", __func__);
            ALOGE("%s: no permission for AUDIO_SESSION_OUTPUT_MIX", __func__);
            lStatus = PERMISSION_DENIED;
            lStatus = PERMISSION_DENIED;
            goto Exit;
            goto Exit;
+5 −0
Original line number Original line Diff line number Diff line
@@ -33,6 +33,7 @@
#include <audio_utils/mutex.h>
#include <audio_utils/mutex.h>
#include <audio_utils/FdToString.h>
#include <audio_utils/FdToString.h>
#include <audio_utils/SimpleLog.h>
#include <audio_utils/SimpleLog.h>
#include <com/android/media/permission/PermissionEnum.h>
#include <media/IAudioFlinger.h>
#include <media/IAudioFlinger.h>
#include <media/IAudioPolicyServiceLocal.h>
#include <media/IAudioPolicyServiceLocal.h>
#include <media/MediaMetricsItem.h>
#include <media/MediaMetricsItem.h>
@@ -49,6 +50,7 @@
#include <map>
#include <map>
#include <optional>
#include <optional>
#include <set>
#include <set>
#include <variant>


namespace android {
namespace android {


@@ -475,6 +477,9 @@ private:
    AudioHwDevice*          findSuitableHwDev_l(audio_module_handle_t module,
    AudioHwDevice*          findSuitableHwDev_l(audio_module_handle_t module,
            audio_devices_t deviceType) REQUIRES(mutex());
            audio_devices_t deviceType) REQUIRES(mutex());


    error::BinderResult<std::monostate> enforceCallingPermission(
                    com::android::media::permission::PermissionEnum perm);

    // incremented by 2 when screen state changes, bit 0 == 1 means "off"
    // incremented by 2 when screen state changes, bit 0 == 1 means "off"
    // AudioFlinger::setParameters() updates with mutex().
    // AudioFlinger::setParameters() updates with mutex().
    std::atomic_uint32_t mScreenState{};
    std::atomic_uint32_t mScreenState{};
+23 −4
Original line number Original line Diff line number Diff line
@@ -124,6 +124,8 @@ static inline T min(const T& a, const T& b)
    return a < b ? a : b;
    return a < b ? a : b;
}
}


using com::android::media::audio::audioserver_permissions;
using com::android::media::permission::PermissionEnum::CAPTURE_AUDIO_HOTWORD;
using com::android::media::permission::ValidatedAttributionSourceState;
using com::android::media::permission::ValidatedAttributionSourceState;
namespace audioserver_flags = com::android::media::audioserver;
namespace audioserver_flags = com::android::media::audioserver;


@@ -9126,10 +9128,23 @@ sp<IAfRecordTrack> RecordThread::createRecordTrack_l(
    }
    }


    if (maxSharedAudioHistoryMs != 0) {
    if (maxSharedAudioHistoryMs != 0) {
        if (audioserver_permissions()) {
            const auto res = mAfThreadCallback->getPermissionProvider().checkPermission(
                    CAPTURE_AUDIO_HOTWORD,
                    attributionSource.uid);
            if (!res.ok()) {
                lStatus = aidl_utils::statusTFromBinderStatus(res.error());
            }
            if (!res.value()) {
                lStatus = PERMISSION_DENIED;
                goto Exit;
            }
        } else {
            if (!captureHotwordAllowed(attributionSource)) {
            if (!captureHotwordAllowed(attributionSource)) {
                lStatus = PERMISSION_DENIED;
                lStatus = PERMISSION_DENIED;
                goto Exit;
                goto Exit;
            }
            }
        }
        if (maxSharedAudioHistoryMs < 0
        if (maxSharedAudioHistoryMs < 0
                || maxSharedAudioHistoryMs > kMaxSharedAudioHistoryMs) {
                || maxSharedAudioHistoryMs > kMaxSharedAudioHistoryMs) {
            lStatus = BAD_VALUE;
            lStatus = BAD_VALUE;
@@ -9249,7 +9264,11 @@ sp<IAfRecordTrack> RecordThread::createRecordTrack_l(
        if (!mSharedAudioPackageName.empty()
        if (!mSharedAudioPackageName.empty()
                && mSharedAudioPackageName == attributionSource.packageName
                && mSharedAudioPackageName == attributionSource.packageName
                && mSharedAudioSessionId == sessionId
                && mSharedAudioSessionId == sessionId
                && captureHotwordAllowed(attributionSource)) {
                && (audioserver_permissions() ?
                      mAfThreadCallback->getPermissionProvider().checkPermission(
                          CAPTURE_AUDIO_HOTWORD,
                          attributionSource.uid).value_or(false)
                    : captureHotwordAllowed(attributionSource))) {
            startFrames = mSharedAudioStartFrames;
            startFrames = mSharedAudioStartFrames;
        }
        }


+20 −3
Original line number Original line Diff line number Diff line
@@ -30,7 +30,9 @@


#include <audio_utils/StringUtils.h>
#include <audio_utils/StringUtils.h>
#include <audio_utils/minifloat.h>
#include <audio_utils/minifloat.h>
#include <com_android_media_audio.h>
#include <media/AudioValidator.h>
#include <media/AudioValidator.h>
#include <media/IPermissionProvider.h>
#include <media/RecordBufferConverter.h>
#include <media/RecordBufferConverter.h>
#include <media/nbaio/Pipe.h>
#include <media/nbaio/Pipe.h>
#include <media/nbaio/PipeReader.h>
#include <media/nbaio/PipeReader.h>
@@ -71,8 +73,11 @@ namespace android {


using ::android::aidl_utils::binderStatusFromStatusT;
using ::android::aidl_utils::binderStatusFromStatusT;
using binder::Status;
using binder::Status;
using com::android::media::audio::audioserver_permissions;
using com::android::media::permission::PermissionEnum::CAPTURE_AUDIO_HOTWORD;
using content::AttributionSourceState;
using content::AttributionSourceState;
using media::VolumeShaper;
using media::VolumeShaper;

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//      TrackBase
//      TrackBase
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
@@ -3286,11 +3291,23 @@ status_t RecordTrack::shareAudioHistory(
    attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
    attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
    attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
    attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
    attributionSource.token = sp<BBinder>::make();
    attributionSource.token = sp<BBinder>::make();
    const sp<IAfThreadBase> thread = mThread.promote();
    if (audioserver_permissions()) {
        const auto res = thread->afThreadCallback()->getPermissionProvider().checkPermission(
                    CAPTURE_AUDIO_HOTWORD,
                    attributionSource.uid);
            if (!res.ok()) {
                return aidl_utils::statusTFromBinderStatus(res.error());
            }
            if (!res.value()) {
                return PERMISSION_DENIED;
            }
    } else {
        if (!captureHotwordAllowed(attributionSource)) {
        if (!captureHotwordAllowed(attributionSource)) {
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
    }


    const sp<IAfThreadBase> thread = mThread.promote();
    if (thread != 0) {
    if (thread != 0) {
        auto* const recordThread = thread->asIAfRecordThread().get();
        auto* const recordThread = thread->asIAfRecordThread().get();
        status_t status = recordThread->shareAudioHistory(
        status_t status = recordThread->shareAudioHistory(