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

Commit ad7dd961 authored by Eric Laurent's avatar Eric Laurent
Browse files

audioflinger: limit max number of tracks per client

Limit max number of audio tracks for a given application to
limit the chance of denial of service by misbehaving apps
not releasing tracks.

Bug: 7007023
Change-Id: Id7ac37450aabdbeaa5f83cb6e4b2a2b0c749f99c
parent 08e1f417
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -4588,10 +4588,25 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac
    return mixerStatus;
}

// trackCountForUid_l() must be called with ThreadBase::mLock held
uint32_t AudioFlinger::PlaybackThread::trackCountForUid_l(uid_t uid)
{
    uint32_t trackCount = 0;
    for (size_t i = 0; i < mTracks.size() ; i++) {
        if (mTracks[i]->uid() == (int)uid) {
            trackCount++;
        }
    }
    return trackCount;
}

// getTrackName_l() must be called with ThreadBase::mLock held
int AudioFlinger::MixerThread::getTrackName_l(audio_channel_mask_t channelMask,
        audio_format_t format, audio_session_t sessionId)
        audio_format_t format, audio_session_t sessionId, uid_t uid)
{
    if (trackCountForUid_l(uid) > (PlaybackThread::kMaxTracksPerUid - 1)) {
        return -1;
    }
    return mAudioMixer->getTrackName(channelMask, format, sessionId);
}

@@ -4696,7 +4711,7 @@ bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePa
            mAudioMixer = new AudioMixer(mNormalFrameCount, mSampleRate);
            for (size_t i = 0; i < mTracks.size() ; i++) {
                int name = getTrackName_l(mTracks[i]->mChannelMask,
                        mTracks[i]->mFormat, mTracks[i]->mSessionId);
                        mTracks[i]->mFormat, mTracks[i]->mSessionId, mTracks[i]->uid());
                if (name < 0) {
                    break;
                }
@@ -5141,8 +5156,11 @@ bool AudioFlinger::DirectOutputThread::shouldStandby_l()

// getTrackName_l() must be called with ThreadBase::mLock held
int AudioFlinger::DirectOutputThread::getTrackName_l(audio_channel_mask_t channelMask __unused,
        audio_format_t format __unused, audio_session_t sessionId __unused)
        audio_format_t format __unused, audio_session_t sessionId __unused, uid_t uid)
{
    if (trackCountForUid_l(uid) > (PlaybackThread::kMaxTracksPerUid - 1)) {
        return -1;
    }
    return 0;
}

+10 −6
Original line number Diff line number Diff line
@@ -506,6 +506,8 @@ public:
    static const int8_t kMaxTrackRetriesOffload = 20;
    static const int8_t kMaxTrackStartupRetriesOffload = 100;
    static const int8_t kMaxTrackStopRetriesOffload = 2;
    // 14 tracks max per client allows for 2 misbehaving application leaving 4 available tracks.
    static const uint32_t kMaxTracksPerUid = 14;

    PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
                   audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
@@ -736,8 +738,8 @@ protected:

    // Allocate a track name for a given channel mask.
    //   Returns name >= 0 if successful, -1 on failure.
    virtual int             getTrackName_l(audio_channel_mask_t channelMask,
                                           audio_format_t format, audio_session_t sessionId) = 0;
    virtual int             getTrackName_l(audio_channel_mask_t channelMask, audio_format_t format,
                                           audio_session_t sessionId, uid_t uid) = 0;
    virtual void            deleteTrackName_l(int name) = 0;

    // Time to sleep between cycles when:
@@ -767,6 +769,8 @@ protected:
                                    && mHwSupportsPause
                                    && (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }

                uint32_t    trackCountForUid_l(uid_t uid);

private:

    friend class AudioFlinger;      // for numerous
@@ -889,8 +893,8 @@ public:

protected:
    virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
    virtual     int         getTrackName_l(audio_channel_mask_t channelMask,
                                           audio_format_t format, audio_session_t sessionId);
    virtual     int         getTrackName_l(audio_channel_mask_t channelMask, audio_format_t format,
                                           audio_session_t sessionId, uid_t uid);
    virtual     void        deleteTrackName_l(int name);
    virtual     uint32_t    idleSleepTimeUs() const;
    virtual     uint32_t    suspendSleepTimeUs() const;
@@ -969,8 +973,8 @@ public:
    virtual     void        flushHw_l();

protected:
    virtual     int         getTrackName_l(audio_channel_mask_t channelMask,
                                           audio_format_t format, audio_session_t sessionId);
    virtual     int         getTrackName_l(audio_channel_mask_t channelMask, audio_format_t format,
                                           audio_session_t sessionId, uid_t uid);
    virtual     void        deleteTrackName_l(int name);
    virtual     uint32_t    activeSleepTimeUs() const;
    virtual     uint32_t    idleSleepTimeUs() const;
+1 −1
Original line number Diff line number Diff line
@@ -388,7 +388,7 @@ AudioFlinger::PlaybackThread::Track::Track(
    }
    mServerProxy = mAudioTrackServerProxy;

    mName = thread->getTrackName_l(channelMask, format, sessionId);
    mName = thread->getTrackName_l(channelMask, format, sessionId, uid);
    if (mName < 0) {
        ALOGE("no more track names available");
        return;