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

Commit 01a8c813 authored by Bernardo Rufino's avatar Bernardo Rufino Committed by Android (Google) Code Review
Browse files

Merge "Restrict {AM,WM}.closeSystemDialogs()"

parents 9dcb0d78 4347ccb7
Loading
Loading
Loading
Loading
+4 −62
Original line number Original line Diff line number Diff line
@@ -174,7 +174,6 @@ import android.app.ProfilerInfo;
import android.app.WaitResult;
import android.app.WaitResult;
import android.app.backup.BackupManager.OperationType;
import android.app.backup.BackupManager.OperationType;
import android.app.backup.IBackupManager;
import android.app.backup.IBackupManager;
import android.app.compat.CompatChanges;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageEvents.Event;
import android.app.usage.UsageStatsManager;
import android.app.usage.UsageStatsManager;
@@ -13721,34 +13720,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                            false, false, userId, "package unstartable");
                            false, false, userId, "package unstartable");
                    break;
                    break;
                case Intent.ACTION_CLOSE_SYSTEM_DIALOGS:
                case Intent.ACTION_CLOSE_SYSTEM_DIALOGS:
                    if (!canCloseSystemDialogs(callingPid, callingUid, callerApp)) {
                    if (!mAtmInternal.checkCanCloseSystemDialogs(callingPid, callingUid,
                        // The app can't close system dialogs, throw only if it targets S+
                            callerPackage)) {
                        if (CompatChanges.isChangeEnabled(
                                ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, callingUid)) {
                            throw new SecurityException(
                                    "Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS
                                            + " broadcast from " + callerPackage + " (pid="
                                            + callingPid + ", uid=" + callingUid + ")"
                                            + " requires "
                                            + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS + ".");
                        } else if (CompatChanges.isChangeEnabled(
                                ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS, callingUid)) {
                            Slog.w(TAG, "Permission Denial: " + intent.getAction()
                                    + " broadcast from " + callerPackage + " (pid=" + callingPid
                                    + ", uid=" + callingUid + ")"
                                    + " requires "
                                    + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS
                                    + ", dropping broadcast.");
                        // Returning success seems to be the pattern here
                        // Returning success seems to be the pattern here
                        return ActivityManager.BROADCAST_SUCCESS;
                        return ActivityManager.BROADCAST_SUCCESS;
                        } else {
                            Slog.w(TAG, intent.getAction()
                                    + " broadcast from " + callerPackage + " (pid=" + callingPid
                                    + ", uid=" + callingUid + ")"
                                    + " will require  "
                                    + permission.BROADCAST_CLOSE_SYSTEM_DIALOGS
                                    + " in future builds.");
                        }
                    }
                    }
                    break;
                    break;
            }
            }
@@ -14043,39 +14018,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        return ActivityManager.BROADCAST_SUCCESS;
        return ActivityManager.BROADCAST_SUCCESS;
    }
    }
    private boolean canCloseSystemDialogs(int pid, int uid, @Nullable ProcessRecord callerApp) {
        if (checkPermission(permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, pid, uid)
                == PERMISSION_GRANTED) {
            return true;
        }
        if (callerApp == null) {
            synchronized (mPidsSelfLocked) {
                callerApp = mPidsSelfLocked.get(pid);
            }
        }
        if (callerApp != null) {
            // Check if the instrumentation of the process has the permission. This covers the usual
            // test started from the shell (which has the permission) case. This is needed for apps
            // targeting SDK level < S but we are also allowing for targetSdk S+ as a convenience to
            // avoid breaking a bunch of existing tests and asking them to adopt shell permissions
            // to do this.
            ActiveInstrumentation instrumentation = callerApp.getActiveInstrumentation();
            if (instrumentation != null && checkPermission(
                    permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, -1, instrumentation.mSourceUid)
                    == PERMISSION_GRANTED) {
                return true;
            }
            // This is the notification trampoline use-case for example, where apps use Intent.ACSD
            // to close the shade prior to starting an activity.
            WindowProcessController wmApp = callerApp.getWindowProcessController();
            if (wmApp.canCloseSystemDialogsByToken()) {
                return true;
            }
        }
        return false;
    }
    /**
    /**
     * @return uid from the extra field {@link Intent#EXTRA_UID} if present, Otherwise -1
     * @return uid from the extra field {@link Intent#EXTRA_UID} if present, Otherwise -1
     */
     */
+3 −1
Original line number Original line Diff line number Diff line
@@ -1431,7 +1431,9 @@ class ProcessRecord implements WindowProcessListener {
    void setActiveInstrumentation(ActiveInstrumentation instr) {
    void setActiveInstrumentation(ActiveInstrumentation instr) {
        mInstr = instr;
        mInstr = instr;
        boolean isInstrumenting = instr != null;
        boolean isInstrumenting = instr != null;
        mWindowProcessController.setInstrumenting(isInstrumenting,
        mWindowProcessController.setInstrumenting(
                isInstrumenting,
                isInstrumenting ? instr.mSourceUid : -1,
                isInstrumenting && instr.mHasBackgroundActivityStartsPermission);
                isInstrumenting && instr.mHasBackgroundActivityStartsPermission);
    }
    }


+8 −0
Original line number Original line Diff line number Diff line
@@ -284,6 +284,14 @@ public abstract class ActivityTaskManagerInternal {
     */
     */
    public abstract void enforceCallerIsRecentsOrHasPermission(String permission, String func);
    public abstract void enforceCallerIsRecentsOrHasPermission(String permission, String func);


    /**
     * Returns true if the app can close system dialogs. Otherwise it either throws a {@link
     * SecurityException} or returns false with a logcat message depending on whether the app
     * targets SDK level {@link android.os.Build.VERSION_CODES#S} or not.
     */
    public abstract boolean checkCanCloseSystemDialogs(int pid, int uid,
            @Nullable String packageName);

    /**
    /**
     * Called after the voice interaction service has changed.
     * Called after the voice interaction service has changed.
     */
     */
+91 −1
Original line number Original line Diff line number Diff line
@@ -147,6 +147,7 @@ import android.app.WindowConfiguration;
import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyCache;
import android.app.assist.AssistContent;
import android.app.assist.AssistContent;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure;
import android.app.compat.CompatChanges;
import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal;
import android.content.ActivityNotFoundException;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ComponentName;
@@ -2900,6 +2901,86 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        }
        }
    }
    }


    /**
     * Returns true if the app can close system dialogs. Otherwise it either throws a {@link
     * SecurityException} or returns false with a logcat message depending on whether the app
     * targets SDK level {@link android.os.Build.VERSION_CODES#S} or not.
     */
    private boolean checkCanCloseSystemDialogs(int pid, int uid, @Nullable String packageName) {
        final WindowProcessController process;
        synchronized (mGlobalLock) {
            process = mProcessMap.getProcess(pid);
        }
        if (packageName == null && process != null) {
            // WindowProcessController.mInfo is final, so after the synchronized memory barrier
            // above, process.mInfo can't change. As for reading mInfo.packageName,
            // WindowProcessController doesn't own the ApplicationInfo object referenced by mInfo.
            // ProcessRecord for example also holds a reference to that object, so protecting access
            // to packageName with the WM lock would not be enough as we'd also need to synchronize
            // on the AM lock if we are worried about races, but we can't synchronize on AM lock
            // here. Hence, since this is only used for logging, we don't synchronize here.
            packageName = process.mInfo.packageName;
        }
        String caller = "(pid=" + pid + ", uid=" + uid + ")";
        if (packageName != null) {
            caller = packageName + " " + caller;
        }
        if (!canCloseSystemDialogs(pid, uid, process)) {
            // The app can't close system dialogs, throw only if it targets S+
            if (CompatChanges.isChangeEnabled(
                    ActivityManager.LOCK_DOWN_CLOSE_SYSTEM_DIALOGS, uid)) {
                throw new SecurityException(
                        "Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS
                                + " broadcast from " + caller + " requires "
                                + Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS + ".");
            } else if (CompatChanges.isChangeEnabled(
                    ActivityManager.DROP_CLOSE_SYSTEM_DIALOGS, uid)) {
                Slog.e(TAG,
                        "Permission Denial: " + Intent.ACTION_CLOSE_SYSTEM_DIALOGS
                                + " broadcast from " + caller + " requires "
                                + Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS
                                + ", dropping broadcast.");
                return false;
            } else {
                Slog.w(TAG, Intent.ACTION_CLOSE_SYSTEM_DIALOGS
                        + " broadcast from " + caller + " will require "
                        + Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS
                        + " in future builds.");
                return true;
            }
        }
        return true;
    }

    private boolean canCloseSystemDialogs(int pid, int uid,
            @Nullable WindowProcessController process) {
        if (checkPermission(Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, pid, uid)
                == PERMISSION_GRANTED) {
            return true;
        }
        if (process != null) {
            // Check if the instrumentation of the process has the permission. This covers the
            // usual test started from the shell (which has the permission) case. This is needed
            // for apps targeting SDK level < S but we are also allowing for targetSdk S+ as a
            // convenience to avoid breaking a bunch of existing tests and asking them to adopt
            // shell permissions to do this.
            // Note that these getters all read from volatile fields in WindowProcessController, so
            // no need to lock.
            int sourceUid = process.getInstrumentationSourceUid();
            if (process.isInstrumenting() && sourceUid != -1 && checkPermission(
                    Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, -1, sourceUid)
                    == PERMISSION_GRANTED) {
                return true;
            }
            // This is the notification trampoline use-case for example, where apps use Intent.ACSD
            // to close the shade prior to starting an activity.
            if (process.canCloseSystemDialogsByToken()) {
                return true;
            }
        }
        return false;
    }

    static void enforceTaskPermission(String func) {
    static void enforceTaskPermission(String func) {
        if (checkCallingPermission(MANAGE_ACTIVITY_TASKS) == PackageManager.PERMISSION_GRANTED) {
        if (checkCallingPermission(MANAGE_ACTIVITY_TASKS) == PackageManager.PERMISSION_GRANTED) {
            return;
            return;
@@ -5176,6 +5257,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            ActivityTaskManagerService.this.enforceCallerIsRecentsOrHasPermission(permission, func);
            ActivityTaskManagerService.this.enforceCallerIsRecentsOrHasPermission(permission, func);
        }
        }


        @Override
        public boolean checkCanCloseSystemDialogs(int pid, int uid, @Nullable String packageName) {
            return ActivityTaskManagerService.this.checkCanCloseSystemDialogs(pid, uid,
                    packageName);
        }

        @Override
        @Override
        public void notifyActiveVoiceInteractionServiceChanged(ComponentName component) {
        public void notifyActiveVoiceInteractionServiceChanged(ComponentName component) {
            synchronized (mGlobalLock) {
            synchronized (mGlobalLock) {
@@ -5676,9 +5763,12 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        @Override
        @Override
        public void closeSystemDialogs(String reason) {
        public void closeSystemDialogs(String reason) {
            enforceNotIsolatedCaller("closeSystemDialogs");
            enforceNotIsolatedCaller("closeSystemDialogs");

            final int pid = Binder.getCallingPid();
            final int pid = Binder.getCallingPid();
            final int uid = Binder.getCallingUid();
            final int uid = Binder.getCallingUid();
            if (!checkCanCloseSystemDialogs(pid, uid, null)) {
                return;
            }

            final long origId = Binder.clearCallingIdentity();
            final long origId = Binder.clearCallingIdentity();
            try {
            try {
                synchronized (mGlobalLock) {
                synchronized (mGlobalLock) {
+5 −0
Original line number Original line Diff line number Diff line
@@ -3243,6 +3243,11 @@ public class WindowManagerService extends IWindowManager.Stub


    @Override
    @Override
    public void closeSystemDialogs(String reason) {
    public void closeSystemDialogs(String reason) {
        int callingPid = Binder.getCallingPid();
        int callingUid = Binder.getCallingUid();
        if (!mAtmInternal.checkCanCloseSystemDialogs(callingPid, callingUid, null)) {
            return;
        }
        synchronized (mGlobalLock) {
        synchronized (mGlobalLock) {
            mRoot.closeSystemDialogs(reason);
            mRoot.closeSystemDialogs(reason);
        }
        }
Loading