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

Commit 29283375 authored by Sudheer Shanka's avatar Sudheer Shanka
Browse files

Prevent apps from uninstalling packages that are not installed by them.

Bug: 27404193
Change-Id: Ib8868d6522fc3e41526c6909fc6ea531f344e676
parent b8572b3d
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -862,8 +862,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub {
                IntentSender statusReceiver, int userId) {
        final int callingUid = Binder.getCallingUid();
        mPm.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall");
        boolean allowSilentUninstall = true;
        if ((callingUid != Process.SHELL_UID) && (callingUid != Process.ROOT_UID)) {
            mAppOps.checkPackage(callingUid, callerPackageName);
            final String installerPackageName = mPm.getInstallerPackageName(packageName);
            allowSilentUninstall = installerPackageName != null
                    && installerPackageName.equals(callerPackageName);
        }

        // Check whether the caller is device owner, in which case we do it silently.
@@ -874,8 +878,8 @@ public class PackageInstallerService extends IPackageInstaller.Stub {

        final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext,
                statusReceiver, packageName, isDeviceOwner, userId);
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES)
                == PackageManager.PERMISSION_GRANTED) {
        if (allowSilentUninstall && mContext.checkCallingOrSelfPermission(
                android.Manifest.permission.DELETE_PACKAGES) == PackageManager.PERMISSION_GRANTED) {
            // Sweet, call straight through!
            mPm.deletePackage(packageName, adapter.getBinder(), userId, flags);
        } else if (isDeviceOwner) {
+4 −1
Original line number Diff line number Diff line
@@ -11361,6 +11361,9 @@ public class PackageManagerService extends IPackageManager.Stub {
            // Okay!
            targetPackageSetting.installerPackageName = installerPackageName;
            if (installerPackageName != null) {
                mSettings.mInstallerPackages.add(installerPackageName);
            }
            scheduleWriteSettingsLocked();
        }
    }
@@ -14477,7 +14480,7 @@ public class PackageManagerService extends IPackageManager.Stub {
     *  This method is an internal method that could be get invoked either
     *  to delete an installed package or to clean up a failed installation.
     *  After deleting an installed package, a broadcast is sent to notify any
     *  listeners that the package has been installed. For cleaning up a failed
     *  listeners that the package has been removed. For cleaning up a failed
     *  installation, the broadcast is not necessary since the package's
     *  installation wouldn't have sent the initial broadcast either
     *  The key steps in deleting a package are
+32 −0
Original line number Diff line number Diff line
@@ -247,6 +247,9 @@ final class Settings {
    /** Map from package name to settings */
    final ArrayMap<String, PackageSetting> mPackages = new ArrayMap<>();

    /** List of packages that installed other packages */
    final ArraySet<String> mInstallerPackages = new ArraySet<>();

    /** Map from package name to appId */
    private final ArrayMap<String, Integer> mKernelMapping = new ArrayMap<>();

@@ -506,6 +509,9 @@ final class Settings {
        PackageSetting p = mPackages.get(pkgName);
        if (p != null) {
            p.setInstallerPackageName(installerPkgName);
            if (installerPkgName != null) {
                mInstallerPackages.add(installerPkgName);
            }
        }
    }

@@ -1062,6 +1068,7 @@ final class Settings {
        final PackageSetting p = mPackages.get(name);
        if (p != null) {
            mPackages.remove(name);
            removeInstallerPackageStatus(name);
            if (p.sharedUser != null) {
                p.sharedUser.removePackage(p);
                if (p.sharedUser.packages.size() == 0) {
@@ -1077,6 +1084,26 @@ final class Settings {
        return -1;
    }

    /**
     * Checks if {@param packageName} is an installer package and if so, clear the installer
     * package name of the packages that are installed by this.
     */
    private void removeInstallerPackageStatus(String packageName) {
        // Check if the package to be removed is an installer package.
        if (!mInstallerPackages.contains(packageName)) {
            return;
        }
        for (int i = 0; i < mPackages.size(); i++) {
            final PackageSetting ps = mPackages.valueAt(i);
            final String installerPackageName = ps.getInstallerPackageName();
            if (installerPackageName != null
                    && installerPackageName.equals(packageName)) {
                ps.setInstallerPackageName(null);
            }
        }
        mInstallerPackages.remove(packageName);
    }

    private void replacePackageLPw(String name, PackageSetting newp) {
        final PackageSetting p = mPackages.get(name);
        if (p != null) {
@@ -2742,6 +2769,7 @@ final class Settings {
        mPendingPackages.clear();
        mPastSignatures.clear();
        mKeySetRefs.clear();
        mInstallerPackages.clear();

        try {
            if (str == null) {
@@ -3706,6 +3734,10 @@ final class Settings {
                packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0, null);
            }

            if (installerPackageName != null) {
                mInstallerPackages.add(installerPackageName);
            }

            final String installStatusStr = parser.getAttributeValue(null, "installStatus");
            if (installStatusStr != null) {
                if (installStatusStr.equalsIgnoreCase("false")) {