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

Commit ee536b9d authored by Nick Kovacs's avatar Nick Kovacs
Browse files

Enforce min installable target sdk version

This change will block the installation (but not the execution)
of apps that do not meet the minimum target sdk version.

The intention is to improve security and privacy by blocking low
target sdk apps as malware can target older sdk versions to avoid
the enforcement of new API behavior.

This change is fenced off by a feature flag. The plan is to
progressively ramp up the min_installable_target_sdk version
up to version 23 for Android U.

Bug: 237321649
Test: adb shell device_config put package_manager_service MinInstallableTargetSdk__install_block_enabled true
Test: adb shell device_config put package_manager_service MinInstallableTargetSdk__min_installable_target_sdk 5
Test: adb install com.senecacreeksoftware.simpletip-3.apk (this app uses
target sdk 4)
Test: adb shell device_config put package_manager_service
MinInstallableTargetSdk__min_installable_target_sdk 6
Test: adb install com.senecacreeksoftware.simpletip-3.apk
Test: adb shell device_config put package_manager_service
MinInstallableTargetSdk__min_installable_target_sdk 23
Test: Attempted side load install via files app
Test: Attempted install from Play Store of low target sdk app

Change-Id: Id86c65d088b62b0a9b36734c14fbf919fa458e32
parent 068c438d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1958,6 +1958,14 @@ public abstract class PackageManager {
     */
    public static final int INSTALL_FAILED_MISSING_SPLIT = -28;

    /**
     * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
     * if the new package targets a deprecated SDK version.
     *
     * @hide
     */
    public static final int INSTALL_FAILED_DEPRECATED_SDK_VERSION = -29;

    /**
     * Installation parse return code: this is passed in the
     * {@link PackageInstaller#EXTRA_LEGACY_STATUS} if the parser was given a path that is not a
@@ -9618,6 +9626,7 @@ public abstract class PackageManager {
            case INSTALL_FAILED_ABORTED: return "INSTALL_FAILED_ABORTED";
            case INSTALL_FAILED_BAD_DEX_METADATA: return "INSTALL_FAILED_BAD_DEX_METADATA";
            case INSTALL_FAILED_MISSING_SPLIT: return "INSTALL_FAILED_MISSING_SPLIT";
            case INSTALL_FAILED_DEPRECATED_SDK_VERSION: return "INSTALL_FAILED_DEPRECATED_SDK_VERSION";
            case INSTALL_FAILED_BAD_SIGNATURE: return "INSTALL_FAILED_BAD_SIGNATURE";
            case INSTALL_FAILED_WRONG_INSTALLED_VERSION: return "INSTALL_FAILED_WRONG_INSTALLED_VERSION";
            case INSTALL_FAILED_PROCESS_NOT_DEFINED: return "INSTALL_FAILED_PROCESS_NOT_DEFINED";
@@ -9675,6 +9684,7 @@ public abstract class PackageManager {
            case INSTALL_FAILED_ABORTED: return PackageInstaller.STATUS_FAILURE_ABORTED;
            case INSTALL_FAILED_MISSING_SPLIT: return PackageInstaller.STATUS_FAILURE_INCOMPATIBLE;
            case INSTALL_FAILED_PRE_APPROVAL_NOT_AVAILABLE: return PackageInstaller.STATUS_FAILURE_BLOCKED;
            case INSTALL_FAILED_DEPRECATED_SDK_VERSION: return PackageInstaller.STATUS_FAILURE_INCOMPATIBLE;
            default: return PackageInstaller.STATUS_FAILURE;
        }
    }
+24 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_PERMISSION_GROUP;
import static android.content.pm.PackageManager.INSTALL_FAILED_DEPRECATED_SDK_VERSION;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION_GROUP;
@@ -136,6 +137,7 @@ import android.os.incremental.IncrementalManager;
import android.os.incremental.IncrementalStorage;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.provider.DeviceConfig;
import android.stats.storage.StorageEnums;
import android.system.ErrnoException;
import android.system.Os;
@@ -1017,6 +1019,28 @@ final class InstallPackageHelper {
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
        }

        // If the minimum installable SDK version enforcement is enabled, block the install
        // of apps using a lower target SDK version than required. This helps improve security
        // and privacy as malware can target older SDK versions to avoid enforcement of new API
        // behavior.
        if (DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
                "MinInstallableTargetSdk__install_block_enabled",
                false)) {
            int minInstallableTargetSdk =
                    DeviceConfig.getInt(DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
                            "MinInstallableTargetSdk__min_installable_target_sdk",
                            0);
            if (parsedPackage.getTargetSdkVersion() < minInstallableTargetSdk) {
                Slog.w(TAG, "App " + parsedPackage.getPackageName()
                        + " targets deprecated sdk version");
                throw new PrepareFailure(INSTALL_FAILED_DEPRECATED_SDK_VERSION,
                        "App package must target at least version "
                                + minInstallableTargetSdk);
            }
        } else {
            Slog.i(TAG, "Minimum installable target sdk enforcement not enabled");
        }

        // Instant apps have several additional install-time checks.
        if (instantApp) {
            if (parsedPackage.getTargetSdkVersion() < Build.VERSION_CODES.O) {