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

Commit d4c436d9 authored by Jeff Chang's avatar Jeff Chang
Browse files

Only allow system to apply relinquishTaskIdentity

Any malicious application could hijack tasks by
android:relinquishTaskIdentity. This vulnerability can perform UI
spoofing or spy on user’s activities.

This CL limit the usage which only allow system to apply
relinquishTaskIdentity

Bug: 185810717
Test: atest IntentTests
      atest ActivityStarterTests
      atest com.android.server.wm.TaskTests
Change-Id: Iddbb9c04237fdc8bdc0c2223ee597f43f37cb178
parent 08774f2f
Loading
Loading
Loading
Loading
+12 −2
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
@@ -570,7 +571,9 @@ class Task extends TaskFragment {
            mRoot = r;

            // Only end search if we are ignore relinquishing identity or we are not relinquishing.
            return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
            return ignoreRelinquishIdentity
                    || mNeverRelinquishIdentity
                    || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
        }
    }

@@ -1009,7 +1012,14 @@ class Task extends TaskFragment {
    private void setIntent(Intent _intent, ActivityInfo info) {
        if (!isLeafTask()) return;

        if (info.applicationInfo.uid == Process.SYSTEM_UID
                || info.applicationInfo.isSystemApp()) {
            // Only allow the apps that pre-installed on the system image to apply
            // relinquishTaskIdentity
            mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
        } else {
            mNeverRelinquishIdentity = true;
        }
        affinity = info.taskAffinity;
        if (intent == null) {
            // If this task already has an intent associated with it, don't set the root
+11 −10
Original line number Diff line number Diff line
@@ -898,7 +898,8 @@ public class TaskTests extends WindowTestsBase {

    /**
     * Test that root activity index is reported correctly when looking for the 'effective root' in
     * case when bottom activities are relinquishing task identity or finishing.
     * case when bottom activity is finishing. Ignore the relinquishing task identity if it's not a
     * system activity even with the FLAG_RELINQUISH_TASK_IDENTITY.
     */
    @Test
    public void testFindRootIndex_effectiveRoot_finishingAndRelinquishing() {
@@ -912,7 +913,7 @@ public class TaskTests extends WindowTestsBase {
        new ActivityBuilder(mAtm).setTask(task).build();

        assertEquals("The first non-finishing activity and non-relinquishing task identity "
                + "must be reported.", task.getChildAt(2), task.getRootActivity(
                + "must be reported.", task.getChildAt(0), task.getRootActivity(
                false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
    }

@@ -932,8 +933,8 @@ public class TaskTests extends WindowTestsBase {
    }

    /**
     * Test that the topmost activity index is reported correctly when looking for the
     * 'effective root' for the case when all activities have relinquishTaskIdentity set.
     * Test that the root activity index is reported correctly when looking for the
     * 'effective root' for the case when all non-system activities have relinquishTaskIdentity set.
     */
    @Test
    public void testFindRootIndex_effectiveRoot_relinquishingMultipleActivities() {
@@ -944,9 +945,9 @@ public class TaskTests extends WindowTestsBase {
        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
        activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;

        assertEquals("The topmost activity in the task must be reported.",
                task.getChildAt(task.getChildCount() - 1), task.getRootActivity(
                        false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
        assertEquals("The topmost activity in the task must be reported.", task.getChildAt(0),
                task.getRootActivity(false /*ignoreRelinquishIdentity*/,
                        true /*setToBottomIfNone*/));
    }

    /** Test that bottom-most activity is reported in {@link Task#getRootActivity()}. */
@@ -1084,8 +1085,8 @@ public class TaskTests extends WindowTestsBase {
    }

    /**
     * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with activity that
     * relinquishes task identity.
     * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with non-system
     * activity that relinquishes task identity.
     */
    @Test
    public void testGetTaskForActivity_onlyRoot_relinquishTaskIdentity() {
@@ -1100,7 +1101,7 @@ public class TaskTests extends WindowTestsBase {

        assertEquals(task.mTaskId,
                ActivityRecord.getTaskForActivityLocked(activity0.appToken, true /* onlyRoot */));
        assertEquals(task.mTaskId,
        assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
                ActivityRecord.getTaskForActivityLocked(activity1.appToken, true /* onlyRoot */));
        assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
                ActivityRecord.getTaskForActivityLocked(activity2.appToken, true /* onlyRoot */));