Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75ae46d0 authored by Dmitry Dementyev's avatar Dmitry Dementyev
Browse files

Add permission check to Intents used by Authenticator Settings.

Setting shares system uid and can be used to bypass different security
checks.
We add proper handling for intents which resolve toexported=true
activities with permission filed.
Added nested preferences filtering.

Bug: 33123882
Test: manual tests
Change-Id: Ib5bab7989fc44b4391f9050c6b18f81c58c09cf6
parent 2e006b2b
Loading
Loading
Loading
Loading
+21 −11
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
import android.util.Log;
import android.view.LayoutInflater;
@@ -422,15 +423,18 @@ public class ManageAccountsSettings extends AccountPreferenceBase
    }

    /**
     * Filters through the preference list provided by GoogleLoginService.
     * Recursively filters through the preference list provided by GoogleLoginService.
     *
     * This method removes all the invalid intent from the list, adds account name as extra into the
     * intent, and hack the location settings to start it as a fragment.
     */
    private void updatePreferenceIntents(PreferenceScreen prefs) {
    private void updatePreferenceIntents(PreferenceGroup prefs) {
        final PackageManager pm = getActivity().getPackageManager();
        for (int i = 0; i < prefs.getPreferenceCount();) {
            Preference pref = prefs.getPreference(i);
            if (pref instanceof PreferenceGroup) {
                updatePreferenceIntents((PreferenceGroup) pref);
            }
            Intent intent = pref.getIntent();
            if (intent != null) {
                // Hack. Launch "Location" as fragment instead of as activity.
@@ -500,20 +504,26 @@ public class ManageAccountsSettings extends AccountPreferenceBase
    private boolean isSafeIntent(PackageManager pm, Intent intent) {
        AuthenticatorDescription authDesc =
                mAuthenticatorHelper.getAccountTypeDescription(mAccountType);
        ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
        ResolveInfo resolveInfo =
            pm.resolveActivityAsUser(intent, 0, mUserHandle.getIdentifier());
        if (resolveInfo == null) {
            return false;
        }
        ActivityInfo resolvedActivityInfo = resolveInfo.activityInfo;
        ApplicationInfo resolvedAppInfo = resolvedActivityInfo.applicationInfo;
        try {
            if (resolvedActivityInfo.exported) {
                if (resolvedActivityInfo.permission == null) {
                    return true; // exported activity without permission.
                } else if (pm.checkPermission(resolvedActivityInfo.permission,
                        authDesc.packageName) == PackageManager.PERMISSION_GRANTED) {
                    return true;
                }
            }
            ApplicationInfo authenticatorAppInf = pm.getApplicationInfo(authDesc.packageName, 0);
            return resolvedActivityInfo.exported
                    || resolvedAppInfo.uid == authenticatorAppInf.uid;
            return  resolvedAppInfo.uid == authenticatorAppInf.uid;
        } catch (NameNotFoundException e) {
            Log.e(TAG,
                    "Intent considered unsafe due to exception.",
                    e);
            Log.e(TAG, "Intent considered unsafe due to exception.", e);
            return false;
        }
    }