diff options
author | Carlos Valdivia <carlosvaldivia@google.com> | 2014-09-08 20:12:24 -0700 |
---|---|---|
committer | Carlos Valdivia <carlosvaldivia@google.com> | 2014-09-09 11:17:19 -0700 |
commit | 92f761550246e60016ce1c37f1c19869536756af (patch) | |
tree | 0dd94d1721c47cf3abcb69f0014211b2577bdd04 /src/com/android/settings/accounts | |
parent | bec89d797b6f2680c544639faed7e47573625e11 (diff) | |
download | packages_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.java | 51 |
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 |