Updated strict package check patches from GrapheneOS

Signed-off-by: Tad <tad@spotco.us>
This commit is contained in:
Tad 2023-02-03 15:04:37 -05:00
parent 6e75c0dbd3
commit ef51b5e5af
No known key found for this signature in database
GPG Key ID: B286E9F57A07424B
6 changed files with 268 additions and 83 deletions

View File

@ -0,0 +1,31 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Mon, 30 Jan 2023 19:04:30 +0200
Subject: [PATCH] disable package parser cache
This is needed for properly verifying updates of system packages.
---
.../java/com/android/server/pm/PackageManagerServiceUtils.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 302d845e7f15..a45a42aafcf8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -155,7 +155,7 @@ public class PackageManagerServiceUtils {
/**
* The initial enabled state of the cache before other checks are done.
*/
- private static final boolean DEFAULT_PACKAGE_PARSER_CACHE_ENABLED = true;
+ private static final boolean DEFAULT_PACKAGE_PARSER_CACHE_ENABLED = false;
/**
* Whether to skip all other checks and force the cache to be enabled.
@@ -1297,6 +1297,7 @@ public class PackageManagerServiceUtils {
boolean isUserDebugBuild, String incrementalVersion) {
if (!FORCE_PACKAGE_PARSED_CACHE_ENABLED) {
if (!DEFAULT_PACKAGE_PARSER_CACHE_ENABLED) {
+ FileUtils.deleteContentsAndDir(Environment.getPackageCacheDirectory());
return null;
}

View File

@ -0,0 +1,198 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Tue, 31 Jan 2023 17:55:11 +0200
Subject: [PATCH] perform additional boot-time checks on system package updates
[tad@spotco.us]: disable verity checks
---
.../server/pm/InstallPackageHelper.java | 7 +
.../android/server/pm/PackageVerityExt.java | 162 ++++++++++++++++++
2 files changed, 169 insertions(+)
create mode 100644 services/core/java/com/android/server/pm/PackageVerityExt.java
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 7da5f51bcbc2..45fbd95e19d4 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -3781,6 +3781,13 @@ final class InstallPackageHelper {
@Nullable UserHandle user) throws PackageManagerException {
final boolean scanSystemPartition =
(parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0;
+ if ((scanFlags & SCAN_BOOTING) != 0) {
+ if (scanSystemPartition) {
+ PackageVerityExt.addSystemPackage(parsedPackage);
+ } else {
+ PackageVerityExt.checkSystemPackageUpdate(parsedPackage);
+ }
+ }
final ScanRequest initialScanRequest = prepareInitialScanRequest(parsedPackage, parseFlags,
scanFlags, user, null);
final PackageSetting installedPkgSetting = initialScanRequest.mPkgSetting;
diff --git a/services/core/java/com/android/server/pm/PackageVerityExt.java b/services/core/java/com/android/server/pm/PackageVerityExt.java
new file mode 100644
index 000000000000..cd0e213b3f4d
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageVerityExt.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2022 GrapheneOS
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.android.server.pm;
+
+import android.annotation.Nullable;
+import android.content.pm.SigningDetails;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
+import android.os.Build;
+import android.os.SystemProperties;
+import android.util.ArrayMap;
+import android.util.Slog;
+
+import com.android.internal.security.VerityUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
+
+import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_SIGNATURE;
+import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_APK;
+import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
+
+// Performs additional checks on system package updates
+public class PackageVerityExt {
+ private static final String TAG = PackageVerityExt.class.getSimpleName();
+
+ // Parsed packages from immutable partitions. Static shared libraries are handled separately
+ // due to a different policy that OS uses for their replacement
+ private static final ArrayMap<String, AndroidPackage> packages = new ArrayMap<>();
+ private static final ArrayMap<String, AndroidPackage> staticSharedLibraries = new ArrayMap<>();
+
+ // Called when PackageManager scans a package from immutable system image partition during OS boot.
+ // All packages from immutable partitions are scanned before any packages from mutable partitions.
+ public static void addSystemPackage(AndroidPackage pkg) {
+ if (pkg.isStaticSharedLibrary()) {
+ String name = pkg.getStaticSharedLibName();
+ AndroidPackage prev;
+ synchronized (staticSharedLibraries) {
+ prev = staticSharedLibraries.put(name, pkg);
+ }
+ if (prev != null) {
+ Slog.w(TAG, "duplicate static shared lib " + name
+ + ": prev " + prev.getPath() + " -> new " + pkg.getPath());
+ }
+ } else {
+ String name = pkg.getManifestPackageName();
+ AndroidPackage prev;
+ synchronized (packages) {
+ prev = packages.put(name, pkg);
+ }
+ if (prev != null) {
+ Slog.w(TAG, "duplicate system package " + name + ": prev " + prev.getPath() +
+ " -> new " + pkg.getPath());
+ }
+ }
+ }
+
+ // If pkg is a system package update, returns its matching system image package
+ @Nullable public static AndroidPackage getSystemPackage(AndroidPackage pkg) {
+ if (pkg.isStaticSharedLibrary()) {
+ String name = pkg.getStaticSharedLibName();
+ synchronized (staticSharedLibraries) {
+ return staticSharedLibraries.get(name);
+ }
+ } else {
+ String name = pkg.getManifestPackageName();
+ synchronized (packages) {
+ return packages.get(name);
+ }
+ }
+ }
+
+ // Called when PackageManager scans a package from mutable partition (ie /data) during OS boot.
+ // PackageManagerException thrown from here will prevent this package from replacing its system
+ // image version.
+ public static void checkSystemPackageUpdate(AndroidPackage maybeSystemPackageUpdate) throws PackageManagerException {
+ final AndroidPackage systemPkg = getSystemPackage(maybeSystemPackageUpdate);
+
+ if (systemPkg == null) {
+ // not a system package update
+ return;
+ }
+
+ final AndroidPackage systemPkgUpdate = maybeSystemPackageUpdate;
+
+ Slog.d(TAG, "Performing verification of system package update "
+ + systemPkgUpdate.getManifestPackageName());
+
+ if (systemPkg.getLongVersionCode() >= systemPkgUpdate.getLongVersionCode()) {
+ throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
+ "versionCode of system image package (" + systemPkg.getLongVersionCode()
+ + ") is >= versionCode of system package update ("
+ + systemPkgUpdate.getLongVersionCode() + ")");
+ }
+
+ boolean checkFsVerity = false;
+ if (Build.IS_DEBUGGABLE) {
+ if (SystemProperties.getBoolean("persist.disable_boot_time_fsverity_check", false)) {
+ checkFsVerity = false;
+ }
+ }
+
+ if (checkFsVerity) {
+ checkFsVerity(systemPkgUpdate);
+ }
+
+ final SigningDetails updatePkgSigningDetails = parseSigningDetails(systemPkgUpdate,
+ // verify APK against its signature
+ false);
+
+ final SigningDetails systemPkgSigningDetails = parseSigningDetails(systemPkg,
+ // skip signature verification, system image APKs are protected by verified boot
+ true);
+
+ final boolean valid = updatePkgSigningDetails.checkCapability(systemPkgSigningDetails,
+ SigningDetails.CertCapabilities.INSTALLED_DATA)
+ || systemPkgSigningDetails.checkCapability(updatePkgSigningDetails,
+ SigningDetails.CertCapabilities.ROLLBACK);
+
+ if (!valid) {
+ String msg = "System package update " + systemPkgUpdate.getManifestPackageName()
+ + " signature doesn't match the signature of system image package";
+ throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE, msg);
+ }
+ }
+
+ public static void checkFsVerity(AndroidPackage pkg) throws PackageManagerException {
+ final String baseApkPath = pkg.getBaseApkPath();
+ if (!VerityUtils.hasFsverity(baseApkPath)) {
+ throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE,
+ "Base APK doesn't have fs-verity: " + baseApkPath);
+ }
+
+ for (String path : pkg.getSplitCodePaths()) {
+ if (!VerityUtils.hasFsverity(path)) {
+ throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE,
+ "APK split doesn't have fs-verity: " + path);
+ }
+ }
+ }
+
+ private static SigningDetails parseSigningDetails(AndroidPackage pkg, boolean skipVerify) throws PackageManagerException {
+ final ParseTypeImpl input = ParseTypeImpl.forDefaultParsing();
+ final ParseResult<SigningDetails> result = ParsingPackageUtils.getSigningDetails(
+ input, pkg, skipVerify);
+
+ if (result.isError()) {
+ throw new PackageManagerException(
+ result.getErrorCode(), result.getErrorMessage(), result.getException());
+ }
+
+ final SigningDetails sd = result.getResult();
+ if (sd == null) {
+ throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
+ "Null signing details of package " + pkg.getManifestPackageName());
+ }
+
+ return sd;
+ }
+}

View File

@ -0,0 +1,36 @@
From 7d0c4f3aa7c7640afc0496a9c901eeb49c65b47d Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Tue, 31 Jan 2023 19:32:46 +0200
Subject: [PATCH] require fs-verity when installing system package updates
---
.../android/server/pm/InstallPackageHelper.java | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index e929e4762126..2bfbd199d7f5 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -1513,6 +1513,22 @@ && cannotInstallWithBadPermissionGroups(parsedPackage)) {
"Failed to set up verity: " + e);
}
+ boolean checkVerity = true;
+ if (Build.IS_DEBUGGABLE) {
+ if (SystemProperties.getBoolean("persist.disable_install_time_fsverity_check", false)) {
+ checkVerity = false;
+ }
+ }
+
+ if (checkVerity && PackageVerityExt.getSystemPackage(parsedPackage) != null) {
+ try {
+ PackageVerityExt.checkFsVerity(parsedPackage);
+ } catch (PackageManagerException e) {
+ throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
+ "fs-verity not set up for system package update " + e);
+ }
+ }
+
final PackageFreezer freezer =
freezePackageForInstall(pkgName, installFlags, "installPackageLI");
boolean shouldCloseFreezerBeforeReturn = true;

View File

@ -1,30 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Tue, 27 Dec 2022 11:40:14 +0200
Subject: [PATCH] don't allow updating system packages to the same versionCode
versionCode of many system packages, including privileged ones, is set to the current SDK version
and is thus not incremented during non-major OS upgrades.
This allowed to downgrade them to the older version that had the same versionCode.
---
.../java/com/android/server/pm/InstallPackageHelper.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 7da5f51bcbc2..0f3802ac794b 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2466,6 +2466,13 @@ final class InstallPackageHelper {
}
}
}
+
+ if (!Build.isDebuggable() && dataOwnerPkg != null && dataOwnerPkg.isSystem()) {
+ if (dataOwnerPkg.getLongVersionCode() == pkgLite.getLongVersionCode()) {
+ return Pair.create(INSTALL_FAILED_SESSION_INVALID,
+ "Not allowed to update system package to the same versionCode");
+ }
+ }
}
return Pair.create(PackageManager.INSTALL_SUCCEEDED, null);
}

View File

@ -1,51 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Dmitry Muhomor <muhomor.dmitry@gmail.com>
Date: Tue, 27 Dec 2022 11:21:28 +0200
Subject: [PATCH] prefer package from OS image over equal version of upgraded
system package
Previously, system package that was upgraded on the previous OS version was used by the OS even
after OS upgrade that included the same version of this package in OS image.
This weakened verified boot and wasted storage space.
---
.../com/android/server/pm/InstallPackageHelper.java | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 0f3802ac794b..9a4dbb0a0a12 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -3842,10 +3842,10 @@ final class InstallPackageHelper {
final boolean newPkgChangedPaths = pkgAlreadyExists
&& !pkgSetting.getPathString().equals(parsedPackage.getPath());
- final boolean newPkgVersionGreater = pkgAlreadyExists
- && parsedPackage.getLongVersionCode() > pkgSetting.getVersionCode();
+ final boolean newPkgVersionGreaterOrEqual = pkgAlreadyExists
+ && parsedPackage.getLongVersionCode() >= pkgSetting.getVersionCode();
final boolean isSystemPkgBetter = scanSystemPartition && isSystemPkgUpdated
- && newPkgChangedPaths && newPkgVersionGreater;
+ && newPkgChangedPaths && newPkgVersionGreaterOrEqual;
if (isSystemPkgBetter) {
// The version of the application on /system is greater than the version on
// /data. Switch back to the application on /system.
@@ -3873,8 +3873,8 @@ final class InstallPackageHelper {
}
}
- // The version of the application on the /system partition is less than or
- // equal to the version on the /data partition. Throw an exception and use
+ // The version of the application on the /system partition is less than
+ // the version on the /data partition. Throw an exception and use
// the application already installed on the /data partition.
if (scanSystemPartition && isSystemPkgUpdated && !isSystemPkgBetter) {
// In the case of a skipped package, commitReconciledScanResultLocked is not called to
@@ -3938,7 +3938,7 @@ final class InstallPackageHelper {
deletePackageHelper.deletePackageLIF(parsedPackage.getPackageName(), null, true,
mPm.mUserManager.getUserIds(), 0, null, false);
}
- } else if (newPkgVersionGreater) {
+ } else if (newPkgVersionGreaterOrEqual) {
// The application on /system is newer than the application on /data.
// Simply remove the application on /data [keeping application data]
// and replace it with the version on /system.

View File

@ -174,8 +174,9 @@ applyPatch "$DOS_PATCHES/android_frameworks_base/0024-Burnin_Protection.patch";
applyPatch "$DOS_PATCHES/android_frameworks_base/0026-Crash_Details.patch"; #Add an option to show the details of an application error to the user (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0027-Installer_Glitch.patch"; #Make sure PackageInstaller UI returns a result (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0028-Remove_Legacy_Package_Query.patch"; #Don't leak device-wide package list to apps when work profile is present (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0029-Strict_versionCode_Checks-1.patch"; #Don't allow updating system packages to the same versionCode (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0029-Strict_versionCode_Checks-2.patch"; #Prefer package from OS image over equal version of upgraded system package (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0029-Strict_Package_Checks-1.patch"; #Disable package parser cache (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0029-Strict_Package_Checks-2.patch"; #Perform additional boot-time checks on system package updates (GrapheneOS)
#applyPatch "$DOS_PATCHES/android_frameworks_base/0029-Strict_Package_Checks-3.patch"; #Require fs-verity when installing system package updates (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0030-agnss.goog_override.patch"; #Replace agnss.goog with the Broadcom PSDS server (heavily based off of a GrapheneOS patch)
applyPatch "$DOS_PATCHES/android_frameworks_base/0031-appops_reset_fix-1.patch"; #Revert "Null safe package name in AppOps writeState" (GrapheneOS)
applyPatch "$DOS_PATCHES/android_frameworks_base/0031-appops_reset_fix-2.patch"; #appops: skip ops for invalid null package during state serialization (GrapheneOS)