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

Commit b03b49fd authored by Marvin Ramin's avatar Marvin Ramin
Browse files

Update AttributionSource deviceIds thoroughly

PermissionChecker expects consistent deviceIds throughout the
AttributionSource chain.

Bug: 291737188
Test: atest VirtualAudioPermissionTest
Change-Id: I101a4705fc8703cf77bc8046d032bc58b3404ed5
parent 9f179836
Loading
Loading
Loading
Loading
+13 −9
Original line number Diff line number Diff line
@@ -86,7 +86,7 @@ int32_t getOpForSource(audio_source_t source) {
}

std::optional<AttributionSourceState> resolveAttributionSource(
        const AttributionSourceState& callerAttributionSource) {
        const AttributionSourceState& callerAttributionSource, const uint32_t virtualDeviceId) {
    AttributionSourceState nextAttributionSource = callerAttributionSource;

    if (!nextAttributionSource.packageName.has_value()) {
@@ -101,6 +101,7 @@ std::optional<AttributionSourceState> resolveAttributionSource(
            return std::nullopt;
        }
    }
    nextAttributionSource.deviceId = virtualDeviceId;

    AttributionSourceState myAttributionSource;
    myAttributionSource.uid = VALUE_OR_FATAL(android::legacy2aidl_uid_t_int32_t(getuid()));
@@ -109,6 +110,7 @@ std::optional<AttributionSourceState> resolveAttributionSource(
    // audioserver to the app ops system
    static sp<BBinder> appOpsToken = sp<BBinder>::make();
    myAttributionSource.token = appOpsToken;
    myAttributionSource.deviceId = virtualDeviceId;
    myAttributionSource.next.push_back(nextAttributionSource);

    return std::optional<AttributionSourceState>{myAttributionSource};
@@ -129,7 +131,7 @@ std::optional<AttributionSourceState> resolveAttributionSource(
    // may open a record track on behalf of a client. Note that pid may be a tid.
    // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE.
    std::optional<AttributionSourceState> resolvedAttributionSource =
            resolveAttributionSource(attributionSource);
            resolveAttributionSource(attributionSource, virtualDeviceId);
    if (!resolvedAttributionSource.has_value()) {
        return false;
    }
@@ -137,7 +139,6 @@ std::optional<AttributionSourceState> resolveAttributionSource(
    const int32_t attributedOpCode = getOpForSource(source);

    permission::PermissionChecker permissionChecker;
    resolvedAttributionSource.value().deviceId = virtualDeviceId;
    bool permitted = false;
    if (start) {
        permitted = (permissionChecker.checkPermissionForStartDataDeliveryFromDatasource(
@@ -166,13 +167,16 @@ bool recordingAllowed(const AttributionSourceState &attributionSource,
                                  String16(), /*start*/ false, source);
}

bool startRecording(const AttributionSourceState& attributionSource, const String16& msg,
bool startRecording(const AttributionSourceState& attributionSource,
                    const uint32_t virtualDeviceId,
                    const String16& msg,
                    audio_source_t source) {
    return checkRecordingInternal(attributionSource, DEVICE_ID_DEFAULT, msg, /*start*/ true,
    return checkRecordingInternal(attributionSource, virtualDeviceId, msg, /*start*/ true,
                                  source);
}

void finishRecording(const AttributionSourceState& attributionSource, audio_source_t source) {
void finishRecording(const AttributionSourceState &attributionSource, uint32_t virtualDeviceId,
                     audio_source_t source) {
    // Okay to not track in app ops as audio server is us and if
    // device is rooted security model is considered compromised.
    uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
@@ -182,7 +186,7 @@ void finishRecording(const AttributionSourceState& attributionSource, audio_sour
    // may open a record track on behalf of a client. Note that pid may be a tid.
    // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE.
    const std::optional<AttributionSourceState> resolvedAttributionSource =
            resolveAttributionSource(attributionSource);
            resolveAttributionSource(attributionSource, virtualDeviceId);
    if (!resolvedAttributionSource.has_value()) {
        return;
    }
@@ -406,7 +410,7 @@ bool mustAnonymizeBluetoothAddress(
        return false;
    }
    const std::optional<AttributionSourceState> resolvedAttributionSource =
            resolveAttributionSource(attributionSource);
            resolveAttributionSource(attributionSource, DEVICE_ID_DEFAULT);
    if (!resolvedAttributionSource.has_value()) {
        return true;
    }
+4 −2
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    int32_t pid = data_provider.ConsumeIntegral<int32_t>();
    audio_source_t source = static_cast<audio_source_t>(data_provider
        .ConsumeIntegral<std::underlying_type_t<audio_source_t>>());
    uint32_t deviceId = data_provider.ConsumeIntegral<uint32_t>();

    std::string packageNameStr = data_provider.ConsumeRandomLengthString(kMaxStringLen);
    std::string msgStr = data_provider.ConsumeRandomLengthString(kMaxStringLen);
@@ -70,8 +71,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    android::isAudioServerOrSystemServerUid(uid);
    android::isAudioServerOrMediaServerUid(uid);
    android::recordingAllowed(attributionSource);
    android::startRecording(attributionSource, msgStr16, source);
    android::finishRecording(attributionSource, source);
    android::recordingAllowed(attributionSource, deviceId, source);
    android::startRecording(attributionSource, deviceId, msgStr16, source);
    android::finishRecording(attributionSource, deviceId, source);
    android::captureAudioOutputAllowed(attributionSource);
    android::captureMediaOutputAllowed(attributionSource);
    android::captureHotwordAllowed(attributionSource);
+5 −4
Original line number Diff line number Diff line
@@ -91,11 +91,12 @@ bool recordingAllowed(const AttributionSourceState& attributionSource,
bool recordingAllowed(const AttributionSourceState &attributionSource,
                      uint32_t virtualDeviceId,
                      audio_source_t source);
bool startRecording(const AttributionSourceState& attributionSource,
bool startRecording(const AttributionSourceState& attributionSource, uint32_t virtualDeviceId,
                    const String16& msg, audio_source_t source);
void finishRecording(const AttributionSourceState& attributionSource, audio_source_t source);
void finishRecording(const AttributionSourceState& attributionSource, uint32_t virtualDeviceId,
                     audio_source_t source);
std::optional<AttributionSourceState> resolveAttributionSource(
    const AttributionSourceState& callerAttributionSource);
    const AttributionSourceState& callerAttributionSource, uint32_t virtualDeviceId);
bool captureAudioOutputAllowed(const AttributionSourceState& attributionSource);
bool captureMediaOutputAllowed(const AttributionSourceState& attributionSource);
bool captureTunerAudioInputAllowed(const AttributionSourceState& attributionSource);
+7 −5
Original line number Diff line number Diff line
@@ -823,8 +823,8 @@ Status AudioPolicyService::startInput(int32_t portIdAidl)
    msg << "Audio recording on session " << client->session;

    // check calling permissions
    if (!(startRecording(client->attributionSource, String16(msg.str().c_str()),
                         client->attributes.source)
    if (!(startRecording(client->attributionSource, client->virtualDeviceId,
                         String16(msg.str().c_str()), client->attributes.source)
            || client->attributes.source == AUDIO_SOURCE_FM_TUNER
            || client->attributes.source == AUDIO_SOURCE_REMOTE_SUBMIX
            || client->attributes.source == AUDIO_SOURCE_ECHO_REFERENCE)) {
@@ -842,7 +842,8 @@ Status AudioPolicyService::startInput(int32_t portIdAidl)
    if (client->active) {
        ALOGE("Client should never be active before startInput. Uid %d port %d",
                client->attributionSource.uid, portId);
        finishRecording(client->attributionSource, client->attributes.source);
        finishRecording(client->attributionSource, client->virtualDeviceId,
                        client->attributes.source);
        return binderStatusFromStatusT(INVALID_OPERATION);
    }

@@ -938,7 +939,8 @@ Status AudioPolicyService::startInput(int32_t portIdAidl)
        client->active = false;
        client->startTimeNs = 0;
        updateUidStates_l();
        finishRecording(client->attributionSource, client->attributes.source);
        finishRecording(client->attributionSource, client->virtualDeviceId,
                        client->attributes.source);
    }

    return binderStatusFromStatusT(status);
@@ -967,7 +969,7 @@ Status AudioPolicyService::stopInput(int32_t portIdAidl)
    updateUidStates_l();

    // finish the recording app op
    finishRecording(client->attributionSource, client->attributes.source);
    finishRecording(client->attributionSource, client->virtualDeviceId, client->attributes.source);
    AutoCallerClear acc;
    return binderStatusFromStatusT(mAudioPolicyManager->stopInput(portId));
}
+4 −3
Original line number Diff line number Diff line
@@ -1190,12 +1190,13 @@ void AudioPolicyService::setAppState_l(sp<AudioRecordClient> client, app_state_t
        if (client->silenced != silenced) {
            if (client->active) {
                if (silenced) {
                    finishRecording(client->attributionSource, client->attributes.source);
                    finishRecording(client->attributionSource, client->virtualDeviceId,
                                    client->attributes.source);
                } else {
                    std::stringstream msg;
                    msg << "Audio recording un-silenced on session " << client->session;
                    if (!startRecording(client->attributionSource, String16(msg.str().c_str()),
                            client->attributes.source)) {
                    if (!startRecording(client->attributionSource, client->virtualDeviceId,
                                        String16(msg.str().c_str()), client->attributes.source)) {
                        silenced = true;
                    }
                }