From 2da50cfe339113e334e61efc0d4927cf6458aa8b Mon Sep 17 00:00:00 2001 From: Hall Liu Date: Wed, 18 Mar 2020 16:24:04 -0700 Subject: [PATCH] Institute limit on PhoneStateListener Limit apps to 50 concurrently registered instances of PhoneStateListener via TelephonyManager#listen Test: atest CtsTelephonyTestCases:PhoneStateListenerTest#testListenerLimit Bug: 151835251 Change-Id: I8486d86773a1e28b4018620c48003855dae75b9d --- .../android/telephony/PhoneStateListener.java | 12 ++++++++ .../com/android/server/TelephonyRegistry.java | 30 ++++++++++++++++--- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index d2735008611c0..a2af15866d668 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -64,6 +64,18 @@ public class PhoneStateListener { private static final String LOG_TAG = "PhoneStateListener"; private static final boolean DBG = false; // STOPSHIP if true + + /** + * Limit on registrations of {@link PhoneStateListener}s on a per-pid + * basis. When this limit is exceeded, any calls to {@link TelephonyManager#listen} will fail + * with an {@link IllegalStateException}. + * + * {@link android.os.Process#PHONE_UID}, {@link android.os.Process#SYSTEM_UID}, and the uid that + * TelephonyRegistry runs under are exempt from this limit. + * @hide + */ + public static final int PER_PID_REGISTRATION_LIMIT = 50; + /** * Stop listening for updates. * diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 7dedad7f2fea6..ae379e1858fff 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -39,6 +39,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; import android.telephony.Annotation; @@ -605,7 +606,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { // register IBinder b = callback.asBinder(); - Record r = add(b); + Record r = add(b, Binder.getCallingPid(), false); if (r == null) { return; @@ -659,7 +660,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { // register IBinder b = callback.asBinder(); - Record r = add(b); + Record r = add(b, Binder.getCallingPid(), false); if (r == null) { return; @@ -789,7 +790,11 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { // register IBinder b = callback.asBinder(); - Record r = add(b); + boolean shouldEnforceListenerLimit = + Binder.getCallingUid() != Process.SYSTEM_UID + && Binder.getCallingUid() != Process.PHONE_UID + && Binder.getCallingUid() != Process.myUid(); + Record r = add(b, Binder.getCallingPid(), shouldEnforceListenerLimit); if (r == null) { return; @@ -1084,18 +1089,35 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : ""; } - private Record add(IBinder binder) { + private Record add(IBinder binder, int callingPid, boolean enforceLimit) { Record r; synchronized (mRecords) { final int N = mRecords.size(); + // While iterating through the records, keep track of how many we have from this pid. + int numRecordsForPid = 0; for (int i = 0; i < N; i++) { r = mRecords.get(i); if (binder == r.binder) { // Already existed. return r; } + if (r.callerPid == callingPid) { + numRecordsForPid++; + } } + // If we've exceeded the limit for registrations, log a warning and quit. + if (enforceLimit && numRecordsForPid >= PhoneStateListener.PER_PID_REGISTRATION_LIMIT) { + String errorMsg = "Pid " + callingPid + " has exceeded the number of permissible" + + "registered listeners. Ignoring request to add."; + loge(errorMsg); + throw new IllegalStateException(errorMsg); + } else if (enforceLimit + && numRecordsForPid >= PhoneStateListener.PER_PID_REGISTRATION_LIMIT / 2) { + Rlog.w(TAG, "Pid " + callingPid + " has exceeded half the number of permissible" + + "registered listeners. Now at " + numRecordsForPid); + } + r = new Record(); r.binder = binder; r.deathRecipient = new TelephonyRegistryDeathRecipient(binder);