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

Commit 8e7cc8fa authored by Edgar Wang's avatar Edgar Wang
Browse files

Fix bypass CALL_PRIVILEGED permission in AppRestrictionsFragment

In onReceive of AppRestrictionsFragment.java, there is a possible way to
start a phone call without permissions due to a confused deputy.
This could lead to local escalation of privilege with no additional
execution privileges needed.

We should not allow the restrictionsIntent to startActivity simply
because it resolves to multiple activities.
Instead, we should call resolveActivity and check the result's package
name is same as current package name, then it is safe to startActivity.

Bug: 200688991
Test: manual verify
Change-Id: Iaa2d3a9497c3266babe0789961befc9776a4db7a
Merged-In: Iaa2d3a9497c3266babe0789961befc9776a4db7a
(cherry picked from commit 359512cd)
parent 88b7d05d
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.settings.users;

import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -37,6 +38,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.EventLog;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
@@ -641,7 +643,15 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
            } else if (restrictionsIntent != null) {
                preference.setRestrictions(restrictions);
                if (invokeIfCustom && AppRestrictionsFragment.this.isResumed()) {
                    try {
                        assertSafeToStartCustomActivity(restrictionsIntent);
                    } catch (ActivityNotFoundException | SecurityException e) {
                        // return without startActivity
                        Log.e(TAG, "Cannot start restrictionsIntent " + e);
                        EventLog.writeEvent(0x534e4554, "200688991", -1 /* UID */, "");
                        return;
                    }

                    int requestCode = generateCustomActivityRequestCode(
                            RestrictionsResultReceiver.this.preference);
                    AppRestrictionsFragment.this.startActivityForResult(
@@ -655,14 +665,14 @@ public class AppRestrictionsFragment extends SettingsPreferenceFragment implemen
            if (intent.getPackage() != null && intent.getPackage().equals(packageName)) {
                return;
            }
            // Activity can be started if intent resolves to multiple activities
            List<ResolveInfo> resolveInfos = AppRestrictionsFragment.this.mPackageManager
                    .queryIntentActivities(intent, 0 /* no flags */);
            if (resolveInfos.size() != 1) {
                return;
            ResolveInfo resolveInfo = mPackageManager.resolveActivity(
                    intent, PackageManager.MATCH_DEFAULT_ONLY);

            if (resolveInfo == null) {
                throw new ActivityNotFoundException("No result for resolving " + intent);
            }
            // Prevent potential privilege escalation
            ActivityInfo activityInfo = resolveInfos.get(0).activityInfo;
            ActivityInfo activityInfo = resolveInfo.activityInfo;
            if (!packageName.equals(activityInfo.packageName)) {
                throw new SecurityException("Application " + packageName
                        + " is not allowed to start activity " + intent);