summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/accounts
diff options
context:
space:
mode:
authorCarlos Valdivia <carlosvaldivia@google.com>2014-09-08 20:12:24 -0700
committerCarlos Valdivia <carlosvaldivia@google.com>2014-09-09 11:17:19 -0700
commit92f761550246e60016ce1c37f1c19869536756af (patch)
tree0dd94d1721c47cf3abcb69f0014211b2577bdd04 /src/com/android/settings/accounts
parentbec89d797b6f2680c544639faed7e47573625e11 (diff)
downloadpackages_apps_Settings-92f761550246e60016ce1c37f1c19869536756af.zip
packages_apps_Settings-92f761550246e60016ce1c37f1c19869536756af.tar.gz
packages_apps_Settings-92f761550246e60016ce1c37f1c19869536756af.tar.bz2
SECURITY: Prevent preference intents from exploiting settings.
Settings has super powers because it shares the system uid. We prevent those powers from being exploited by malicious authenticators by checking the intents those authenticators provide. We will only launch intents that resolve to Activities that are exported=true or owned by the same UID as the authenticator. Bug: 14408627 Change-Id: Ia179df8561d29745767dac0f3c97eb0f68083f59
Diffstat (limited to 'src/com/android/settings/accounts')
-rw-r--r--src/com/android/settings/accounts/ManageAccountsSettings.java51
1 files changed, 48 insertions, 3 deletions
diff --git a/src/com/android/settings/accounts/ManageAccountsSettings.java b/src/com/android/settings/accounts/ManageAccountsSettings.java
index 8787bce..074176b 100644
--- a/src/com/android/settings/accounts/ManageAccountsSettings.java
+++ b/src/com/android/settings/accounts/ManageAccountsSettings.java
@@ -18,6 +18,7 @@ package com.android.settings.accounts;
import android.accounts.Account;
import android.accounts.AccountManager;
+import android.accounts.AuthenticatorDescription;
import android.app.ActionBar;
import android.app.Activity;
import android.content.ContentResolver;
@@ -25,7 +26,11 @@ import android.content.Intent;
import android.content.SyncAdapterType;
import android.content.SyncInfo;
import android.content.SyncStatusInfo;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -423,7 +428,7 @@ public class ManageAccountsSettings extends AccountPreferenceBase
* intent, and hack the location settings to start it as a fragment.
*/
private void updatePreferenceIntents(PreferenceScreen prefs) {
- PackageManager pm = getActivity().getPackageManager();
+ final PackageManager pm = getActivity().getPackageManager();
for (int i = 0; i < prefs.getPreferenceCount();) {
Preference pref = prefs.getPreference(i);
Intent intent = pref.getIntent();
@@ -461,8 +466,22 @@ public class ManageAccountsSettings extends AccountPreferenceBase
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
- getActivity().startActivityAsUser(preference.getIntent(),
- mUserHandle);
+ Intent prefIntent = preference.getIntent();
+ /*
+ * Check the intent to see if it resolves to a exported=false
+ * activity that doesn't share a uid with the authenticator.
+ *
+ * Otherwise the intent is considered unsafe in that it will be
+ * exploiting the fact that settings has system privileges.
+ */
+ if (isSafeIntent(pm, prefIntent)) {
+ getActivity().startActivityAsUser(prefIntent, mUserHandle);
+ } else {
+ Log.e(TAG,
+ "Refusing to launch authenticator intent because"
+ + "it exploits Settings permissions: "
+ + prefIntent);
+ }
return true;
}
});
@@ -473,6 +492,32 @@ public class ManageAccountsSettings extends AccountPreferenceBase
}
}
+ /**
+ * Determines if the supplied Intent is safe. A safe intent is one that is
+ * will launch a exported=true activity or owned by the same uid as the
+ * authenticator supplying the intent.
+ */
+ private boolean isSafeIntent(PackageManager pm, Intent intent) {
+ AuthenticatorDescription authDesc =
+ mAuthenticatorHelper.getAccountTypeDescription(mAccountType);
+ ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
+ if (resolveInfo == null) {
+ return false;
+ }
+ ActivityInfo resolvedActivityInfo = resolveInfo.activityInfo;
+ ApplicationInfo resolvedAppInfo = resolvedActivityInfo.applicationInfo;
+ try {
+ ApplicationInfo authenticatorAppInf = pm.getApplicationInfo(authDesc.packageName, 0);
+ return resolvedActivityInfo.exported
+ || resolvedAppInfo.uid == authenticatorAppInf.uid;
+ } catch (NameNotFoundException e) {
+ Log.e(TAG,
+ "Intent considered unsafe due to exception.",
+ e);
+ return false;
+ }
+ }
+
@Override
protected void onAuthDescriptionsUpdated() {
// Update account icons for all account preference items