From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: tiansiming <tiansiming@xiaomi.com>
Date: Wed, 20 Sep 2017 13:59:13 +0800
Subject: [PATCH] Fix another AddAccountSettings memory leak

The memory leak will always occur in AddAccoutSettings
when Bundle with an invalid intent returned in the addAccount we implement.

Bug:https://issuetracker.google.com/issues/66088681
Test:Install the app through the github offered in above link,
then press the "Test" item in ChooseAccountActivity (adb shell am start -n
'com.android.settings/.accounts.ChooseAccountActivity') serveal times.
Check the activity number by "adb shell dumpsys meminfo com.android.settings".

Change-Id: Id15fc73521d0ddc6ca891b6029ad04cd4427dbfe
Signed-off-by: tiansiming <tiansiming@xiaomi.com>
---
 .../accounts/AccountManagerService.java       | 36 +++++++++++++------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 520a0d314318..dd3e4d9cb17c 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2530,9 +2530,13 @@ public class AccountManagerService
                              * have users launching arbitrary activities by tricking users to
                              * interact with malicious notifications.
                              */
-                            checkKeyIntent(
+                            if (!checkKeyIntent(
                                     Binder.getCallingUid(),
-                                    intent);
+                                    intent)) {
+                                onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
+                                        "invalid intent in bundle returned");
+                                return;
+                            }
                             doNotification(mAccounts,
                                     account, result.getString(AccountManager.KEY_AUTH_FAILED_MESSAGE),
                                     intent, "android", accounts.userId);
@@ -2941,9 +2945,13 @@ public class AccountManagerService
             Intent intent = null;
             if (result != null
                     && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
-                checkKeyIntent(
+                if (!checkKeyIntent(
                         Binder.getCallingUid(),
-                        intent);
+                        intent)) {
+                    onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
+                            "invalid intent in bundle returned");
+                    return;
+                }
             }
             IAccountManagerResponse response;
             if (mExpectActivityLaunch && result != null
@@ -4209,9 +4217,7 @@ public class AccountManagerService
          * into launching aribtrary intents on the device via by tricking to click authenticator
          * supplied entries in the system Settings app.
          */
-        protected void checkKeyIntent(
-                int authUid,
-                Intent intent) throws SecurityException {
+        protected boolean checkKeyIntent(int authUid, Intent intent) {
             intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_READ_URI_PERMISSION
                     | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                     | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
@@ -4220,6 +4226,9 @@ public class AccountManagerService
             try {
                 PackageManager pm = mContext.getPackageManager();
                 ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId);
+                if (resolveInfo == null) {
+                    return false;
+                }
                 ActivityInfo targetActivityInfo = resolveInfo.activityInfo;
                 int targetUid = targetActivityInfo.applicationInfo.uid;
                 if (PackageManager.SIGNATURE_MATCH != pm.checkSignatures(authUid, targetUid)) {
@@ -4227,9 +4236,10 @@ public class AccountManagerService
                     String activityName = targetActivityInfo.name;
                     String tmpl = "KEY_INTENT resolved to an Activity (%s) in a package (%s) that "
                             + "does not share a signature with the supplying authenticator (%s).";
-                    throw new SecurityException(
-                            String.format(tmpl, activityName, pkgName, mAccountType));
+                    Log.e(TAG, String.format(tmpl, activityName, pkgName, mAccountType));
+                    return false;
                 }
+                return true;
             } finally {
                 Binder.restoreCallingIdentity(bid);
             }
@@ -4378,9 +4388,13 @@ public class AccountManagerService
             }
             if (result != null
                     && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
-                checkKeyIntent(
+                if (!checkKeyIntent(
                         Binder.getCallingUid(),
-                        intent);
+                        intent)) {
+                    onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
+                            "invalid intent in bundle returned");
+                    return;
+                }
             }
             if (result != null
                     && !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) {
