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

Commit ed401cc1 authored by Galia Peycheva's avatar Galia Peycheva
Browse files

Introduce security checks to startDreamActivity

This CL checks that the caller is the dream package and that the
device is dreaming when the activity is started.

isDream was instroduced in order to exempt the DreamActivity from
background start check. setAllowBackgroundActivityStart does that
more cleanly.

Bug: 152281628

Test: m && flashall && verify dream works

Change-Id: Id6161f923f3350d482b3452a78a792a541dcf1a1
parent 480275a1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1049,6 +1049,7 @@ public class DreamService extends Service implements Window.Callback {
        // DreamServiceWrapper.onActivityCreated.
        if (!mWindowless) {
            Intent i = new Intent(this, DreamActivity.class);
            i.setPackage(getApplicationContext().getPackageName());
            i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            i.putExtra(DreamActivity.EXTRA_CALLBACK, mDreamServiceWrapper);

+2 −14
Original line number Diff line number Diff line
@@ -341,7 +341,6 @@ class ActivityStarter {
        int filterCallingUid;
        PendingIntentRecord originatingPendingIntent;
        boolean allowBackgroundActivityStart;
        boolean isDream;

        /**
         * If set to {@code true}, allows this activity start to look into
@@ -393,7 +392,6 @@ class ActivityStarter {
            filterCallingUid = UserHandle.USER_NULL;
            originatingPendingIntent = null;
            allowBackgroundActivityStart = false;
            isDream = false;
        }

        /**
@@ -434,7 +432,6 @@ class ActivityStarter {
            filterCallingUid = request.filterCallingUid;
            originatingPendingIntent = request.originatingPendingIntent;
            allowBackgroundActivityStart = request.allowBackgroundActivityStart;
            isDream = request.isDream;
        }

        /**
@@ -985,7 +982,7 @@ class ActivityStarter {
                restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
                        callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
                        request.originatingPendingIntent, request.allowBackgroundActivityStart,
                        request.isDream, intent);
                        intent);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
            }
@@ -1195,7 +1192,7 @@ class ActivityStarter {
    boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
            final String callingPackage, int realCallingUid, int realCallingPid,
            WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
            boolean allowBackgroundActivityStart, boolean isDream, Intent intent) {
            boolean allowBackgroundActivityStart, Intent intent) {
        // don't abort for the most important UIDs
        final int callingAppId = UserHandle.getAppId(callingUid);
        if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
@@ -1203,10 +1200,6 @@ class ActivityStarter {
            return false;
        }

        // don't abort if this is the dream activity
        if (isDream) {
            return false;
        }
        // don't abort if the callingUid has a visible window or is a persistent system process
        final int callingUidProcState = mService.getUidState(callingUid);
        final boolean callingUidHasAnyVisibleWindow =
@@ -2717,11 +2710,6 @@ class ActivityStarter {
        return this;
    }

    ActivityStarter setIsDream(boolean isDream) {
        mRequest.isDream = isDream;
        return this;
    }

    void dump(PrintWriter pw, String prefix) {
        prefix = prefix + "  ";
        pw.print(prefix);
+43 −32
Original line number Diff line number Diff line
@@ -212,7 +212,6 @@ import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.service.dreams.DreamActivity;
import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
import android.sysprop.DisplayProperties;
@@ -1245,36 +1244,29 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        }
    }

    @Override
    public boolean startDreamActivity(Intent intent) {
        final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
    private void enforceCallerIsDream(String callerPackageName) {
        final long origId = Binder.clearCallingIdentity();

        // The dream activity is only called for non-doze dreams.
        final ComponentName currentDream = LocalServices.getService(DreamManagerInternal.class)
                .getActiveDreamComponent(/* doze= */ false);

        if (currentDream == null || currentDream.getPackageName() == null
                || !currentDream.getPackageName().equals(process.mInfo.packageName)) {
            Slog.e(TAG, "Calling package is not the current dream package. "
                    + "Aborting startDreamActivity...");
            return false;
        try {
            if (!ActivityRecord.canLaunchDreamActivity(callerPackageName)) {
                throw new SecurityException("The dream activity can be started only when the device"
                        + " is dreaming and only by the active dream package.");
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
    }

    @Override
    public boolean startDreamActivity(@NonNull Intent intent) {
        assertPackageMatchesCallingUid(intent.getPackage());
        enforceCallerIsDream(intent.getPackage());

        final ActivityInfo a = new ActivityInfo();
        a.theme = com.android.internal.R.style.Theme_Dream;
        a.exported = true;
        a.name = DreamActivity.class.getName();


        a.packageName = process.mInfo.packageName;
        a.applicationInfo = process.mInfo;
        a.processName = process.mInfo.processName;
        a.uiOptions = process.mInfo.uiOptions;
        a.taskAffinity = "android:" + a.packageName + "/dream";
        a.enabled = true;
        a.launchMode = ActivityInfo.LAUNCH_SINGLE_INSTANCE;

        a.persistableMode = ActivityInfo.PERSIST_NEVER;
        a.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
        a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
@@ -1283,17 +1275,36 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        final ActivityOptions options = ActivityOptions.makeBasic();
        options.setLaunchActivityType(ACTIVITY_TYPE_DREAM);

        synchronized (mGlobalLock) {
            final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());

            a.packageName = process.mInfo.packageName;
            a.applicationInfo = process.mInfo;
            a.processName = process.mInfo.processName;
            a.uiOptions = process.mInfo.uiOptions;
            a.taskAffinity = "android:" + a.packageName + "/dream";

            final int callingUid = Binder.getCallingUid();
            final int callingPid = Binder.getCallingPid();

            final long origId = Binder.clearCallingIdentity();
            try {
                getActivityStartController().obtainStarter(intent, "dream")
                        .setCallingUid(callingUid)
                        .setCallingPid(callingPid)
                        .setActivityInfo(a)
                        .setActivityOptions(options.toBundle())
                    .setIsDream(true)
                        // To start the dream from background, we need to start it from a persistent
                        // system process. Here we set the real calling uid to the system server uid
                        .setRealCallingUid(Binder.getCallingUid())
                        .setAllowBackgroundActivityStart(true)
                        .execute();
                return true;
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

    @Override
    public final WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
@@ -2478,7 +2489,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        final ActivityStarter starter = getActivityStartController().obtainStarter(
                null /* intent */, "moveTaskToFront");
        if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, -1,
                -1, callerApp, null, false, false, null)) {
                -1, callerApp, null, false, null)) {
            if (!isBackgroundActivityStartsEnabled()) {
                return;
            }
+1 −1
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ class AppTaskImpl extends IAppTask.Stub {
                final ActivityStarter starter = mService.getActivityStartController().obtainStarter(
                        null /* intent */, "moveToFront");
                if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid,
                        callingPackage, -1, -1, callerApp, null, false, false, null)) {
                        callingPackage, -1, -1, callerApp, null, false, null)) {
                    if (!mService.isBackgroundActivityStartsEnabled()) {
                        return;
                    }