OMS: Add config_signature policy handling
Alongside SIGNATURE and ACTOR_SIGNATURE policies, add CONFIG_SIGNATURE policy to overlayable that overlay fulfills if it is signed with the same certificate as the reference package whose package name is declared in 'config-signature' tag of SystemConfig and is vetted by OMS that it's a system pre-installed package. BUG: 158726924 TEST: regular aapt2, idmap2, OMS tests Change-Id: I645ee72271496008742886274be0d63a2985201b
This commit is contained in:
committed by
Ryan Mitchell
parent
936849dd1a
commit
9336d9e13b
@@ -29,4 +29,5 @@ interface OverlayablePolicy {
|
||||
const int ODM_PARTITION = 0x00000020;
|
||||
const int OEM_PARTITION = 0x00000040;
|
||||
const int ACTOR_SIGNATURE = 0x00000080;
|
||||
const int CONFIG_SIGNATURE = 0x0000100;
|
||||
}
|
||||
|
||||
@@ -61,10 +61,13 @@ Result<Unit> CheckOverlayable(const LoadedPackage& target_package,
|
||||
const ResourceId& target_resource) {
|
||||
static constexpr const PolicyBitmask sDefaultPolicies =
|
||||
PolicyFlags::ODM_PARTITION | PolicyFlags::OEM_PARTITION | PolicyFlags::SYSTEM_PARTITION |
|
||||
PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE;
|
||||
PolicyFlags::VENDOR_PARTITION | PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE |
|
||||
PolicyFlags::CONFIG_SIGNATURE;
|
||||
|
||||
// If the resource does not have an overlayable definition, allow the resource to be overlaid if
|
||||
// the overlay is preinstalled or signed with the same signature as the target.
|
||||
// the overlay is preinstalled, signed with the same signature as the target or signed with the
|
||||
// same signature as reference package defined in SystemConfig under 'overlay-config-signature'
|
||||
// tag.
|
||||
if (!target_package.DefinesOverlayable()) {
|
||||
return (sDefaultPolicies & fulfilled_policies) != 0
|
||||
? Result<Unit>({})
|
||||
|
||||
@@ -38,16 +38,18 @@ constexpr const char* kPolicyOdm = "odm";
|
||||
constexpr const char* kPolicyOem = "oem";
|
||||
constexpr const char* kPolicyProduct = "product";
|
||||
constexpr const char* kPolicyPublic = "public";
|
||||
constexpr const char* kPolicyConfigSignature = "config_signature";
|
||||
constexpr const char* kPolicySignature = "signature";
|
||||
constexpr const char* kPolicySystem = "system";
|
||||
constexpr const char* kPolicyVendor = "vendor";
|
||||
|
||||
inline static const std::array<std::pair<StringPiece, PolicyFlags>, 8> kPolicyStringToFlag = {
|
||||
inline static const std::array<std::pair<StringPiece, PolicyFlags>, 9> kPolicyStringToFlag = {
|
||||
std::pair{kPolicyActor, PolicyFlags::ACTOR_SIGNATURE},
|
||||
{kPolicyOdm, PolicyFlags::ODM_PARTITION},
|
||||
{kPolicyOem, PolicyFlags::OEM_PARTITION},
|
||||
{kPolicyProduct, PolicyFlags::PRODUCT_PARTITION},
|
||||
{kPolicyPublic, PolicyFlags::PUBLIC},
|
||||
{kPolicyConfigSignature, PolicyFlags::CONFIG_SIGNATURE},
|
||||
{kPolicySignature, PolicyFlags::SIGNATURE},
|
||||
{kPolicySystem, PolicyFlags::SYSTEM_PARTITION},
|
||||
{kPolicyVendor, PolicyFlags::VENDOR_PARTITION},
|
||||
|
||||
@@ -43,16 +43,17 @@ namespace R::target {
|
||||
constexpr ResourceId not_overlayable = 0x7f020003;
|
||||
constexpr ResourceId other = 0x7f020004;
|
||||
constexpr ResourceId policy_actor = 0x7f020005;
|
||||
constexpr ResourceId policy_odm = 0x7f020006;
|
||||
constexpr ResourceId policy_oem = 0x7f020007;
|
||||
constexpr ResourceId policy_product = 0x7f020008;
|
||||
constexpr ResourceId policy_public = 0x7f020009;
|
||||
constexpr ResourceId policy_signature = 0x7f02000a;
|
||||
constexpr ResourceId policy_system = 0x7f02000b;
|
||||
constexpr ResourceId policy_system_vendor = 0x7f02000c;
|
||||
constexpr ResourceId str1 = 0x7f02000d;
|
||||
constexpr ResourceId str3 = 0x7f02000f;
|
||||
constexpr ResourceId str4 = 0x7f020010;
|
||||
constexpr ResourceId policy_config_signature = 0x7f020006;
|
||||
constexpr ResourceId policy_odm = 0x7f020007;
|
||||
constexpr ResourceId policy_oem = 0x7f020008;
|
||||
constexpr ResourceId policy_product = 0x7f020009;
|
||||
constexpr ResourceId policy_public = 0x7f02000a;
|
||||
constexpr ResourceId policy_signature = 0x7f02000b;
|
||||
constexpr ResourceId policy_system = 0x7f02000c;
|
||||
constexpr ResourceId policy_system_vendor = 0x7f02000d;
|
||||
constexpr ResourceId str1 = 0x7f02000e;
|
||||
constexpr ResourceId str3 = 0x7f020010;
|
||||
constexpr ResourceId str4 = 0x7f020011;
|
||||
|
||||
namespace literal { // NOLINT(runtime/indentation_namespace)
|
||||
inline const std::string str1 = hexify(R::target::string::str1);
|
||||
@@ -94,13 +95,14 @@ namespace R::system_overlay_invalid::string {
|
||||
constexpr ResourceId not_overlayable = 0x7f010000;
|
||||
constexpr ResourceId other = 0x7f010001;
|
||||
constexpr ResourceId policy_actor = 0x7f010002;
|
||||
constexpr ResourceId policy_odm = 0x7f010003;
|
||||
constexpr ResourceId policy_oem = 0x7f010004;
|
||||
constexpr ResourceId policy_product = 0x7f010005;
|
||||
constexpr ResourceId policy_public = 0x7f010006;
|
||||
constexpr ResourceId policy_signature = 0x7f010007;
|
||||
constexpr ResourceId policy_system = 0x7f010008;
|
||||
constexpr ResourceId policy_system_vendor = 0x7f010009;
|
||||
constexpr ResourceId policy_config_signature = 0x7f010003;
|
||||
constexpr ResourceId policy_odm = 0x7f010004;
|
||||
constexpr ResourceId policy_oem = 0x7f010005;
|
||||
constexpr ResourceId policy_product = 0x7f010006;
|
||||
constexpr ResourceId policy_public = 0x7f010007;
|
||||
constexpr ResourceId policy_signature = 0x7f010008;
|
||||
constexpr ResourceId policy_system = 0x7f010009;
|
||||
constexpr ResourceId policy_system_vendor = 0x7f01000a;
|
||||
} // namespace R::system_overlay_invalid::string
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -237,7 +237,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore
|
||||
|
||||
ASSERT_TRUE(resources) << resources.GetErrorMessage();
|
||||
auto& res = *resources;
|
||||
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 10U);
|
||||
ASSERT_EQ(res.GetTargetToOverlayMap().size(), 11U);
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::not_overlayable,
|
||||
false /* rewrite */));
|
||||
@@ -256,6 +256,10 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsPolicySystemPublicInvalidIgnore
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_public,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
|
||||
Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_config_signature,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_signature,
|
||||
false /* rewrite */));
|
||||
@@ -298,8 +302,9 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) {
|
||||
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 0U);
|
||||
}
|
||||
|
||||
// Overlays that are pre-installed or are signed with the same signature as the target can overlay
|
||||
// packages that have not defined overlayable resources.
|
||||
// Overlays that are pre-installed or are signed with the same signature as the target or are signed
|
||||
// with the same signature as the reference package can overlay packages that have not defined
|
||||
// overlayable resources.
|
||||
TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
|
||||
auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void {
|
||||
auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk",
|
||||
@@ -309,7 +314,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
|
||||
|
||||
ASSERT_TRUE(resources) << resources.GetErrorMessage();
|
||||
auto& res = *resources;
|
||||
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U);
|
||||
ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 11U);
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::not_overlayable,
|
||||
false /* rewrite */));
|
||||
@@ -330,6 +335,10 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_public, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_public,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_config_signature,
|
||||
Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_config_signature,
|
||||
false /* rewrite */));
|
||||
ASSERT_RESULT(MappingExists(res, R::target::string::policy_signature, Res_value::TYPE_REFERENCE,
|
||||
R::system_overlay_invalid::string::policy_signature,
|
||||
false /* rewrite */));
|
||||
@@ -342,6 +351,7 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) {
|
||||
};
|
||||
|
||||
CheckEntries(PolicyFlags::SIGNATURE);
|
||||
CheckEntries(PolicyFlags::CONFIG_SIGNATURE);
|
||||
CheckEntries(PolicyFlags::PRODUCT_PARTITION);
|
||||
CheckEntries(PolicyFlags::SYSTEM_PARTITION);
|
||||
CheckEntries(PolicyFlags::VENDOR_PARTITION);
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
|
||||
namespace android::idmap2::TestConstants {
|
||||
|
||||
constexpr const auto TARGET_CRC = 0x41c60c8c;
|
||||
constexpr const auto TARGET_CRC_STRING = "41c60c8c";
|
||||
constexpr const auto TARGET_CRC = 0x7c2d4719;
|
||||
constexpr const auto TARGET_CRC_STRING = "7c2d4719";
|
||||
|
||||
constexpr const auto OVERLAY_CRC = 0xc054fb26;
|
||||
constexpr const auto OVERLAY_CRC_STRING = "c054fb26";
|
||||
constexpr const auto OVERLAY_CRC = 0x5afff726;
|
||||
constexpr const auto OVERLAY_CRC_STRING = "5afff726";
|
||||
|
||||
} // namespace android::idmap2::TestConstants
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -26,6 +26,7 @@
|
||||
<string name="policy_odm">policy_odm</string>
|
||||
<string name="policy_oem">policy_oem</string>
|
||||
<string name="policy_actor">policy_actor</string>
|
||||
<string name="policy_config_signature">policy_config_signature</string>
|
||||
|
||||
<!-- Requests to overlay a resource that is not declared as overlayable. -->
|
||||
<string name="not_overlayable">not_overlayable</string>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -45,6 +45,10 @@
|
||||
<item type="string" name="policy_actor" />
|
||||
</policy>
|
||||
|
||||
<policy type="config_signature">
|
||||
<item type="string" name="policy_config_signature"/>
|
||||
</policy>
|
||||
|
||||
<!-- Resources publicly overlayable -->
|
||||
<policy type="public">
|
||||
<item type="string" name="policy_public" />
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
<string name="policy_system">policy_system</string>
|
||||
<string name="policy_system_vendor">policy_system_vendor</string>
|
||||
<string name="policy_actor">policy_actor</string>
|
||||
<string name="policy_config_signature">policy_config_signature</string>
|
||||
|
||||
<string name="other">other</string>
|
||||
</resources>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -19,6 +19,7 @@ package com.android.server;
|
||||
import static com.android.internal.util.ArrayUtils.appendInt;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.FeatureInfo;
|
||||
@@ -245,6 +246,14 @@ public class SystemConfig {
|
||||
*/
|
||||
private Map<String, Map<String, String>> mNamedActors = null;
|
||||
|
||||
// Package name of the package pre-installed on a read-only
|
||||
// partition that is used to verify if an overlay package fulfills
|
||||
// the 'config_signature' policy by comparing their signatures:
|
||||
// if the overlay package is signed with the same certificate as
|
||||
// the package declared in 'config-signature' tag, then the
|
||||
// overlay package fulfills the 'config_signature' policy.
|
||||
private String mOverlayConfigSignaturePackage;
|
||||
|
||||
public static SystemConfig getInstance() {
|
||||
if (!isSystemProcess()) {
|
||||
Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
|
||||
@@ -432,6 +441,12 @@ public class SystemConfig {
|
||||
return mNamedActors != null ? mNamedActors : Collections.emptyMap();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getOverlayConfigSignaturePackage() {
|
||||
return TextUtils.isEmpty(mOverlayConfigSignaturePackage)
|
||||
? null : mOverlayConfigSignaturePackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only use for testing. Do NOT use in production code.
|
||||
* @param readPermissions false to create an empty SystemConfig; true to read the permissions.
|
||||
@@ -1137,6 +1152,27 @@ public class SystemConfig {
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
} break;
|
||||
case "overlay-config-signature": {
|
||||
if (allowAll) {
|
||||
String pkgName = parser.getAttributeValue(null, "package");
|
||||
if (pkgName == null) {
|
||||
Slog.w(TAG, "<" + name + "> without package in " + permFile
|
||||
+ " at " + parser.getPositionDescription());
|
||||
} else {
|
||||
if (TextUtils.isEmpty(mOverlayConfigSignaturePackage)) {
|
||||
mOverlayConfigSignaturePackage = pkgName.intern();
|
||||
} else {
|
||||
throw new IllegalStateException("Reference signature package "
|
||||
+ "defined as both "
|
||||
+ mOverlayConfigSignaturePackage
|
||||
+ " and " + pkgName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logNotAllowedInPartition(name, permFile, parser);
|
||||
}
|
||||
XmlUtils.skipCurrentTag(parser);
|
||||
} break;
|
||||
case "rollback-whitelisted-app": {
|
||||
String pkgname = parser.getAttributeValue(null, "package");
|
||||
if (pkgname == null) {
|
||||
|
||||
@@ -1717,6 +1717,10 @@ struct ResTable_overlayable_policy_header
|
||||
// The overlay must be signed with the same signature as the actor declared for the target
|
||||
// resource
|
||||
ACTOR_SIGNATURE = 0x00000080,
|
||||
|
||||
// The overlay must be signed with the same signature as the reference package declared
|
||||
// in the SystemConfig
|
||||
CONFIG_SIGNATURE = 0x00000100,
|
||||
};
|
||||
|
||||
using PolicyBitmask = uint32_t;
|
||||
|
||||
@@ -69,6 +69,7 @@ public abstract class PackageManagerInternal {
|
||||
public static final int PACKAGE_WIFI = 13;
|
||||
public static final int PACKAGE_COMPANION = 14;
|
||||
public static final int PACKAGE_RETAIL_DEMO = 15;
|
||||
public static final int PACKAGE_OVERLAY_CONFIG_SIGNATURE = 16;
|
||||
|
||||
@IntDef(flag = true, prefix = "RESOLVE_", value = {
|
||||
RESOLVE_NON_BROWSER_ONLY,
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.content.pm.PackageInfo;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.OverlayablePolicy;
|
||||
import android.os.SystemProperties;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -53,11 +54,20 @@ final class IdmapManager {
|
||||
}
|
||||
|
||||
private final IdmapDaemon mIdmapDaemon;
|
||||
private final OverlayableInfoCallback mOverlayableCallback;
|
||||
private final PackageManagerHelper mPackageManager;
|
||||
|
||||
IdmapManager(final IdmapDaemon idmapDaemon, final OverlayableInfoCallback verifyCallback) {
|
||||
mOverlayableCallback = verifyCallback;
|
||||
/**
|
||||
* Package name of the reference package defined in 'config-signature' tag of
|
||||
* SystemConfig or empty String if tag not defined. This package is vetted on scan by
|
||||
* PackageManagerService that it's a system package and is used to check if overlay matches
|
||||
* its signature in order to fulfill the config_signature policy.
|
||||
*/
|
||||
private final String mConfigSignaturePackage;
|
||||
|
||||
IdmapManager(final IdmapDaemon idmapDaemon, final PackageManagerHelper packageManager) {
|
||||
mPackageManager = packageManager;
|
||||
mIdmapDaemon = idmapDaemon;
|
||||
mConfigSignaturePackage = packageManager.getConfigSignaturePackage();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +149,7 @@ final class IdmapManager {
|
||||
int fulfilledPolicies = OverlayablePolicy.PUBLIC;
|
||||
|
||||
// Overlay matches target signature
|
||||
if (mOverlayableCallback.signaturesMatching(targetPackage.packageName,
|
||||
if (mPackageManager.signaturesMatching(targetPackage.packageName,
|
||||
overlayPackage.packageName, userId)) {
|
||||
fulfilledPolicies |= OverlayablePolicy.SIGNATURE;
|
||||
}
|
||||
@@ -149,6 +159,16 @@ final class IdmapManager {
|
||||
fulfilledPolicies |= OverlayablePolicy.ACTOR_SIGNATURE;
|
||||
}
|
||||
|
||||
// If SystemConfig defines 'config-signature' package, given that
|
||||
// this package is vetted by OverlayManagerService that it's a
|
||||
// preinstalled package, check if overlay matches its signature.
|
||||
if (!TextUtils.isEmpty(mConfigSignaturePackage)
|
||||
&& mPackageManager.signaturesMatching(mConfigSignaturePackage,
|
||||
overlayPackage.packageName,
|
||||
userId)) {
|
||||
fulfilledPolicies |= OverlayablePolicy.CONFIG_SIGNATURE;
|
||||
}
|
||||
|
||||
// Vendor partition (/vendor)
|
||||
if (ai.isVendor()) {
|
||||
return fulfilledPolicies | OverlayablePolicy.VENDOR_PARTITION;
|
||||
@@ -183,12 +203,12 @@ final class IdmapManager {
|
||||
String targetOverlayableName = overlayPackage.targetOverlayableName;
|
||||
if (targetOverlayableName != null) {
|
||||
try {
|
||||
OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget(
|
||||
OverlayableInfo overlayableInfo = mPackageManager.getOverlayableForTarget(
|
||||
targetPackage.packageName, targetOverlayableName, userId);
|
||||
if (overlayableInfo != null && overlayableInfo.actor != null) {
|
||||
String actorPackageName = OverlayActorEnforcer.getPackageNameForActor(
|
||||
overlayableInfo.actor, mOverlayableCallback.getNamedActors()).first;
|
||||
if (mOverlayableCallback.signaturesMatching(actorPackageName,
|
||||
overlayableInfo.actor, mPackageManager.getNamedActors()).first;
|
||||
if (mPackageManager.signaturesMatching(actorPackageName,
|
||||
overlayPackage.packageName, userId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class OverlayActorEnforcer {
|
||||
// By default, the reason is not logged to prevent leaks of why it failed
|
||||
private static final boolean DEBUG_REASON = false;
|
||||
|
||||
private final OverlayableInfoCallback mOverlayableCallback;
|
||||
private final PackageManagerHelper mPackageManager;
|
||||
|
||||
/**
|
||||
* @return nullable actor result with {@link ActorState} failure status
|
||||
@@ -79,8 +79,8 @@ public class OverlayActorEnforcer {
|
||||
return Pair.create(packageName, ActorState.ALLOWED);
|
||||
}
|
||||
|
||||
public OverlayActorEnforcer(@NonNull OverlayableInfoCallback overlayableCallback) {
|
||||
mOverlayableCallback = overlayableCallback;
|
||||
public OverlayActorEnforcer(@NonNull PackageManagerHelper packageManager) {
|
||||
mPackageManager = packageManager;
|
||||
}
|
||||
|
||||
void enforceActor(@NonNull OverlayInfo overlayInfo, @NonNull String methodName,
|
||||
@@ -110,7 +110,7 @@ public class OverlayActorEnforcer {
|
||||
return ActorState.ALLOWED;
|
||||
}
|
||||
|
||||
String[] callingPackageNames = mOverlayableCallback.getPackagesForUid(callingUid);
|
||||
String[] callingPackageNames = mPackageManager.getPackagesForUid(callingUid);
|
||||
if (ArrayUtils.isEmpty(callingPackageNames)) {
|
||||
return ActorState.NO_PACKAGES_FOR_UID;
|
||||
}
|
||||
@@ -125,12 +125,12 @@ public class OverlayActorEnforcer {
|
||||
|
||||
if (TextUtils.isEmpty(targetOverlayableName)) {
|
||||
try {
|
||||
if (mOverlayableCallback.doesTargetDefineOverlayable(targetPackageName, userId)) {
|
||||
if (mPackageManager.doesTargetDefineOverlayable(targetPackageName, userId)) {
|
||||
return ActorState.MISSING_TARGET_OVERLAYABLE_NAME;
|
||||
} else {
|
||||
// If there's no overlayable defined, fallback to the legacy permission check
|
||||
try {
|
||||
mOverlayableCallback.enforcePermission(
|
||||
mPackageManager.enforcePermission(
|
||||
android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
|
||||
|
||||
// If the previous method didn't throw, check passed
|
||||
@@ -146,7 +146,7 @@ public class OverlayActorEnforcer {
|
||||
|
||||
OverlayableInfo targetOverlayable;
|
||||
try {
|
||||
targetOverlayable = mOverlayableCallback.getOverlayableForTarget(targetPackageName,
|
||||
targetOverlayable = mPackageManager.getOverlayableForTarget(targetPackageName,
|
||||
targetOverlayableName, userId);
|
||||
} catch (IOException e) {
|
||||
return ActorState.UNABLE_TO_GET_TARGET;
|
||||
@@ -160,7 +160,7 @@ public class OverlayActorEnforcer {
|
||||
if (TextUtils.isEmpty(actor)) {
|
||||
// If there's no actor defined, fallback to the legacy permission check
|
||||
try {
|
||||
mOverlayableCallback.enforcePermission(
|
||||
mPackageManager.enforcePermission(
|
||||
android.Manifest.permission.CHANGE_OVERLAY_PACKAGES, methodName);
|
||||
|
||||
// If the previous method didn't throw, check passed
|
||||
@@ -170,7 +170,7 @@ public class OverlayActorEnforcer {
|
||||
}
|
||||
}
|
||||
|
||||
Map<String, Map<String, String>> namedActors = mOverlayableCallback.getNamedActors();
|
||||
Map<String, Map<String, String>> namedActors = mPackageManager.getNamedActors();
|
||||
Pair<String, ActorState> actorUriPair = getPackageNameForActor(actor, namedActors);
|
||||
ActorState actorUriState = actorUriPair.second;
|
||||
if (actorUriState != ActorState.ALLOWED) {
|
||||
@@ -178,7 +178,7 @@ public class OverlayActorEnforcer {
|
||||
}
|
||||
|
||||
String packageName = actorUriPair.first;
|
||||
PackageInfo packageInfo = mOverlayableCallback.getPackageInfo(packageName, userId);
|
||||
PackageInfo packageInfo = mPackageManager.getPackageInfo(packageName, userId);
|
||||
if (packageInfo == null) {
|
||||
return ActorState.MISSING_APP_INFO;
|
||||
}
|
||||
|
||||
@@ -1053,8 +1053,7 @@ public final class OverlayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class PackageManagerHelperImpl implements PackageManagerHelper,
|
||||
OverlayableInfoCallback {
|
||||
private static final class PackageManagerHelperImpl implements PackageManagerHelper {
|
||||
|
||||
private final Context mContext;
|
||||
private final IPackageManager mPackageManager;
|
||||
@@ -1127,6 +1126,14 @@ public final class OverlayManagerService extends SystemService {
|
||||
return overlays;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getConfigSignaturePackage() {
|
||||
final String[] pkgs = mPackageManagerInternal.getKnownPackageNames(
|
||||
PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE,
|
||||
UserHandle.USER_SYSTEM);
|
||||
return (pkgs.length == 0) ? null : pkgs[0];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.om;
|
||||
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.om.OverlayableInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import com.android.server.pm.PackageManagerServiceUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Delegate to the system for querying information about overlayables and packages.
|
||||
*/
|
||||
public interface OverlayableInfoCallback {
|
||||
|
||||
/**
|
||||
* Read from the APK and AndroidManifest of a package to return the overlayable defined for
|
||||
* a given name.
|
||||
*
|
||||
* @throws IOException if the target can't be read
|
||||
*/
|
||||
@Nullable
|
||||
OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
|
||||
@NonNull String targetOverlayableName, int userId)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* @see PackageManager#getPackagesForUid(int)
|
||||
*/
|
||||
@Nullable
|
||||
String[] getPackagesForUid(int uid);
|
||||
|
||||
/**
|
||||
* @param userId user to filter package visibility by
|
||||
* @see PackageManager#getPackageInfo(String, int)
|
||||
*/
|
||||
@Nullable
|
||||
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
|
||||
|
||||
/**
|
||||
* @return map of system pre-defined, uniquely named actors; keys are namespace,
|
||||
* value maps actor name to package name
|
||||
*/
|
||||
@NonNull
|
||||
Map<String, Map<String, String>> getNamedActors();
|
||||
|
||||
/**
|
||||
* @return true if the target package has declared an overlayable
|
||||
*/
|
||||
boolean doesTargetDefineOverlayable(String targetPackageName, int userId) throws IOException;
|
||||
|
||||
/**
|
||||
* @throws SecurityException containing message if the caller doesn't have the given
|
||||
* permission
|
||||
*/
|
||||
void enforcePermission(String permission, String message) throws SecurityException;
|
||||
|
||||
/**
|
||||
* @return true if {@link PackageManagerServiceUtils#compareSignatures} run on both packages
|
||||
* in the system returns {@link PackageManager#SIGNATURE_MATCH}
|
||||
*/
|
||||
boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
|
||||
}
|
||||
@@ -17,11 +17,17 @@
|
||||
package com.android.server.om;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.om.OverlayableInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
|
||||
import com.android.server.pm.PackageManagerServiceUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Delegate for {@link PackageManager} and {@link PackageManagerInternal} functionality,
|
||||
@@ -30,7 +36,65 @@ import java.util.List;
|
||||
* @hide
|
||||
*/
|
||||
interface PackageManagerHelper {
|
||||
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
|
||||
boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
|
||||
/**
|
||||
* @return true if the target package has declared an overlayable
|
||||
*/
|
||||
boolean doesTargetDefineOverlayable(String targetPackageName, int userId) throws IOException;
|
||||
|
||||
/**
|
||||
* @throws SecurityException containing message if the caller doesn't have the given
|
||||
* permission
|
||||
*/
|
||||
void enforcePermission(String permission, String message) throws SecurityException;
|
||||
|
||||
/**
|
||||
* Returns the package name of the reference package defined in 'overlay-config-signature' tag
|
||||
* of SystemConfig. This package is vetted on scan by PackageManagerService that it's a system
|
||||
* package and is used to check if overlay matches its signature in order to fulfill the
|
||||
* config_signature policy.
|
||||
*/
|
||||
@Nullable
|
||||
String getConfigSignaturePackage();
|
||||
|
||||
/**
|
||||
* @return map of system pre-defined, uniquely named actors; keys are namespace,
|
||||
* value maps actor name to package name
|
||||
*/
|
||||
@NonNull
|
||||
Map<String, Map<String, String>> getNamedActors();
|
||||
|
||||
/**
|
||||
* @see PackageManagerInternal#getOverlayPackages(int)
|
||||
*/
|
||||
List<PackageInfo> getOverlayPackages(int userId);
|
||||
|
||||
/**
|
||||
* Read from the APK and AndroidManifest of a package to return the overlayable defined for
|
||||
* a given name.
|
||||
*
|
||||
* @throws IOException if the target can't be read
|
||||
*/
|
||||
@Nullable
|
||||
OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
|
||||
@NonNull String targetOverlayableName, int userId)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* @see PackageManager#getPackagesForUid(int)
|
||||
*/
|
||||
@Nullable
|
||||
String[] getPackagesForUid(int uid);
|
||||
|
||||
/**
|
||||
* @param userId user to filter package visibility by
|
||||
* @see PackageManager#getPackageInfo(String, int)
|
||||
*/
|
||||
@Nullable
|
||||
PackageInfo getPackageInfo(@NonNull String packageName, int userId);
|
||||
|
||||
/**
|
||||
* @return true if {@link PackageManagerServiceUtils#compareSignatures} run on both packages
|
||||
* in the system returns {@link PackageManager#SIGNATURE_MATCH}
|
||||
*/
|
||||
boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId);
|
||||
}
|
||||
|
||||
@@ -120,6 +120,7 @@ import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
|
||||
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
|
||||
import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
|
||||
import static com.android.server.pm.PackageManagerServiceCompilerMapping.getDefaultCompilerFilter;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.comparePackageSignatures;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.decompressFile;
|
||||
@@ -1127,6 +1128,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
public @Nullable String storageManagerPackage;
|
||||
public @Nullable String defaultTextClassifierPackage;
|
||||
public @Nullable String systemTextClassifierPackage;
|
||||
public @Nullable String overlayConfigSignaturePackage;
|
||||
public ViewCompiler viewCompiler;
|
||||
public @Nullable String wellbeingPackage;
|
||||
public @Nullable String retailDemoPackage;
|
||||
@@ -1659,6 +1661,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final @Nullable String mServicesExtensionPackageName;
|
||||
final @Nullable String mSharedSystemSharedLibraryPackageName;
|
||||
final @Nullable String mRetailDemoPackage;
|
||||
final @Nullable String mOverlayConfigSignaturePackage;
|
||||
|
||||
private final PackageUsage mPackageUsage = new PackageUsage();
|
||||
private final CompilerStats mCompilerStats = new CompilerStats();
|
||||
@@ -2814,6 +2817,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mIncidentReportApproverPackage = testParams.incidentReportApproverPackage;
|
||||
mServicesExtensionPackageName = testParams.servicesExtensionPackageName;
|
||||
mSharedSystemSharedLibraryPackageName = testParams.sharedSystemSharedLibraryPackageName;
|
||||
mOverlayConfigSignaturePackage = testParams.overlayConfigSignaturePackage;
|
||||
|
||||
mResolveComponentName = testParams.resolveComponentName;
|
||||
mPackages.putAll(testParams.packages);
|
||||
@@ -3379,6 +3383,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mAppPredictionServicePackage = getAppPredictionServicePackageName();
|
||||
mIncidentReportApproverPackage = getIncidentReportApproverPackageName();
|
||||
mRetailDemoPackage = getRetailDemoPackageName();
|
||||
mOverlayConfigSignaturePackage = getOverlayConfigSignaturePackageName();
|
||||
|
||||
// Now that we know all of the shared libraries, update all clients to have
|
||||
// the correct library paths.
|
||||
@@ -12119,12 +12124,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
|
||||
// Exempt SharedUsers signed with the platform key.
|
||||
PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
|
||||
if ((platformPkgSetting.signatures.mSigningDetails
|
||||
!= PackageParser.SigningDetails.UNKNOWN)
|
||||
&& (compareSignatures(
|
||||
platformPkgSetting.signatures.mSigningDetails.signatures,
|
||||
pkg.getSigningDetails().signatures)
|
||||
!= PackageManager.SIGNATURE_MATCH)) {
|
||||
if (!comparePackageSignatures(platformPkgSetting,
|
||||
pkg.getSigningDetails().signatures)) {
|
||||
throw new PackageManagerException("Apps that share a user with a " +
|
||||
"privileged app must themselves be marked as privileged. " +
|
||||
pkg.getPackageName() + " shares privileged user " +
|
||||
@@ -12171,12 +12172,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
if (pkg.getTargetSdkVersion() < Build.VERSION_CODES.Q) {
|
||||
final PackageSetting platformPkgSetting =
|
||||
mSettings.getPackageLPr("android");
|
||||
if ((platformPkgSetting.signatures.mSigningDetails
|
||||
!= PackageParser.SigningDetails.UNKNOWN)
|
||||
&& (compareSignatures(
|
||||
platformPkgSetting.signatures.mSigningDetails.signatures,
|
||||
pkg.getSigningDetails().signatures)
|
||||
!= PackageManager.SIGNATURE_MATCH)) {
|
||||
if (!comparePackageSignatures(platformPkgSetting,
|
||||
pkg.getSigningDetails().signatures)) {
|
||||
throw new PackageManagerException("Overlay "
|
||||
+ pkg.getPackageName()
|
||||
+ " must target Q or later, "
|
||||
@@ -12185,24 +12182,35 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
}
|
||||
|
||||
// A non-preloaded overlay package, without <overlay android:targetName>, will
|
||||
// only be used if it is signed with the same certificate as its target. If the
|
||||
// target is already installed, check this here to augment the last line of
|
||||
// defence which is OMS.
|
||||
// only be used if it is signed with the same certificate as its target OR if
|
||||
// it is signed with the same certificate as a reference package declared
|
||||
// in 'config-signature' tag of SystemConfig.
|
||||
// If the target is already installed or 'config-signature' tag in SystemConfig
|
||||
// is set, check this here to augment the last line of defence which is OMS.
|
||||
if (pkg.getOverlayTargetName() == null) {
|
||||
final PackageSetting targetPkgSetting =
|
||||
mSettings.getPackageLPr(pkg.getOverlayTarget());
|
||||
if (targetPkgSetting != null) {
|
||||
if ((targetPkgSetting.signatures.mSigningDetails
|
||||
!= PackageParser.SigningDetails.UNKNOWN)
|
||||
&& (compareSignatures(
|
||||
targetPkgSetting.signatures.mSigningDetails.signatures,
|
||||
pkg.getSigningDetails().signatures)
|
||||
!= PackageManager.SIGNATURE_MATCH)) {
|
||||
throw new PackageManagerException("Overlay "
|
||||
+ pkg.getPackageName() + " and target "
|
||||
+ pkg.getOverlayTarget() + " signed with"
|
||||
+ " different certificates, and the overlay lacks"
|
||||
+ " <overlay android:targetName>");
|
||||
if (!comparePackageSignatures(targetPkgSetting,
|
||||
pkg.getSigningDetails().signatures)) {
|
||||
// check reference signature
|
||||
if (mOverlayConfigSignaturePackage == null) {
|
||||
throw new PackageManagerException("Overlay "
|
||||
+ pkg.getPackageName() + " and target "
|
||||
+ pkg.getOverlayTarget() + " signed with"
|
||||
+ " different certificates, and the overlay lacks"
|
||||
+ " <overlay android:targetName>");
|
||||
}
|
||||
final PackageSetting refPkgSetting =
|
||||
mSettings.getPackageLPr(mOverlayConfigSignaturePackage);
|
||||
if (!comparePackageSignatures(refPkgSetting,
|
||||
pkg.getSigningDetails().signatures)) {
|
||||
throw new PackageManagerException("Overlay "
|
||||
+ pkg.getPackageName() + " signed with a different "
|
||||
+ "certificate than both the reference package and "
|
||||
+ "target " + pkg.getOverlayTarget() + ", and the "
|
||||
+ "overlay lacks <overlay android:targetName>");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20755,6 +20763,11 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
return ensureSystemPackageName(contentCaptureServiceComponentName.getPackageName());
|
||||
}
|
||||
|
||||
public String getOverlayConfigSignaturePackageName() {
|
||||
return ensureSystemPackageName(SystemConfig.getInstance()
|
||||
.getOverlayConfigSignaturePackage());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getRetailDemoPackageName() {
|
||||
final String predefinedPkgName = mContext.getString(R.string.config_retailDemoPackage);
|
||||
@@ -24275,6 +24288,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
return TextUtils.isEmpty(mRetailDemoPackage)
|
||||
? ArrayUtils.emptyArray(String.class)
|
||||
: new String[] {mRetailDemoPackage};
|
||||
case PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE:
|
||||
return filterOnlySystemPackages(getOverlayConfigSignaturePackageName());
|
||||
default:
|
||||
return ArrayUtils.emptyArray(String.class);
|
||||
}
|
||||
|
||||
@@ -487,6 +487,18 @@ public class PackageManagerServiceUtils {
|
||||
return PackageManager.SIGNATURE_NO_MATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the signature set of the package is identical to the specified signature
|
||||
* set or if the signing details of the package are unknown.
|
||||
*/
|
||||
public static boolean comparePackageSignatures(PackageSetting pkgSetting,
|
||||
Signature[] signatures) {
|
||||
return pkgSetting.signatures.mSigningDetails
|
||||
== PackageParser.SigningDetails.UNKNOWN
|
||||
|| compareSignatures(pkgSetting.signatures.mSigningDetails.signatures, signatures)
|
||||
== PackageManager.SIGNATURE_MATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for backward compatibility to make sure any packages with
|
||||
* certificate chains get upgraded to the new style. {@code existingSigs}
|
||||
|
||||
@@ -160,7 +160,7 @@ class OverlayActorEnforcerTests {
|
||||
private val hasPermission: Boolean = false,
|
||||
private val overlayableInfo: OverlayableInfo? = null,
|
||||
private vararg val packageNames: String = arrayOf("com.test.actor.one")
|
||||
) : OverlayableInfoCallback {
|
||||
) : PackageManagerHelper {
|
||||
|
||||
override fun getNamedActors() = if (isActor) {
|
||||
mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME))
|
||||
@@ -195,6 +195,14 @@ class OverlayActorEnforcerTests {
|
||||
}
|
||||
}
|
||||
|
||||
override fun getConfigSignaturePackage(): String {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun getOverlayPackages(userId: Int): MutableList<PackageInfo> {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
override fun signaturesMatching(pkgName1: String, pkgName2: String, userId: Int): Boolean {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
||||
@Test
|
||||
public void testUpdateOverlaysForUser() {
|
||||
final OverlayManagerServiceImpl impl = getImpl();
|
||||
addSystemPackage(target(TARGET), USER);
|
||||
addSystemPackage(target("some.other.target"), USER);;
|
||||
addSystemPackage(overlay(OVERLAY, TARGET), USER);
|
||||
addPackage(target(TARGET), USER);
|
||||
addPackage(target("some.other.target"), USER);
|
||||
addPackage(overlay(OVERLAY, TARGET), USER);
|
||||
|
||||
// do nothing, expect no change
|
||||
final List<String> a = impl.updateOverlaysForUser(USER);
|
||||
@@ -54,7 +54,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
||||
assertTrue(a.contains(TARGET));
|
||||
|
||||
// upgrade overlay, keep target
|
||||
addSystemPackage(overlay(OVERLAY, TARGET), USER);
|
||||
addPackage(overlay(OVERLAY, TARGET), USER);
|
||||
|
||||
final List<String> b = impl.updateOverlaysForUser(USER);
|
||||
assertEquals(1, b.size());
|
||||
@@ -66,7 +66,7 @@ public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceI
|
||||
assertTrue(c.contains(TARGET));
|
||||
|
||||
// upgrade overlay, switch to new target
|
||||
addSystemPackage(overlay(OVERLAY, "some.other.target"), USER);
|
||||
addPackage(overlay(OVERLAY, "some.other.target"), USER);
|
||||
final List<String> d = impl.updateOverlaysForUser(USER);
|
||||
assertEquals(2, d.size());
|
||||
assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.om;
|
||||
import static android.content.om.OverlayInfo.STATE_DISABLED;
|
||||
import static android.content.om.OverlayInfo.STATE_ENABLED;
|
||||
import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
|
||||
import static android.os.OverlayablePolicy.CONFIG_SIGNATURE;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
@@ -49,6 +50,10 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
|
||||
private static final String OVERLAY3 = OVERLAY + "3";
|
||||
private static final int USER3 = USER2 + 1;
|
||||
|
||||
private static final String CONFIG_SIGNATURE_REFERENCE_PKG = "com.dummy.ref";
|
||||
private static final String CERT_CONFIG_OK = "config_certificate_ok";
|
||||
private static final String CERT_CONFIG_NOK = "config_certificate_nok";
|
||||
|
||||
@Test
|
||||
public void testGetOverlayInfo() {
|
||||
installNewPackage(overlay(OVERLAY, TARGET), USER);
|
||||
@@ -204,4 +209,87 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes
|
||||
impl.setEnabled(OVERLAY, true, USER);
|
||||
assertEquals(0, listener.count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigSignaturePolicyOk() {
|
||||
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
|
||||
reinitializeImpl();
|
||||
|
||||
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
|
||||
installNewPackage(target(TARGET), USER);
|
||||
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_OK), USER);
|
||||
|
||||
final DummyIdmapDaemon idmapd = getIdmapd();
|
||||
final DummyDeviceState state = getState();
|
||||
String overlayPath = state.select(OVERLAY, USER).apkPath;
|
||||
assertTrue(idmapd.idmapExists(overlayPath, USER));
|
||||
|
||||
DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
|
||||
assertTrue((CONFIG_SIGNATURE & idmap.policies) == CONFIG_SIGNATURE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigSignaturePolicyCertNok() {
|
||||
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
|
||||
reinitializeImpl();
|
||||
|
||||
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
|
||||
installNewPackage(target(TARGET), USER);
|
||||
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
|
||||
|
||||
final DummyIdmapDaemon idmapd = getIdmapd();
|
||||
final DummyDeviceState state = getState();
|
||||
String overlayPath = state.select(OVERLAY, USER).apkPath;
|
||||
assertTrue(idmapd.idmapExists(overlayPath, USER));
|
||||
|
||||
DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
|
||||
assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigSignaturePolicyNoConfig() {
|
||||
addPackage(target(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
|
||||
installNewPackage(target(TARGET), USER);
|
||||
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
|
||||
|
||||
final DummyIdmapDaemon idmapd = getIdmapd();
|
||||
final DummyDeviceState state = getState();
|
||||
String overlayPath = state.select(OVERLAY, USER).apkPath;
|
||||
assertTrue(idmapd.idmapExists(overlayPath, USER));
|
||||
|
||||
DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
|
||||
assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigSignaturePolicyNoRefPkg() {
|
||||
installNewPackage(target(TARGET), USER);
|
||||
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
|
||||
|
||||
final DummyIdmapDaemon idmapd = getIdmapd();
|
||||
final DummyDeviceState state = getState();
|
||||
String overlayPath = state.select(OVERLAY, USER).apkPath;
|
||||
assertTrue(idmapd.idmapExists(overlayPath, USER));
|
||||
|
||||
DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
|
||||
assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfigSignaturePolicyRefPkgNotSystem() {
|
||||
setConfigSignaturePackageName(CONFIG_SIGNATURE_REFERENCE_PKG);
|
||||
reinitializeImpl();
|
||||
|
||||
addPackage(app(CONFIG_SIGNATURE_REFERENCE_PKG).setCertificate(CERT_CONFIG_OK), USER);
|
||||
installNewPackage(target(TARGET), USER);
|
||||
installNewPackage(overlay(OVERLAY, TARGET).setCertificate(CERT_CONFIG_NOK), USER);
|
||||
|
||||
final DummyIdmapDaemon idmapd = getIdmapd();
|
||||
final DummyDeviceState state = getState();
|
||||
String overlayPath = state.select(OVERLAY, USER).apkPath;
|
||||
assertTrue(idmapd.idmapExists(overlayPath, USER));
|
||||
|
||||
DummyIdmapDaemon.IdmapHeader idmap = idmapd.getIdmap(overlayPath);
|
||||
assertTrue((CONFIG_SIGNATURE & idmap.policies) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.content.om.OverlayInfo.State;
|
||||
import android.content.om.OverlayableInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
|
||||
@@ -52,6 +53,7 @@ class OverlayManagerServiceImplTestsBase {
|
||||
private DummyPackageManagerHelper mPackageManager;
|
||||
private DummyIdmapDaemon mIdmapDaemon;
|
||||
private OverlayConfig mOverlayConfig;
|
||||
private String mConfigSignaturePackageName;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
@@ -83,6 +85,18 @@ class OverlayManagerServiceImplTestsBase {
|
||||
return mListener;
|
||||
}
|
||||
|
||||
DummyIdmapDaemon getIdmapd() {
|
||||
return mIdmapDaemon;
|
||||
}
|
||||
|
||||
DummyDeviceState getState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
void setConfigSignaturePackageName(String packageName) {
|
||||
mConfigSignaturePackageName = packageName;
|
||||
}
|
||||
|
||||
void assertState(@State int expected, final String overlayPackageName, int userId) {
|
||||
final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId);
|
||||
if (info == null) {
|
||||
@@ -102,9 +116,14 @@ class OverlayManagerServiceImplTestsBase {
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
DummyDeviceState.PackageBuilder app(String packageName) {
|
||||
return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
|
||||
null /* targetOverlayableName */, "data");
|
||||
}
|
||||
|
||||
DummyDeviceState.PackageBuilder target(String packageName) {
|
||||
return new DummyDeviceState.PackageBuilder(packageName, null /* targetPackageName */,
|
||||
null /* targetOverlayableName */);
|
||||
null /* targetOverlayableName */, "");
|
||||
}
|
||||
|
||||
DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName) {
|
||||
@@ -114,10 +133,10 @@ class OverlayManagerServiceImplTestsBase {
|
||||
DummyDeviceState.PackageBuilder overlay(String packageName, String targetPackageName,
|
||||
String targetOverlayableName) {
|
||||
return new DummyDeviceState.PackageBuilder(packageName, targetPackageName,
|
||||
targetOverlayableName);
|
||||
targetOverlayableName, "");
|
||||
}
|
||||
|
||||
void addSystemPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
|
||||
void addPackage(DummyDeviceState.PackageBuilder pkg, int userId) {
|
||||
mState.add(pkg, userId);
|
||||
}
|
||||
|
||||
@@ -242,15 +261,17 @@ class OverlayManagerServiceImplTestsBase {
|
||||
private String packageName;
|
||||
private String targetPackage;
|
||||
private String certificate = "[default]";
|
||||
private String partition;
|
||||
private int version = 0;
|
||||
private ArrayList<String> overlayableNames = new ArrayList<>();
|
||||
private String targetOverlayableName;
|
||||
|
||||
private PackageBuilder(String packageName, String targetPackage,
|
||||
String targetOverlayableName) {
|
||||
String targetOverlayableName, String partition) {
|
||||
this.packageName = packageName;
|
||||
this.targetPackage = targetPackage;
|
||||
this.targetOverlayableName = targetOverlayableName;
|
||||
this.partition = partition;
|
||||
}
|
||||
|
||||
PackageBuilder setCertificate(String certificate) {
|
||||
@@ -269,9 +290,19 @@ class OverlayManagerServiceImplTestsBase {
|
||||
}
|
||||
|
||||
Package build() {
|
||||
final String apkPath = String.format("%s/%s/base.apk",
|
||||
targetPackage == null ? "/system/app/:" : "/vendor/overlay/:",
|
||||
packageName);
|
||||
String path = "";
|
||||
if (TextUtils.isEmpty(partition)) {
|
||||
if (targetPackage == null) {
|
||||
path = "/system/app";
|
||||
} else {
|
||||
path = "/vendor/overlay";
|
||||
}
|
||||
} else {
|
||||
String type = targetPackage == null ? "app" : "overlay";
|
||||
path = String.format("%s/%s", partition, type);
|
||||
}
|
||||
|
||||
final String apkPath = String.format("%s/%s/base.apk", path, packageName);
|
||||
final Package newPackage = new Package(packageName, targetPackage,
|
||||
targetOverlayableName, version, apkPath, certificate);
|
||||
newPackage.overlayableNames.addAll(overlayableNames);
|
||||
@@ -302,8 +333,7 @@ class OverlayManagerServiceImplTestsBase {
|
||||
}
|
||||
}
|
||||
|
||||
static final class DummyPackageManagerHelper implements PackageManagerHelper,
|
||||
OverlayableInfoCallback {
|
||||
final class DummyPackageManagerHelper implements PackageManagerHelper {
|
||||
private final DummyDeviceState mState;
|
||||
|
||||
private DummyPackageManagerHelper(DummyDeviceState state) {
|
||||
@@ -343,6 +373,11 @@ class OverlayManagerServiceImplTestsBase {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull String getConfigSignaturePackage() {
|
||||
return mConfigSignaturePackageName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public OverlayableInfo getOverlayableForTarget(@NonNull String packageName,
|
||||
|
||||
@@ -168,6 +168,7 @@ message OverlayableItem {
|
||||
ODM = 6;
|
||||
OEM = 7;
|
||||
ACTOR = 8;
|
||||
CONFIG_SIGNATURE = 9;
|
||||
}
|
||||
|
||||
// The location of the <item> declaration in source.
|
||||
|
||||
@@ -776,6 +776,7 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
|
||||
OverlayableItem overlayable_item_three(group_one);
|
||||
overlayable_item_three.policies |= PolicyFlags::SIGNATURE;
|
||||
overlayable_item_three.policies |= PolicyFlags::ACTOR_SIGNATURE;
|
||||
overlayable_item_three.policies |= PolicyFlags::CONFIG_SIGNATURE;
|
||||
|
||||
std::unique_ptr<ResourceTable> table =
|
||||
test::ResourceTableBuilder()
|
||||
@@ -830,7 +831,8 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayable) {
|
||||
EXPECT_EQ(result_overlayable.overlayable->name, "OtherName");
|
||||
EXPECT_EQ(result_overlayable.overlayable->actor, "overlay://customization");
|
||||
EXPECT_EQ(result_overlayable.policies, PolicyFlags::SIGNATURE
|
||||
| PolicyFlags::ACTOR_SIGNATURE);
|
||||
| PolicyFlags::ACTOR_SIGNATURE
|
||||
| PolicyFlags::CONFIG_SIGNATURE);
|
||||
}
|
||||
|
||||
TEST_F(TableFlattenerTest, FlattenOverlayableNoPolicyFails) {
|
||||
|
||||
@@ -404,6 +404,9 @@ bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable,
|
||||
case pb::OverlayableItem::ACTOR:
|
||||
out_overlayable->policies |= PolicyFlags::ACTOR_SIGNATURE;
|
||||
break;
|
||||
case pb::OverlayableItem::CONFIG_SIGNATURE:
|
||||
out_overlayable->policies |= PolicyFlags::CONFIG_SIGNATURE;
|
||||
break;
|
||||
default:
|
||||
*out_error = "unknown overlayable policy";
|
||||
return false;
|
||||
|
||||
@@ -325,6 +325,9 @@ static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item
|
||||
if (overlayable_item.policies & PolicyFlags::ACTOR_SIGNATURE) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::ACTOR);
|
||||
}
|
||||
if (overlayable_item.policies & PolicyFlags::CONFIG_SIGNATURE) {
|
||||
pb_overlayable_item->add_policy(pb::OverlayableItem::CONFIG_SIGNATURE);
|
||||
}
|
||||
|
||||
if (source_pool != nullptr) {
|
||||
SerializeSourceToPb(overlayable_item.source, source_pool,
|
||||
|
||||
Reference in New Issue
Block a user