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

Commit 4d8d32cb authored by Jorim Jaggi's avatar Jorim Jaggi
Browse files

Fix issue with permission check for shortcuts and pendingIntent

When launching a PendingIntent, we have two sets of activity
options: One supplied from the caller that obtained the
pending intent, and those supplied from the caller that is
sending it. We need to perform the permission check depending
on which caller the options are coming from.

For that, we introduce SafeActivityOptions that records the
callingPid/callingUid when obtaining it and checks for the
permissions with the correct callingPid/callingUid, and
also supports merging both activity options.

In addition to that, fix shortcuts by not clearing caller
identity in LauncherAppsService.

Test: go/wm-smoke
Test: Install custom launcher APK with animation for shortcuts
enabled, make sure launch works properly.
Bug: 64674361

Change-Id: I9a854d43c65c8fa69bf16ccfbed86e8e681a095b
parent 8f0d71e3
Loading
Loading
Loading
Loading
+49 −27
Original line number Diff line number Diff line
@@ -4707,7 +4707,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setMayWait(bOptions, userId)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
    }
@@ -4778,7 +4779,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                    .setResultWho(resultWho)
                    .setRequestCode(requestCode)
                    .setStartFlags(startFlags)
                    .setMayWait(bOptions, userId)
                    .setActivityOptions(bOptions)
                    .setMayWait(userId)
                    .setIgnoreTargetSecurity(ignoreTargetSecurity)
                    .execute();
        } catch (SecurityException e) {
@@ -4814,7 +4816,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setMayWait(bOptions, userId)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .setProfilerInfo(profilerInfo)
                .setWaitResult(res)
                .execute();
@@ -4838,7 +4841,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setGlobalConfiguration(config)
                .setMayWait(bOptions, userId)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
    }
@@ -4893,7 +4897,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                .setVoiceInteractor(interactor)
                .setStartFlags(startFlags)
                .setProfilerInfo(profilerInfo)
                .setMayWait(bOptions, userId)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
    }
@@ -4908,7 +4913,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                .setCallingUid(callingUid)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setMayWait(bOptions, userId)
                .setActivityOptions(bOptions)
                .setMayWait(userId)
                .execute();
    }
@@ -4923,6 +4929,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            throw new SecurityException(msg);
        }
        final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options);
        final int recentsUid = mRecentTasks.getRecentsComponentUid();
        final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
        final String recentsPackage = recentsComponent.getPackageName();
@@ -4953,7 +4960,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                return mActivityStartController.obtainStarter(intent, "startRecentsActivity")
                        .setCallingUid(recentsUid)
                        .setCallingPackage(recentsPackage)
                        .setMayWait(activityOptions, userId)
                        .setActivityOptions(safeOptions)
                        .setMayWait(userId)
                        .execute();
            }
        } finally {
@@ -5041,17 +5049,17 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (intent != null && intent.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }
        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
        SafeActivityOptions options = SafeActivityOptions.fromBundle(bOptions);
        synchronized (this) {
            final ActivityRecord r = ActivityRecord.isInStackLocked(callingActivity);
            if (r == null) {
                ActivityOptions.abort(options);
                SafeActivityOptions.abort(options);
                return false;
            }
            if (r.app == null || r.app.thread == null) {
                // The caller is not running...  d'oh!
                ActivityOptions.abort(options);
                SafeActivityOptions.abort(options);
                return false;
            }
            intent = new Intent(intent);
@@ -5096,7 +5104,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            if (aInfo == null) {
                // Nobody who is next!
                ActivityOptions.abort(options);
                SafeActivityOptions.abort(options);
                if (debug) Slog.d(TAG, "Next matching activity: nothing found");
                return false;
            }
@@ -5158,10 +5166,13 @@ public class ActivityManagerService extends IActivityManager.Stub
        enforceCallerIsRecentsOrHasPermission(START_TASKS_FROM_RECENTS,
                "startActivityFromRecents()");
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        try {
            synchronized (this) {
                return mStackSupervisor.startActivityFromRecents(taskId, bOptions);
                return mStackSupervisor.startActivityFromRecents(callingPid, callingUid, taskId,
                        SafeActivityOptions.fromBundle(bOptions));
            }
        } finally {
            Binder.restoreCallingIdentity(origId);
@@ -5178,7 +5189,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                userId, false, ALLOW_FULL_ONLY, reason, null);
        // TODO: Switch to user app stacks here.
        int ret = mActivityStartController.startActivities(caller, -1, callingPackage,
                intents, resolvedTypes, resultTo, bOptions, userId, reason);
                intents, resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId,
                reason);
        return ret;
    }
@@ -7937,9 +7949,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
                |PendingIntent.FLAG_UPDATE_CURRENT);
        PendingIntentRecord.Key key = new PendingIntentRecord.Key(
                type, packageName, activity, resultWho,
                requestCode, intents, resolvedTypes, flags, bOptions, userId);
        PendingIntentRecord.Key key = new PendingIntentRecord.Key(type, packageName, activity,
                resultWho, requestCode, intents, resolvedTypes, flags,
                SafeActivityOptions.fromBundle(bOptions), userId);
        WeakReference<PendingIntentRecord> ref;
        ref = mIntentSenderRecords.get(key);
        PendingIntentRecord rec = ref != null ? ref.get() : null;
@@ -10422,9 +10434,13 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public void startInPlaceAnimationOnFrontMostApplication(Bundle opts)
            throws RemoteException {
        final ActivityOptions activityOptions = ActivityOptions.fromBundle(opts);
        if (activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE ||
                activityOptions.getCustomInPlaceResId() == 0) {
        final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(opts);
        final ActivityOptions activityOptions = safeOptions != null
                ? safeOptions.getOptions(mStackSupervisor)
                : null;
        if (activityOptions == null
                || activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE
                || activityOptions.getCustomInPlaceResId() == 0) {
            throw new IllegalArgumentException("Expected in-place ActivityOption " +
                    "with valid animation");
        }
@@ -10527,16 +10543,17 @@ public class ActivityManagerService extends IActivityManager.Stub
        if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
        synchronized(this) {
            moveTaskToFrontLocked(taskId, flags, bOptions, false /* fromRecents */);
            moveTaskToFrontLocked(taskId, flags, SafeActivityOptions.fromBundle(bOptions),
                    false /* fromRecents */);
        }
    }
    void moveTaskToFrontLocked(int taskId, int flags, Bundle bOptions, boolean fromRecents) {
        ActivityOptions options = ActivityOptions.fromBundle(bOptions);
    void moveTaskToFrontLocked(int taskId, int flags, SafeActivityOptions options,
            boolean fromRecents) {
        if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
                Binder.getCallingUid(), -1, -1, "Task to front")) {
            ActivityOptions.abort(options);
            SafeActivityOptions.abort(options);
            return;
        }
        final long origId = Binder.clearCallingIdentity();
@@ -10550,7 +10567,10 @@ public class ActivityManagerService extends IActivityManager.Stub
                Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
                return;
            }
            mStackSupervisor.findTaskToMoveToFront(task, flags, options, "moveTaskToFront",
            ActivityOptions realOptions = options != null
                    ? options.getOptions(mStackSupervisor)
                    : null;
            mStackSupervisor.findTaskToMoveToFront(task, flags, realOptions, "moveTaskToFront",
                    false /* forceNonResizable */);
            final ActivityRecord topActivity = task.getTopActivity();
@@ -10564,7 +10584,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        } finally {
            Binder.restoreCallingIdentity(origId);
        }
        ActivityOptions.abort(options);
        SafeActivityOptions.abort(options);
    }
    /**
@@ -13522,6 +13542,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public boolean convertToTranslucent(IBinder token, Bundle options) {
        SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options);
        final long origId = Binder.clearCallingIdentity();
        try {
            synchronized (this) {
@@ -13533,7 +13554,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                int index = task.mActivities.lastIndexOf(r);
                if (index > 0) {
                    ActivityRecord under = task.mActivities.get(index - 1);
                    under.returningOptions = ActivityOptions.fromBundle(options);
                    under.returningOptions = safeOptions.getOptions(r);
                }
                final boolean translucentChanged = r.changeWindowTranslucency(false);
                if (translucentChanged) {
@@ -24886,7 +24907,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            synchronized (ActivityManagerService.this) {
                return mActivityStartController.startActivitiesInPackage(packageUid, packageName,
                        intents, resolvedTypes, /*resultTo*/ null, bOptions, userId);
                        intents, resolvedTypes, null /* resultTo */,
                        SafeActivityOptions.fromBundle(bOptions), userId);
            }
        }
+12 −62
Original line number Diff line number Diff line
@@ -1591,7 +1591,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
    boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo,
            String resultWho, int requestCode, int callingPid, int callingUid,
            String callingPackage, boolean ignoreTargetSecurity, ProcessRecord callerApp,
            ActivityRecord resultRecord, ActivityStack resultStack, ActivityOptions options) {
            ActivityRecord resultRecord, ActivityStack resultStack) {
        final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid,
                callingUid);
        if (startAnyPerm == PERMISSION_GRANTED) {
@@ -1645,57 +1645,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
            Slog.w(TAG, message);
            return false;
        }
        if (options != null) {
            // If a launch task id is specified, then ensure that the caller is the recents
            // component or has the START_TASKS_FROM_RECENTS permission
            if (options.getLaunchTaskId() != INVALID_TASK_ID
                    && !mRecentTasks.isCallerRecents(callingUid)) {
                final int startInTaskPerm = mService.checkPermission(START_TASKS_FROM_RECENTS,
                        callingPid, callingUid);
                if (startInTaskPerm == PERMISSION_DENIED) {
                    final String msg = "Permission Denial: starting " + intent.toString()
                            + " from " + callerApp + " (pid=" + callingPid
                            + ", uid=" + callingUid + ") with launchTaskId="
                            + options.getLaunchTaskId();
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                }
            }
            // Check if someone tries to launch an activity on a private display with a different
            // owner.
            final int launchDisplayId = options.getLaunchDisplayId();
            if (launchDisplayId != INVALID_DISPLAY && !isCallerAllowedToLaunchOnDisplay(callingPid,
                    callingUid, launchDisplayId, aInfo)) {
                final String msg = "Permission Denial: starting " + intent.toString()
                        + " from " + callerApp + " (pid=" + callingPid
                        + ", uid=" + callingUid + ") with launchDisplayId="
                        + launchDisplayId;
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            }
            // Check if someone tries to launch an unwhitelisted activity into LockTask mode.
            final boolean lockTaskMode = options.getLockTaskMode();
            if (lockTaskMode && !mService.mLockTaskController.isPackageWhitelisted(
                    UserHandle.getUserId(callingUid), aInfo.packageName)) {
                final String msg = "Permission Denial: starting " + intent.toString()
                        + " from " + callerApp + " (pid=" + callingPid
                        + ", uid=" + callingUid + ") with lockTaskMode=true";
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            }

            // Check permission for remote animations
            final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter();
            if (adapter != null && mService.checkPermission(
                    CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid)
                            != PERMISSION_GRANTED) {
                final String msg = "Permission Denial: starting " + intent.toString()
                        + " from " + callerApp + " (pid=" + callingPid
                        + ", uid=" + callingUid + ") with remoteAnimationAdapter";
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            }
        }

        return true;
    }
@@ -2166,8 +2115,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        }
    }

    void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options,
            String reason, boolean forceNonResizeable) {
    void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options, String reason,
            boolean forceNonResizeable) {
        final ActivityStack currentStack = task.getStack();
        if (currentStack == null) {
            Slog.e(TAG, "findTaskToMoveToFront: can't move task="
@@ -4538,16 +4487,17 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
        task.setTaskDockedResizing(true);
    }

    int startActivityFromRecents(int taskId, Bundle bOptions) {
    int startActivityFromRecents(int callingPid, int callingUid, int taskId,
            SafeActivityOptions options) {
        final TaskRecord task;
        final int callingUid;
        final String callingPackage;
        final Intent intent;
        final int userId;
        int activityType = ACTIVITY_TYPE_UNDEFINED;
        int windowingMode = WINDOWING_MODE_UNDEFINED;
        final ActivityOptions activityOptions = (bOptions != null)
                ? new ActivityOptions(bOptions) : null;
        final ActivityOptions activityOptions = options != null
                ? options.getOptions(this)
                : null;
        if (activityOptions != null) {
            activityType = activityOptions.getLaunchActivityType();
            windowingMode = activityOptions.getLaunchWindowingMode();
@@ -4595,7 +4545,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, targetActivity);
                mActivityMetricsLogger.notifyActivityLaunching();
                try {
                    mService.moveTaskToFrontLocked(task.taskId, 0, bOptions,
                    mService.moveTaskToFrontLocked(task.taskId, 0, options,
                            true /* fromRecents */);
                } finally {
                    mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
@@ -4614,13 +4564,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
                        task.getStack());
                return ActivityManager.START_TASK_TO_FRONT;
            }
            callingUid = task.mCallingUid;
            callingPackage = task.mCallingPackage;
            intent = task.intent;
            intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
            userId = task.userId;
            int result = mService.getActivityStartController().startActivityInPackage(callingUid,
                    callingPackage, intent, null, null, null, 0, 0, bOptions, userId, task,
            int result = mService.getActivityStartController().startActivityInPackage(
                    task.mCallingUid, callingPid, callingUid, callingPackage, intent, null, null,
                    null, 0, 0, options, userId, task,
                    "startActivityFromRecents");
            if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                setResizingDuringAnimation(task);
+19 −18
Original line number Diff line number Diff line
@@ -220,43 +220,44 @@ public class ActivityStartController {
        }
    }

    final int startActivityInPackage(int uid, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, Bundle bOptions, int userId,
            TaskRecord inTask, String reason) {
    final int startActivityInPackage(int uid, int realCallingUid, int realCallingPid,
            String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
            String resultWho, int requestCode, int startFlags, SafeActivityOptions options,
            int userId, TaskRecord inTask, String reason) {

        userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
                Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivityInPackage",
                null);
        userId = mService.mUserController.handleIncomingUser(realCallingPid, realCallingUid, userId,
                false, ALLOW_FULL_ONLY, "startActivityInPackage", null);

        // TODO: Switch to user app stacks here.
        return obtainStarter(intent, reason)
                .setCallingUid(uid)
                .setRealCallingPid(realCallingPid)
                .setRealCallingUid(realCallingUid)
                .setCallingPackage(callingPackage)
                .setResolvedType(resolvedType)
                .setResultTo(resultTo)
                .setResultWho(resultWho)
                .setRequestCode(requestCode)
                .setStartFlags(startFlags)
                .setMayWait(bOptions, userId)
                .setActivityOptions(options)
                .setMayWait(userId)
                .setInTask(inTask)
                .execute();
    }

    final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
            String[] resolvedTypes, IBinder resultTo, Bundle bOptions, int userId) {
            String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId) {
        final String reason = "startActivityInPackage";
        userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
                Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
        // TODO: Switch to user app stacks here.
        int ret = startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo,
                bOptions, userId, reason);
        return ret;
        return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options,
                userId, reason);
    }

    int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
            Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions, int userId,
            String reason) {
            Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options,
            int userId, String reason) {
        if (intents == null) {
            throw new NullPointerException("intents is null");
        }
@@ -312,9 +313,9 @@ public class ActivityStartController {
                                "FLAG_CANT_SAVE_STATE not supported here");
                    }

                    ActivityOptions options = ActivityOptions.fromBundle(
                            i == intents.length - 1 ? bOptions : null);

                    final SafeActivityOptions checkedOptions = i == intents.length - 1
                            ? options
                            : null;
                    final int res = obtainStarter(intent, reason)
                            .setCaller(caller)
                            .setResolvedType(resolvedTypes[i])
@@ -326,7 +327,7 @@ public class ActivityStartController {
                            .setCallingPackage(callingPackage)
                            .setRealCallingPid(realCallingPid)
                            .setRealCallingUid(realCallingUid)
                            .setActivityOptions(options)
                            .setActivityOptions(checkedOptions)
                            .setComponentSpecified(componentSpecified)
                            .setOutActivity(outActivity)
                            .execute();
+40 −38

File changed.

Preview size limit exceeded, changes collapsed.

+5 −3
Original line number Diff line number Diff line
@@ -408,9 +408,11 @@ class AppErrors {
                        final Set<String> cats = task.intent.getCategories();
                        if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
                            mService.getActivityStartController().startActivityInPackage(
                                    task.mCallingUid, task.mCallingPackage, task.intent, null, null,
                                    null, 0, 0, ActivityOptions.makeBasic().toBundle(), task.userId,
                                    null, "AppErrors");
                                    task.mCallingUid, callingPid, callingUid, task.mCallingPackage,
                                    task.intent, null, null, null, 0, 0,
                                    new SafeActivityOptions(ActivityOptions.makeBasic()),
                                    task.userId, null,
                                    "AppErrors");
                        }
                    }
                }
Loading