Logging to KEY_INTENT security failure
To help debugging we would like to know the targetPackageName and uid of
the KEY_INTENT that is being rejected.
Bug: 27598664
Change-Id: Idcf1eea82a96913947975b6fe3aa1e9c6e5109a7
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index a63faf1..d4dd505 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -47,6 +47,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -2460,31 +2461,12 @@
public void onResult(Bundle result) {
mNumResults++;
Intent intent = null;
-
if (result != null
&& (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
- /*
- * The Authenticator API allows third party authenticators to
- * supply arbitrary intents to other apps that they can run,
- * this can be very bad when those apps are in the system like
- * the System Settings.
- */
- int authenticatorUid = Binder.getCallingUid();
- long bid = Binder.clearCallingIdentity();
- try {
- PackageManager pm = mContext.getPackageManager();
- ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId);
- int targetUid = resolveInfo.activityInfo.applicationInfo.uid;
- if (PackageManager.SIGNATURE_MATCH != pm.checkSignatures(authenticatorUid,
- targetUid)) {
- throw new SecurityException("Activity to be started with KEY_INTENT must "
- + "share Authenticator's signatures");
- }
- } finally {
- Binder.restoreCallingIdentity(bid);
- }
+ checkKeyIntent(
+ Binder.getCallingUid(),
+ intent);
}
-
IAccountManagerResponse response;
if (mExpectActivityLaunch && result != null
&& result.containsKey(AccountManager.KEY_INTENT)) {
@@ -3569,6 +3551,36 @@
return response;
}
+ /**
+ * Checks Intents, supplied via KEY_INTENT, to make sure that they don't violate our
+ * security policy.
+ *
+ * In particular we want to make sure that the Authenticator doesn't try to trick users
+ * 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 {
+ long bid = Binder.clearCallingIdentity();
+ try {
+ PackageManager pm = mContext.getPackageManager();
+ ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId);
+ ActivityInfo targetActivityInfo = resolveInfo.activityInfo;
+ int targetUid = targetActivityInfo.applicationInfo.uid;
+ if (PackageManager.SIGNATURE_MATCH != pm.checkSignatures(authUid, targetUid)) {
+ String pkgName = targetActivityInfo.packageName;
+ 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));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(bid);
+ }
+ }
+
private void close() {
synchronized (mSessions) {
if (mSessions.remove(toString()) == null) {
@@ -3711,27 +3723,9 @@
}
if (result != null
&& (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) {
- /*
- * The Authenticator API allows third party authenticators to
- * supply arbitrary intents to other apps that they can run,
- * this can be very bad when those apps are in the system like
- * the System Settings.
- */
- int authenticatorUid = Binder.getCallingUid();
- long bid = Binder.clearCallingIdentity();
- try {
- PackageManager pm = mContext.getPackageManager();
- ResolveInfo resolveInfo = pm.resolveActivityAsUser(intent, 0, mAccounts.userId);
- int targetUid = resolveInfo.activityInfo.applicationInfo.uid;
- if (PackageManager.SIGNATURE_MATCH !=
- pm.checkSignatures(authenticatorUid, targetUid)) {
- throw new SecurityException(
- "Activity to be started with KEY_INTENT must " +
- "share Authenticator's signatures");
- }
- } finally {
- Binder.restoreCallingIdentity(bid);
- }
+ checkKeyIntent(
+ Binder.getCallingUid(),
+ intent);
}
if (result != null
&& !TextUtils.isEmpty(result.getString(AccountManager.KEY_AUTHTOKEN))) {