OSDN Git Service

Limit unprivileged keepalives per uid
authorjunyulai <junyulai@google.com>
Tue, 30 Apr 2019 06:42:05 +0000 (14:42 +0800)
committerChalard Jean <jchalard@google.com>
Mon, 13 May 2019 06:53:02 +0000 (15:53 +0900)
Public APIs for creating unprivileged NATT socket keepalive
might allow users to exhaust resource if malicious apps try
to create keepalives with fd which is not created by
IpSecService through binder call. Thus, this change add
customizable limitation per uid to prevent resource exhaustion
attack.

Bug: 129371366
Bug: 132307230
Test: atest FrameworksNetTests

Clean cherry-pick of aosp/954040
Merged-In: Ibcb91105e46f7e898b8aa7c2babc3344ef2c6257
Merged-In: Ia667386c1a8949839871a6949d79552d9c8b88f0

Change-Id: I92f6d977b6dfde4e1bf74df6b60c9a0b9e8eec40

core/res/res/values/config.xml
core/res/res/values/symbols.xml
services/core/java/com/android/server/connectivity/KeepaliveTracker.java

index 5201008..3ac0af7 100644 (file)
     <!-- Reserved privileged keepalive slots per transport. -->
     <integer translatable="false" name="config_reservedPrivilegedKeepaliveSlots">2</integer>
 
+    <!-- Allowed unprivileged keepalive slots per uid. -->
+    <integer translatable="false" name="config_allowedUnprivilegedKeepalivePerUid">2</integer>
+
     <!-- List of regexpressions describing the interface (if any) that represent tetherable
          USB interfaces.  If the device doesn't want to support tethering over USB this should
          be empty.  An example would be "usb.*" -->
index b6d4d76..d91036a 100644 (file)
   <java-symbol type="integer" name="config_networkMeteredMultipathPreference" />
   <java-symbol type="array" name="config_networkSupportedKeepaliveCount" />
   <java-symbol type="integer" name="config_reservedPrivilegedKeepaliveSlots" />
+  <java-symbol type="integer" name="config_allowedUnprivilegedKeepalivePerUid" />
   <java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
   <java-symbol type="integer" name="config_notificationsBatteryLedOff" />
   <java-symbol type="integer" name="config_notificationsBatteryLedOn" />
index 1e3e6a5..4437926 100644 (file)
@@ -104,6 +104,10 @@ public class KeepaliveTracker {
     // the number of remaining keepalive slots is less than or equal to the threshold.
     private final int mReservedPrivilegedSlots;
 
+    // Allowed unprivileged keepalive slots per uid. Caller's permission will be enforced if
+    // the number of remaining keepalive slots is less than or equal to the threshold.
+    private final int mAllowedUnprivilegedSlotsForUid;
+
     public KeepaliveTracker(Context context, Handler handler) {
         mConnectivityServiceHandler = handler;
         mTcpController = new TcpKeepaliveController(handler);
@@ -111,6 +115,8 @@ public class KeepaliveTracker {
         mSupportedKeepalives = KeepaliveUtils.getSupportedKeepalives(mContext);
         mReservedPrivilegedSlots = mContext.getResources().getInteger(
                 R.integer.config_reservedPrivilegedKeepaliveSlots);
+        mAllowedUnprivilegedSlotsForUid = mContext.getResources().getInteger(
+                R.integer.config_allowedUnprivilegedKeepalivePerUid);
     }
 
     /**
@@ -275,6 +281,18 @@ public class KeepaliveTracker {
                 return ERROR_INSUFFICIENT_RESOURCES;
             }
 
+            // Count unprivileged keepalives for the same uid across networks.
+            int unprivilegedCountSameUid = 0;
+            for (final HashMap<Integer, KeepaliveInfo> kaForNetwork : mKeepalives.values()) {
+                for (final KeepaliveInfo ki : kaForNetwork.values()) {
+                    if (ki.mUid == mUid) {
+                        unprivilegedCountSameUid++;
+                    }
+                }
+            }
+            if (unprivilegedCountSameUid > mAllowedUnprivilegedSlotsForUid) {
+                return ERROR_INSUFFICIENT_RESOURCES;
+            }
             return SUCCESS;
         }
 
@@ -674,6 +692,7 @@ public class KeepaliveTracker {
     public void dump(IndentingPrintWriter pw) {
         pw.println("Supported Socket keepalives: " + Arrays.toString(mSupportedKeepalives));
         pw.println("Reserved Privileged keepalives: " + mReservedPrivilegedSlots);
+        pw.println("Allowed Unprivileged keepalives per uid: " + mAllowedUnprivilegedSlotsForUid);
         pw.println("Socket keepalives:");
         pw.increaseIndent();
         for (NetworkAgentInfo nai : mKeepalives.keySet()) {