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

Commit df573a62 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "If the calling process isn't whitelisted for background activity start,...

Merge "If the calling process isn't whitelisted for background activity start, check the other processes of calling UID too" into qt-dev
parents 77d354ef 2e0aad2d
Loading
Loading
Loading
Loading
+27 −36
Original line number Original line Diff line number Diff line
@@ -986,31 +986,6 @@ class ActivityStarter {
                return false;
                return false;
            }
            }
        }
        }
        // If we don't have callerApp at this point, no caller was provided to startActivity().
        // That's the case for PendingIntent-based starts, since the creator's process might not be
        // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
        // caller, so that we can make the decision based on its foreground/whitelisted state.
        if (callerApp == null) {
            callerApp = mService.getProcessController(realCallingPid, realCallingUid);
        }
        if (callerApp != null) {
            // don't abort if the callerApp is instrumenting with background activity starts privs
            if (callerApp.isInstrumentingWithBackgroundActivityStartPrivileges()) {
                return false;
            }
            // don't abort if the caller is currently temporarily whitelisted
            if (callerApp.areBackgroundActivityStartsAllowed()) {
                return false;
            }
            // don't abort if the caller has an activity in any foreground task
            if (callerApp.hasActivityInVisibleTask()) {
                return false;
            }
            // don't abort if the caller is bound by a UID that's currently foreground
            if (isBoundByForegroundUid(callerApp)) {
                return false;
            }
        }
        // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
        // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
        if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
        if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
                == PERMISSION_GRANTED) {
                == PERMISSION_GRANTED) {
@@ -1035,6 +1010,33 @@ class ActivityStarter {
                    + " temporarily whitelisted. This will not be supported in future Q builds.");
                    + " temporarily whitelisted. This will not be supported in future Q builds.");
            return false;
            return false;
        }
        }
        // If we don't have callerApp at this point, no caller was provided to startActivity().
        // That's the case for PendingIntent-based starts, since the creator's process might not be
        // up and alive. If that's the case, we retrieve the WindowProcessController for the send()
        // caller, so that we can make the decision based on its foreground/whitelisted state.
        int callerAppUid = callingUid;
        if (callerApp == null) {
            callerApp = mService.getProcessController(realCallingPid, realCallingUid);
            callerAppUid = realCallingUid;
        }
        // don't abort if the callerApp or other processes of that uid are whitelisted in any way
        if (callerApp != null) {
            // first check the original calling process
            if (callerApp.areBackgroundActivityStartsAllowed()) {
                return false;
            }
            // only if that one wasn't whitelisted, check the other ones
            final ArraySet<WindowProcessController> uidProcesses =
                    mService.mProcessMap.getProcesses(callerAppUid);
            if (uidProcesses != null) {
                for (int i = uidProcesses.size() - 1; i >= 0; i--) {
                    final WindowProcessController proc = uidProcesses.valueAt(i);
                    if (proc != callerApp && proc.areBackgroundActivityStartsAllowed()) {
                        return false;
                    }
                }
            }
        }
        // anything that has fallen through would currently be aborted
        // anything that has fallen through would currently be aborted
        Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
        Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
                + "; callingUid: " + callingUid
                + "; callingUid: " + callingUid
@@ -1059,17 +1061,6 @@ class ActivityStarter {
        return true;
        return true;
    }
    }


    private boolean isBoundByForegroundUid(WindowProcessController callerApp) {
        final ArraySet<Integer> boundClientUids = callerApp.getBoundClientUids();
        for (int i = boundClientUids.size() - 1; i >= 0; --i) {
            final int uid = boundClientUids.valueAt(i);
            if (mService.isUidForeground(uid)) {
                return true;
            }
        }
        return false;
    }

    // TODO: remove this toast after feature development is done
    // TODO: remove this toast after feature development is done
    void showBackgroundActivityBlockedToast(boolean abort, String callingPackage) {
    void showBackgroundActivityBlockedToast(boolean abort, String callingPackage) {
        final Resources res = mService.mContext.getResources();
        final Resources res = mService.mContext.getResources();
+14 −13
Original line number Original line Diff line number Diff line
@@ -373,8 +373,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
    private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
    /** All processes currently running that might have a window organized by name. */
    /** All processes currently running that might have a window organized by name. */
    final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
    final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
    /** All processes we currently have running mapped by pid */
    /** All processes we currently have running mapped by pid and uid */
    final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
    final WindowProcessControllerMap mProcessMap = new WindowProcessControllerMap();
    /** This is the process holding what we currently consider to be the "home" activity. */
    /** This is the process holding what we currently consider to be the "home" activity. */
    WindowProcessController mHomeProcess;
    WindowProcessController mHomeProcess;
    /** The currently running heavy-weight process, if any. */
    /** The currently running heavy-weight process, if any. */
@@ -913,7 +913,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            return getGlobalConfiguration();
            return getGlobalConfiguration();
        }
        }
        synchronized (mGlobalLock) {
        synchronized (mGlobalLock) {
            final WindowProcessController app = mPidMap.get(pid);
            final WindowProcessController app = mProcessMap.getProcess(pid);
            return app != null ? app.getConfiguration() : getGlobalConfiguration();
            return app != null ? app.getConfiguration() : getGlobalConfiguration();
        }
        }
    }
    }
@@ -4640,7 +4640,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        enforceSystemHasVrFeature();
        enforceSystemHasVrFeature();
        synchronized (mGlobalLock) {
        synchronized (mGlobalLock) {
            final int pid = Binder.getCallingPid();
            final int pid = Binder.getCallingPid();
            final WindowProcessController wpc = mPidMap.get(pid);
            final WindowProcessController wpc = mProcessMap.getProcess(pid);
            mVrController.setVrThreadLocked(tid, pid, wpc);
            mVrController.setVrThreadLocked(tid, pid, wpc);
        }
        }
    }
    }
@@ -4659,7 +4659,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        enforceSystemHasVrFeature();
        enforceSystemHasVrFeature();
        synchronized (mGlobalLock) {
        synchronized (mGlobalLock) {
            final int pid = Binder.getCallingPid();
            final int pid = Binder.getCallingPid();
            final WindowProcessController proc = mPidMap.get(pid);
            final WindowProcessController proc = mProcessMap.getProcess(pid);
            mVrController.setPersistentVrThreadLocked(tid, pid, proc);
            mVrController.setPersistentVrThreadLocked(tid, pid, proc);
        }
        }
    }
    }
@@ -5204,9 +5204,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            mH.sendMessage(msg);
            mH.sendMessage(msg);
        }
        }


        for (int i = mPidMap.size() - 1; i >= 0; i--) {
        SparseArray<WindowProcessController> pidMap = mProcessMap.getPidMap();
            final int pid = mPidMap.keyAt(i);
        for (int i = pidMap.size() - 1; i >= 0; i--) {
            final WindowProcessController app = mPidMap.get(pid);
            final int pid = pidMap.keyAt(i);
            final WindowProcessController app = pidMap.get(pid);
            if (DEBUG_CONFIGURATION) {
            if (DEBUG_CONFIGURATION) {
                Slog.v(TAG_CONFIGURATION, "Update process config of "
                Slog.v(TAG_CONFIGURATION, "Update process config of "
                        + app.mName + " to new config " + configCopy);
                        + app.mName + " to new config " + configCopy);
@@ -5859,7 +5860,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
    }
    }


    WindowProcessController getProcessController(int pid, int uid) {
    WindowProcessController getProcessController(int pid, int uid) {
        final WindowProcessController proc = mPidMap.get(pid);
        final WindowProcessController proc = mProcessMap.getProcess(pid);
        if (proc == null) return null;
        if (proc == null) return null;
        if (UserHandle.isApp(uid) && proc.mUid == uid) {
        if (UserHandle.isApp(uid) && proc.mUid == uid) {
            return proc;
            return proc;
@@ -6423,14 +6424,14 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        @Override
        @Override
        public void onProcessMapped(int pid, WindowProcessController proc) {
        public void onProcessMapped(int pid, WindowProcessController proc) {
            synchronized (mGlobalLock) {
            synchronized (mGlobalLock) {
                mPidMap.put(pid, proc);
                mProcessMap.put(pid, proc);
            }
            }
        }
        }


        @Override
        @Override
        public void onProcessUnMapped(int pid) {
        public void onProcessUnMapped(int pid) {
            synchronized (mGlobalLock) {
            synchronized (mGlobalLock) {
                mPidMap.remove(pid);
                mProcessMap.remove(pid);
            }
            }
        }
        }


@@ -6503,7 +6504,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                    }
                    }
                    return;
                    return;
                }
                }
                final WindowProcessController process = mPidMap.get(pid);
                final WindowProcessController process = mProcessMap.getProcess(pid);
                if (process == null) {
                if (process == null) {
                    if (DEBUG_CONFIGURATION) {
                    if (DEBUG_CONFIGURATION) {
                        Slog.w(TAG, "Trying to update display configuration for invalid "
                        Slog.w(TAG, "Trying to update display configuration for invalid "
@@ -6696,7 +6697,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
                    // Only allow this from foreground processes, so that background
                    // Only allow this from foreground processes, so that background
                    // applications can't abuse it to prevent system UI from being shown.
                    // applications can't abuse it to prevent system UI from being shown.
                    if (uid >= FIRST_APPLICATION_UID) {
                    if (uid >= FIRST_APPLICATION_UID) {
                        final WindowProcessController proc = mPidMap.get(pid);
                        final WindowProcessController proc = mProcessMap.getProcess(pid);
                        if (!proc.isPerceptible()) {
                        if (!proc.isPerceptible()) {
                            Slog.w(TAG, "Ignoring closeSystemDialogs " + reason
                            Slog.w(TAG, "Ignoring closeSystemDialogs " + reason
                                    + " from background process " + proc);
                                    + " from background process " + proc);
+4 −2
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.RemoteException;
import android.util.AtomicFile;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
import android.util.Xml;


public final class CompatModePackages {
public final class CompatModePackages {
@@ -324,8 +325,9 @@ public final class CompatModePackages {
            ActivityRecord starting = stack.restartPackage(packageName);
            ActivityRecord starting = stack.restartPackage(packageName);


            // Tell all processes that loaded this package about the change.
            // Tell all processes that loaded this package about the change.
            for (int i = mService.mPidMap.size() - 1; i >= 0; i--) {
            SparseArray<WindowProcessController> pidMap = mService.mProcessMap.getPidMap();
                final WindowProcessController app = mService.mPidMap.valueAt(i);
            for (int i = pidMap.size() - 1; i >= 0; i--) {
                final WindowProcessController app = pidMap.valueAt(i);
                if (!app.mPkgList.contains(packageName)) {
                if (!app.mPkgList.contains(packageName)) {
                    continue;
                    continue;
                }
                }
+28 −15
Original line number Original line Diff line number Diff line
@@ -372,16 +372,37 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
        mAllowBackgroundActivityStarts = allowBackgroundActivityStarts;
    }
    }


    public boolean areBackgroundActivityStartsAllowed() {
    boolean areBackgroundActivityStartsAllowed() {
        return mAllowBackgroundActivityStarts;
        // allow if the whitelisting flag was explicitly set
        if (mAllowBackgroundActivityStarts) {
            return true;
        }
        // allow if the proc is instrumenting with background activity starts privs
        if (mInstrumentingWithBackgroundActivityStartPrivileges) {
            return true;
        }
        // allow if the caller has an activity in any foreground task
        if (hasActivityInVisibleTask()) {
            return true;
        }
        // allow if the caller is bound by a UID that's currently foreground
        if (isBoundByForegroundUid()) {
            return true;
        }
        return false;
    }
    }


    public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
    private boolean isBoundByForegroundUid() {
        mBoundClientUids = boundClientUids;
        for (int i = mBoundClientUids.size() - 1; i >= 0; --i) {
            if (mAtm.isUidForeground(mBoundClientUids.valueAt(i))) {
                return true;
            }
        }
        return false;
    }
    }


    public ArraySet<Integer> getBoundClientUids() {
    public void setBoundClientUids(ArraySet<Integer> boundClientUids) {
        return mBoundClientUids;
        mBoundClientUids = boundClientUids;
    }
    }


    public void setInstrumenting(boolean instrumenting,
    public void setInstrumenting(boolean instrumenting,
@@ -394,14 +415,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        return mInstrumenting;
        return mInstrumenting;
    }
    }


    /**
     * @return true if the instrumentation was started by a holder of
     * START_ACTIVITIES_FROM_BACKGROUND permission
     */
    boolean isInstrumentingWithBackgroundActivityStartPrivileges() {
        return mInstrumentingWithBackgroundActivityStartPrivileges;
    }

    public void setPerceptible(boolean perceptible) {
    public void setPerceptible(boolean perceptible) {
        mPerceptible = perceptible;
        mPerceptible = perceptible;
    }
    }
@@ -487,7 +500,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        }
        }
    }
    }


    boolean hasActivityInVisibleTask() {
    private boolean hasActivityInVisibleTask() {
        for (int i = mActivities.size() - 1; i >= 0; --i) {
        for (int i = mActivities.size() - 1; i >= 0; --i) {
            TaskRecord task = mActivities.get(i).getTaskRecord();
            TaskRecord task = mActivities.get(i).getTaskRecord();
            if (task == null) {
            if (task == null) {
+86 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import android.util.ArraySet;
import android.util.SparseArray;

import java.util.Map;
import java.util.HashMap;

final class WindowProcessControllerMap {

    /** All processes we currently have running mapped by pid */
    private final SparseArray<WindowProcessController> mPidMap = new SparseArray<>();
    /** All processes we currently have running mapped by uid */
    private final Map<Integer, ArraySet<WindowProcessController>> mUidMap = new HashMap<>();

    /** Retrieves a currently running process for pid. */
    WindowProcessController getProcess(int pid) {
        return mPidMap.get(pid);
    }

    /** Retrieves all currently running processes for uid. */
    ArraySet<WindowProcessController> getProcesses(int uid) {
        return mUidMap.get(uid);
    }

    SparseArray<WindowProcessController> getPidMap() {
        return mPidMap;
    }

    void put(int pid, WindowProcessController proc) {
        // if there is a process for this pid already in mPidMap it'll get replaced automagically,
        // but we actually need to remove it from mUidMap too before adding the new one
        final WindowProcessController prevProc = mPidMap.get(pid);
        if (prevProc != null) {
            removeProcessFromUidMap(prevProc);
        }
        // put process into mPidMap
        mPidMap.put(pid, proc);
        // put process into mUidMap
        final int uid = proc.mUid;
        ArraySet<WindowProcessController> procSet = mUidMap.getOrDefault(uid,
                new ArraySet<WindowProcessController>());
        procSet.add(proc);
        mUidMap.put(uid, procSet);
    }

    void remove(int pid) {
        final WindowProcessController proc = mPidMap.get(pid);
        if (proc != null) {
            // remove process from mPidMap
            mPidMap.remove(pid);
            // remove process from mUidMap
            removeProcessFromUidMap(proc);
        }
    }

    private void removeProcessFromUidMap(WindowProcessController proc) {
        if (proc == null) {
            return;
        }
        final int uid = proc.mUid;
        ArraySet<WindowProcessController> procSet = mUidMap.get(uid);
        if (procSet != null) {
            procSet.remove(proc);
            if (procSet.isEmpty()) {
                mUidMap.remove(uid);
            }
        }
    }
}
Loading