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
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index a91fc26..c19cb6a 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -4588,10 +4588,25 @@
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 @@
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 @@
// 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;
}
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 1d5d3c8..f353f3b 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -506,6 +506,8 @@
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 @@
// 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 @@
&& 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 @@
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 @@
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;
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 3cca054..ba6e6e5 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -388,7 +388,7 @@
}
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;