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

Commit ff21533e authored by Sumedh Sen's avatar Sumedh Sen
Browse files

Look for the installer in all users if DELETE_ALL_USERS is requested

If a caller  passes the DELETE_ALL_USERS flag, search for the installer
app in every user, since the uninstall request may initiate from a user
where the package is not installed.

For example, if an app is installed only on user10, and a caller on
user0 is initiating the uninstall (to uninstall from all users),
looking for for the installer package* only on the initiating user
(i.e user 0) will lead to an exception. Thus, loop through all users to
find the installer

(*) We search for the installer to determine if the caller pkg is also
the installer pkg, to allow silent uninstall

Bug: 384544054
Test: TBD
Flag: EXEMPT. Bug fix only
Change-Id: Ibc893fbf32bcef0601cf57cb798f582635ab00c7
parent d6b3bdf8
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -729,10 +729,13 @@ final class DeletePackageHelper {
        final String internalPackageName =
                snapshot.resolveInternalPackageName(packageName, versionCode);

        final boolean deleteAllUsers = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0;
        final int[] users = deleteAllUsers ? mUserManagerInternal.getUserIds() : new int[]{userId};

        if (!isOrphaned(snapshot, internalPackageName)
                && !allowSilentUninstall
                && !isCallerAllowedToSilentlyUninstall(
                        snapshot, callingUid, internalPackageName, userId)) {
                && !isCallerAllowedToSilentlyUninstall(snapshot, callingUid, internalPackageName,
                users)) {
            mPm.mHandler.post(() -> {
                try {
                    final Intent intent = new Intent(Intent.ACTION_UNINSTALL_PACKAGE);
@@ -751,8 +754,7 @@ final class DeletePackageHelper {
            });
            return;
        }
        final boolean deleteAllUsers = (deleteFlags & PackageManager.DELETE_ALL_USERS) != 0;
        final int[] users = deleteAllUsers ? mUserManagerInternal.getUserIds() : new int[]{userId};

        if (UserHandle.getUserId(callingUid) != userId || (deleteAllUsers && users.length > 1)) {
            mPm.mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
@@ -916,17 +918,25 @@ final class DeletePackageHelper {
    }

    private boolean isCallerAllowedToSilentlyUninstall(@NonNull Computer snapshot, int callingUid,
            String pkgName, int userId) {
            String pkgName, int[] targetUserIds) {
        if (PackageManagerServiceUtils.isRootOrShell(callingUid)
                || UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
            return true;
        }
        final int callingUserId = UserHandle.getUserId(callingUid);

        // If the caller installed the pkgName, then allow it to silently uninstall.
        for (int user : targetUserIds) {
            try {
                if (callingUid == snapshot.getPackageUid(
                snapshot.getInstallerPackageName(pkgName, userId), 0, callingUserId)) {
                        snapshot.getInstallerPackageName(pkgName, user), 0, callingUserId)) {
                    return true;
                }
            } catch (Exception ignored) {
                // The app to be uninstalled (`pkgName`) is not installed on this `user`. Continue
                // looking for the installerPkgName in the next user
            }
        }

        // Allow package verifier to silently uninstall.
        for (String verifierPackageName : mPm.mRequiredVerifierPackages) {