From 0586a602922f23e846821bd843e487676c0f6562 Mon Sep 17 00:00:00 2001 From: junyulai Date: Tue, 30 Apr 2019 14:42:05 +0800 Subject: [PATCH] Limit unprivileged keepalives per uid 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 Change-Id: Ibcb91105e46f7e898b8aa7c2babc3344ef2c6257 --- .../server/connectivity/KeepaliveTracker.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java index 4ba88a8dd0..ae58e994a5 100644 --- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java +++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java @@ -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); } /** @@ -276,6 +282,18 @@ public class KeepaliveTracker { return ERROR_INSUFFICIENT_RESOURCES; } + // Count unprivileged keepalives for the same uid across networks. + int unprivilegedCountSameUid = 0; + for (final HashMap kaForNetwork : mKeepalives.values()) { + for (final KeepaliveInfo ki : kaForNetwork.values()) { + if (ki.mUid == mUid) { + unprivilegedCountSameUid++; + } + } + } + if (unprivilegedCountSameUid > mAllowedUnprivilegedSlotsForUid) { + return ERROR_INSUFFICIENT_RESOURCES; + } return SUCCESS; } @@ -701,6 +719,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()) {