From af93f5de66f09797345d2171306c9de2951bf85c Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 26 May 2020 14:29:03 -0700 Subject: [PATCH] Persist implicit overlay configurator actor policy This change does three things: 1) If an overlay targets a package that does not declare an overlayable and the overlay fulfills the actor policy, the overlay can override any resource in the target, 2) The actor policy is now implicitly granted to overlays signed with the same signature as the configurator that target white-listed target packages regardless of whether or not the target defines an overlayable. 3) If an overlay was previously granted the actor policy through the mechanism specified in (2), the overlay will continue to fulfill the actor policy even if the configurator is removed, changes signature, changes to a different package, or the list of configurator targets changes. If the overlay target package or target overlayable name changes, the persisted setting will be reset. Bug: 157244814 Bug: 157266239 Test: atest OverlayManagerServiceImplTests Test: idmap2_tests Change-Id: Iff3937849ad898b1b2d74c2c632a4cdf7690fe10 --- cmds/idmap2/libidmap2/ResourceMapping.cpp | 3 +- cmds/idmap2/tests/ResourceMappingTests.cpp | 68 ++-------- .../com/android/server/om/IdmapManager.java | 30 ++--- .../server/om/OverlayManagerService.java | 36 +++-- .../server/om/OverlayManagerServiceImpl.java | 30 ++++- .../server/om/OverlayManagerSettings.java | 74 ++++++++-- .../server/om/OverlayableInfoCallback.java | 20 --- .../om/OverlayManagerServiceImplTests.java | 127 +++++++++++++++--- .../OverlayManagerServiceImplTestsBase.java | 45 +++---- .../om/OverlayManagerSettingsTests.java | 4 +- 10 files changed, 269 insertions(+), 168 deletions(-) diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index f82c8f1af7139..44acbcaf8ace2 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -61,7 +61,8 @@ Result 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::ACTOR_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. diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index de039f440e33f..5754eaf078a98 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -287,66 +287,26 @@ TEST(ResourceMappingTests, ResourcesFromApkAssetsNoDefinedOverlayableAndNoTarget R::overlay::string::str4, false /* rewrite */)); } -// Overlays that are neither pre-installed nor signed with the same signature as the target cannot + +// Overlays that are pre-installed or are signed with the same signature as the target/actor can // overlay packages that have not defined overlayable resources. -TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPoliciesPublicFail) { - auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk", - "/overlay/overlay-no-name.apk", PolicyFlags::PUBLIC, - /* enforce_overlayable */ true); - - ASSERT_TRUE(resources) << resources.GetErrorMessage(); - 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. TEST(ResourceMappingTests, ResourcesFromApkAssetsDefaultPolicies) { - auto CheckEntries = [&](const PolicyBitmask& fulfilled_policies) -> void { + constexpr PolicyBitmask kDefaultPolicies = + PolicyFlags::SIGNATURE | PolicyFlags::ACTOR_SIGNATURE | PolicyFlags::PRODUCT_PARTITION | + PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION | PolicyFlags::ODM_PARTITION | + PolicyFlags::OEM_PARTITION; + + for (PolicyBitmask policy = 1U << (sizeof(PolicyBitmask) * 8 - 1); policy > 0; + policy = policy >> 1U) { auto resources = TestGetResourceMapping("/target/target-no-overlayable.apk", "/system-overlay-invalid/system-overlay-invalid.apk", - fulfilled_policies, - /* enforce_overlayable */ true); - + policy, /* enforce_overlayable */ true); ASSERT_TRUE(resources) << resources.GetErrorMessage(); - auto& res = *resources; - ASSERT_EQ(resources->GetTargetToOverlayMap().size(), 10U); - ASSERT_RESULT(MappingExists(res, R::target::string::not_overlayable, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::not_overlayable, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::other, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::other, false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_actor, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_actor, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_odm, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_odm, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_oem, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_oem, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_product, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_product, - false /* rewrite */)); - 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_signature, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_signature, - false /* rewrite */)); - ASSERT_RESULT(MappingExists(res, R::target::string::policy_system, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_system, - false /* rewrite */)); - ASSERT_RESULT(MappingExists( - res, R::target::string::policy_system_vendor, Res_value::TYPE_REFERENCE, - R::system_overlay_invalid::string::policy_system_vendor, false /* rewrite */)); - }; - CheckEntries(PolicyFlags::SIGNATURE); - CheckEntries(PolicyFlags::PRODUCT_PARTITION); - CheckEntries(PolicyFlags::SYSTEM_PARTITION); - CheckEntries(PolicyFlags::VENDOR_PARTITION); - CheckEntries(PolicyFlags::ODM_PARTITION); - CheckEntries(PolicyFlags::OEM_PARTITION); + const size_t expected_overlaid = (policy & kDefaultPolicies) != 0 ? 10U : 0U; + ASSERT_EQ(expected_overlaid, resources->GetTargetToOverlayMap().size()) + << "Incorrect number of resources overlaid through policy " << policy; + } } } // namespace android::idmap2 diff --git a/services/core/java/com/android/server/om/IdmapManager.java b/services/core/java/com/android/server/om/IdmapManager.java index 735d669835208..59735ebb24d29 100644 --- a/services/core/java/com/android/server/om/IdmapManager.java +++ b/services/core/java/com/android/server/om/IdmapManager.java @@ -29,18 +29,15 @@ import android.os.OverlayablePolicy; import android.os.SystemProperties; import android.util.Slog; -import com.android.internal.util.ArrayUtils; - import java.io.IOException; /** * Handle the creation and deletion of idmap files. * - * The actual work is performed by the idmap binary, launched through idmap2d. - * - * Note: this class is subclassed in the OMS unit tests, and hence not marked as final. + * The actual work is performed by idmap2d. + * @see IdmapDaemon */ -class IdmapManager { +final class IdmapManager { private static final boolean VENDOR_IS_Q_OR_LATER; static { final String value = SystemProperties.get("ro.vndk.version", "29"); @@ -57,14 +54,10 @@ class IdmapManager { private final IdmapDaemon mIdmapDaemon; private final OverlayableInfoCallback mOverlayableCallback; - private final String mOverlayableConfigurator; - private final String[] mOverlayableConfiguratorTargets; IdmapManager(final IdmapDaemon idmapDaemon, final OverlayableInfoCallback verifyCallback) { mOverlayableCallback = verifyCallback; mIdmapDaemon = idmapDaemon; - mOverlayableConfigurator = verifyCallback.getOverlayableConfigurator(); - mOverlayableConfiguratorTargets = verifyCallback.getOverlayableConfiguratorTargets() ; } /** @@ -72,7 +65,7 @@ class IdmapManager { * modified. */ boolean createIdmap(@NonNull final PackageInfo targetPackage, - @NonNull final PackageInfo overlayPackage, int userId) { + @NonNull final PackageInfo overlayPackage, int additionalPolicies, int userId) { if (DEBUG) { Slog.d(TAG, "create idmap for " + targetPackage.packageName + " and " + overlayPackage.packageName); @@ -80,13 +73,14 @@ class IdmapManager { final String targetPath = targetPackage.applicationInfo.getBaseCodePath(); final String overlayPath = overlayPackage.applicationInfo.getBaseCodePath(); try { - int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId); boolean enforce = enforceOverlayable(overlayPackage); + int policies = calculateFulfilledPolicies(targetPackage, overlayPackage, userId) + | additionalPolicies; if (mIdmapDaemon.verifyIdmap(targetPath, overlayPath, policies, enforce, userId)) { return false; } - return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies, - enforce, userId) != null; + return mIdmapDaemon.createIdmap(targetPath, overlayPath, policies, enforce, userId) + != null; } catch (Exception e) { Slog.w(TAG, "failed to generate idmap for " + targetPath + " and " + overlayPath + ": " + e.getMessage()); @@ -190,14 +184,6 @@ class IdmapManager { String targetOverlayableName = overlayPackage.targetOverlayableName; if (targetOverlayableName != null) { try { - if (!mOverlayableConfigurator.isEmpty() - && ArrayUtils.contains(mOverlayableConfiguratorTargets, - targetPackage.packageName) - && mOverlayableCallback.signaturesMatching(mOverlayableConfigurator, - overlayPackage.packageName, userId)) { - return true; - } - OverlayableInfo overlayableInfo = mOverlayableCallback.getOverlayableForTarget( targetPackage.packageName, targetOverlayableName, userId); if (overlayableInfo != null && overlayableInfo.actor != null) { diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 086ab81832544..3c5e47625fa29 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -252,7 +252,8 @@ public final class OverlayManagerService extends SystemService { mSettings = new OverlayManagerSettings(); mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings, OverlayConfig.getSystemInstance(), getDefaultOverlayPackages(), - new OverlayChangeListener()); + new OverlayChangeListener(), getOverlayableConfigurator(), + getOverlayableConfiguratorTargets()); mActorEnforcer = new OverlayActorEnforcer(mPackageManager); final IntentFilter packageFilter = new IntentFilter(); @@ -335,6 +336,28 @@ public final class OverlayManagerService extends SystemService { return defaultPackages.toArray(new String[defaultPackages.size()]); } + + /** + * Retrieves the package name that is recognized as an actor for the packages specified by + * {@link #getOverlayableConfiguratorTargets()}. + */ + @Nullable + private String getOverlayableConfigurator() { + return TextUtils.nullIfEmpty(Resources.getSystem() + .getString(R.string.config_overlayableConfigurator)); + } + + /** + * Retrieves the target packages that recognize the {@link #getOverlayableConfigurator} as an + * actor for itself. Overlays targeting one of the specified targets that are signed with the + * same signature as the overlayable configurator will be granted the "actor" policy. + */ + @Nullable + private String[] getOverlayableConfiguratorTargets() { + return Resources.getSystem().getStringArray( + R.array.config_overlayableConfiguratorTargets); + } + private final class PackageReceiver extends BroadcastReceiver { @Override public void onReceive(@NonNull final Context context, @NonNull final Intent intent) { @@ -1120,17 +1143,6 @@ public final class OverlayManagerService extends SystemService { return false; } - @Override - public String getOverlayableConfigurator() { - return Resources.getSystem().getString(R.string.config_overlayableConfigurator); - } - - @Override - public String[] getOverlayableConfiguratorTargets() { - return Resources.getSystem().getStringArray( - R.array.config_overlayableConfiguratorTargets); - } - @Override public List getOverlayPackages(final int userId) { final List overlays = mPackageManagerInternal.getOverlayPackages(userId); diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index 05a4a38feef12..879ad4fdf011e 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -31,6 +31,7 @@ import android.annotation.Nullable; import android.content.om.OverlayInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; +import android.os.OverlayablePolicy; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -73,6 +74,9 @@ final class OverlayManagerServiceImpl { private final String[] mDefaultOverlays; private final OverlayChangeListener mListener; + private final String mOverlayableConfigurator; + private final String[] mOverlayableConfiguratorTargets; + /** * Helper method to merge the overlay manager's (as read from overlays.xml) * and package manager's (as parsed from AndroidManifest.xml files) views @@ -115,13 +119,17 @@ final class OverlayManagerServiceImpl { @NonNull final OverlayManagerSettings settings, @NonNull final OverlayConfig overlayConfig, @NonNull final String[] defaultOverlays, - @NonNull final OverlayChangeListener listener) { + @NonNull final OverlayChangeListener listener, + @Nullable final String overlayableConfigurator, + @Nullable final String[] overlayableConfiguratorTargets) { mPackageManager = packageManager; mIdmapManager = idmapManager; mSettings = settings; mOverlayConfig = overlayConfig; mDefaultOverlays = defaultOverlays; mListener = listener; + mOverlayableConfigurator = overlayableConfigurator; + mOverlayableConfiguratorTargets = overlayableConfiguratorTargets; } /** @@ -706,7 +714,25 @@ final class OverlayManagerServiceImpl { if (targetPackage != null && overlayPackage != null && !("android".equals(targetPackageName) && !isPackageConfiguredMutable(overlayPackageName))) { - modified |= mIdmapManager.createIdmap(targetPackage, overlayPackage, userId); + + int additionalPolicies = 0; + if (TextUtils.nullIfEmpty(mOverlayableConfigurator) != null + && ArrayUtils.contains(mOverlayableConfiguratorTargets, targetPackageName) + && isPackageConfiguredMutable(overlayPackageName) + && mPackageManager.signaturesMatching(mOverlayableConfigurator, + overlayPackageName, userId)) { + // The overlay targets a package that has the overlayable configurator configured as + // its actor. The overlay and this actor are signed with the same signature, so + // the overlay fulfills the actor policy. + modified |= mSettings.setHasConfiguratorActorPolicy(overlayPackageName, userId, + true); + additionalPolicies |= OverlayablePolicy.ACTOR_SIGNATURE; + } else if (mSettings.hasConfiguratorActorPolicy(overlayPackageName, userId)) { + additionalPolicies |= OverlayablePolicy.ACTOR_SIGNATURE; + } + + modified |= mIdmapManager.createIdmap(targetPackage, overlayPackage, additionalPolicies, + userId); } if (overlayPackage != null) { diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java index bdbaf78439a8c..f8226faf13368 100644 --- a/services/core/java/com/android/server/om/OverlayManagerSettings.java +++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java @@ -73,7 +73,7 @@ final class OverlayManagerSettings { remove(packageName, userId); insert(new SettingsItem(packageName, userId, targetPackageName, targetOverlayableName, baseCodePath, OverlayInfo.STATE_UNKNOWN, isEnabled, isMutable, priority, - overlayCategory)); + overlayCategory, false /* hasConfiguratorActorPolicy */)); } /** @@ -160,6 +160,26 @@ final class OverlayManagerSettings { return mItems.get(idx).setState(state); } + boolean hasConfiguratorActorPolicy(@NonNull final String packageName, final int userId) { + final int idx = select(packageName, userId); + if (idx < 0) { + throw new BadKeyException(packageName, userId); + } + return mItems.get(idx).hasConfiguratorActorPolicy(); + } + + /** + * Returns true if the settings were modified, false if they remain the same. + */ + boolean setHasConfiguratorActorPolicy(@NonNull final String packageName, final int userId, + boolean hasPolicy) { + final int idx = select(packageName, userId); + if (idx < 0) { + throw new BadKeyException(packageName, userId); + } + return mItems.get(idx).setHasConfiguratorActorPolicy(hasPolicy); + } + List getOverlaysForTarget(@NonNull final String targetPackageName, final int userId) { // Immutable RROs targeting "android" are loaded from AssetManager, and so they should be @@ -323,16 +343,17 @@ final class OverlayManagerSettings { pw.println(item.mPackageName + ":" + item.getUserId() + " {"); pw.increaseIndent(); - pw.println("mPackageName...........: " + item.mPackageName); - pw.println("mUserId................: " + item.getUserId()); - pw.println("mTargetPackageName.....: " + item.getTargetPackageName()); - pw.println("mTargetOverlayableName.: " + item.getTargetOverlayableName()); - pw.println("mBaseCodePath..........: " + item.getBaseCodePath()); - pw.println("mState.................: " + OverlayInfo.stateToString(item.getState())); - pw.println("mIsEnabled.............: " + item.isEnabled()); - pw.println("mIsMutable.............: " + item.isMutable()); - pw.println("mPriority..............: " + item.mPriority); - pw.println("mCategory..............: " + item.mCategory); + pw.println("mPackageName................: " + item.mPackageName); + pw.println("mUserId.....................: " + item.getUserId()); + pw.println("mTargetPackageName..........: " + item.getTargetPackageName()); + pw.println("mTargetOverlayableName......: " + item.getTargetOverlayableName()); + pw.println("mBaseCodePath...............: " + item.getBaseCodePath()); + pw.println("mState......................: " + OverlayInfo.stateToString(item.getState())); + pw.println("mIsEnabled..................: " + item.isEnabled()); + pw.println("mIsMutable..................: " + item.isMutable()); + pw.println("mPriority...................: " + item.mPriority); + pw.println("mCategory...................: " + item.mCategory); + pw.println("mHasConfiguratorActorPolicy.: " + item.hasConfiguratorActorPolicy()); pw.decreaseIndent(); pw.println("}"); @@ -371,6 +392,9 @@ final class OverlayManagerSettings { case "category": pw.println(item.mCategory); break; + case "hasconfiguratoractorpolicy": + pw.println(item.mHasConfiguratorActorPolicy); + break; } } @@ -398,9 +422,11 @@ final class OverlayManagerSettings { private static final String ATTR_CATEGORY = "category"; private static final String ATTR_USER_ID = "userId"; private static final String ATTR_VERSION = "version"; + private static final String ATTR_HAS_CONFIGURATOR_ACTOR_POLICY = + "hasConfiguratorActorPolicy"; @VisibleForTesting - static final int CURRENT_VERSION = 3; + static final int CURRENT_VERSION = 4; public static void restore(@NonNull final ArrayList table, @NonNull final InputStream is) throws IOException, XmlPullParserException { @@ -454,9 +480,12 @@ final class OverlayManagerSettings { final boolean isStatic = XmlUtils.readBooleanAttribute(parser, ATTR_IS_STATIC); final int priority = XmlUtils.readIntAttribute(parser, ATTR_PRIORITY); final String category = XmlUtils.readStringAttribute(parser, ATTR_CATEGORY); + final boolean hasConfiguratorActorPolicy = XmlUtils.readBooleanAttribute(parser, + ATTR_HAS_CONFIGURATOR_ACTOR_POLICY); return new SettingsItem(packageName, userId, targetPackageName, targetOverlayableName, - baseCodePath, state, isEnabled, !isStatic, priority, category); + baseCodePath, state, isEnabled, !isStatic, priority, category, + hasConfiguratorActorPolicy); } public static void persist(@NonNull final ArrayList table, @@ -491,6 +520,8 @@ final class OverlayManagerSettings { XmlUtils.writeBooleanAttribute(xml, ATTR_IS_STATIC, !item.mIsMutable); XmlUtils.writeIntAttribute(xml, ATTR_PRIORITY, item.mPriority); XmlUtils.writeStringAttribute(xml, ATTR_CATEGORY, item.mCategory); + XmlUtils.writeBooleanAttribute(xml, ATTR_HAS_CONFIGURATOR_ACTOR_POLICY, + item.mHasConfiguratorActorPolicy); xml.endTag(null, TAG_ITEM); } } @@ -507,12 +538,14 @@ final class OverlayManagerSettings { private boolean mIsMutable; private int mPriority; private String mCategory; + private boolean mHasConfiguratorActorPolicy; SettingsItem(@NonNull final String packageName, final int userId, @NonNull final String targetPackageName, @Nullable final String targetOverlayableName, @NonNull final String baseCodePath, final @OverlayInfo.State int state, final boolean isEnabled, - final boolean isMutable, final int priority, @Nullable String category) { + final boolean isMutable, final int priority, @Nullable String category, + final boolean hasConfiguratorActorPolicy) { mPackageName = packageName; mUserId = userId; mTargetPackageName = targetPackageName; @@ -524,6 +557,7 @@ final class OverlayManagerSettings { mCache = null; mIsMutable = isMutable; mPriority = priority; + mHasConfiguratorActorPolicy = hasConfiguratorActorPolicy; } private String getTargetPackageName() { @@ -614,6 +648,18 @@ final class OverlayManagerSettings { private int getPriority() { return mPriority; } + + private boolean hasConfiguratorActorPolicy() { + return mHasConfiguratorActorPolicy; + } + + private boolean setHasConfiguratorActorPolicy(boolean hasPolicy) { + if (mHasConfiguratorActorPolicy != hasPolicy) { + mHasConfiguratorActorPolicy = hasPolicy; + return true; + } + return false; + } } private int select(@NonNull final String packageName, final int userId) { diff --git a/services/core/java/com/android/server/om/OverlayableInfoCallback.java b/services/core/java/com/android/server/om/OverlayableInfoCallback.java index 41c341adf1bc0..5066ecdd6316f 100644 --- a/services/core/java/com/android/server/om/OverlayableInfoCallback.java +++ b/services/core/java/com/android/server/om/OverlayableInfoCallback.java @@ -80,24 +80,4 @@ public interface OverlayableInfoCallback { * in the system returns {@link PackageManager#SIGNATURE_MATCH} */ boolean signaturesMatching(@NonNull String pkgName1, @NonNull String pkgName2, int userId); - - /** - * Retrieves the package name that is recognized as an actor for the packages specified by - * {@link #getOverlayableConfiguratorTargets()}. - */ - @NonNull - default String getOverlayableConfigurator() { - return ""; - } - - /** - * Retrieves the target packages that recognize the {@link #getOverlayableConfigurator} as an - * actor for its overlayable declarations. Overlays targeting one of the specified targets that - * are signed with the same signature as the overlayable configurator will be granted the - * "actor" policy. - */ - @NonNull - default String[] getOverlayableConfiguratorTargets() { - return new String[0]; - } } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java index b25af05438294..8774ab020202d 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java @@ -208,45 +208,134 @@ public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTes @Test public void testConfigurator() { - final DummyPackageManagerHelper packageManager = getPackageManager(); - packageManager.overlayableConfigurator = "actor"; - packageManager.overlayableConfiguratorTargets = new String[]{TARGET}; + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; reinitializeImpl(); installNewPackage(target("actor").setCertificate("one"), USER); - installNewPackage(target(TARGET) - .addOverlayable("TestResources") - .setCertificate("two"), USER); + installNewPackage(target(TARGET).addOverlayable("TestResources").setCertificate("two"), + USER); - final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") .setCertificate("one"); installNewPackage(overlay, USER); - final DummyIdmapDaemon idmapDaemon = getIdmapDaemon(); - final DummyIdmapDaemon.IdmapHeader idmap = idmapDaemon.getIdmap(overlay.build().apkPath); + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); assertNotNull(idmap); assertEquals(OverlayablePolicy.ACTOR_SIGNATURE, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); } @Test - public void testConfiguratorDifferentSignatures() { - final DummyPackageManagerHelper packageManager = getPackageManager(); - packageManager.overlayableConfigurator = "actor"; - packageManager.overlayableConfiguratorTargets = new String[]{TARGET}; + public void testConfiguratorWithoutOverlayable() { + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; reinitializeImpl(); installNewPackage(target("actor").setCertificate("one"), USER); - installNewPackage(target(TARGET) - .addOverlayable("TestResources") - .setCertificate("two"), USER); + installNewPackage(target(TARGET).setCertificate("two"), USER); - final DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET).setCertificate("one"); + installNewPackage(overlay, USER); + + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(OverlayablePolicy.ACTOR_SIGNATURE, + idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + } + + @Test + public void testConfiguratorDifferentTargets() { + // The target package is not listed in the configurator target list, so the actor policy + // should not be granted. + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{"somethingElse"}; + reinitializeImpl(); + + installNewPackage(target("actor").setCertificate("one"), USER); + installNewPackage(target(TARGET).setCertificate("two"), USER); + + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET).setCertificate("one"); + installNewPackage(overlay, USER); + + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + } + + @Test + public void testConfiguratorDifferentSignatures() { + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; + reinitializeImpl(); + + installNewPackage(target("actor").setCertificate("one"), USER); + installNewPackage(target(TARGET).addOverlayable("TestResources").setCertificate("two"), + USER); + + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") .setCertificate("two"); installNewPackage(overlay, USER); - final DummyIdmapDaemon idmapDaemon = getIdmapDaemon(); - final DummyIdmapDaemon.IdmapHeader idmap = idmapDaemon.getIdmap(overlay.build().apkPath); + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + } + + @Test + public void testConfiguratorWithoutOverlayableDifferentSignatures() { + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; + reinitializeImpl(); + + installNewPackage(target("actor").setCertificate("one"), USER); + installNewPackage(target(TARGET).setCertificate("two"), USER); + + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET).setCertificate("two"); + installNewPackage(overlay, USER); + + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + } + + @Test + public void testConfiguratorChanges() { + mOverlayableConfigurator = "actor"; + mOverlayableConfiguratorTargets = new String[]{TARGET}; + reinitializeImpl(); + + installNewPackage(target("actor").setCertificate("one"), USER); + installNewPackage(target(TARGET).addOverlayable("TestResources").setCertificate("two"), + USER); + + DummyDeviceState.PackageBuilder overlay = overlay(OVERLAY, TARGET, "TestResources") + .setCertificate("one"); + installNewPackage(overlay, USER); + + DummyIdmapDaemon.IdmapHeader idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(OverlayablePolicy.ACTOR_SIGNATURE, + idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + + // Change the configurator to a different package. The overlay should still be granted the + // actor policy. + mOverlayableConfigurator = "differentActor"; + OverlayManagerServiceImpl impl = reinitializeImpl(); + impl.updateOverlaysForUser(USER); + + idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); + assertNotNull(idmap); + assertEquals(OverlayablePolicy.ACTOR_SIGNATURE, + idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); + + // Reset the setting persisting that the overlay once fulfilled the actor policy implicitly + // through the configurator. The overlay should lose the actor policy. + impl = reinitializeImpl(); + getSettings().setHasConfiguratorActorPolicy(OVERLAY, USER, false); + impl.updateOverlaysForUser(USER); + + idmap = getIdmapDaemon().getIdmap(overlay.build().apkPath); assertNotNull(idmap); assertEquals(0, idmap.policies & OverlayablePolicy.ACTOR_SIGNATURE); } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java index ec6a48182a252..52a58907ea5a9 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java @@ -42,7 +42,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; /** Base class for creating {@link OverlayManagerServiceImplTests} tests. */ @@ -53,6 +52,9 @@ class OverlayManagerServiceImplTestsBase { private DummyPackageManagerHelper mPackageManager; private DummyIdmapDaemon mIdmapDaemon; private OverlayConfig mOverlayConfig; + private OverlayManagerSettings mSettings; + String mOverlayableConfigurator; + String[] mOverlayableConfiguratorTargets; @Before public void setUp() { @@ -60,20 +62,26 @@ class OverlayManagerServiceImplTestsBase { mListener = new DummyListener(); mPackageManager = new DummyPackageManagerHelper(mState); mIdmapDaemon = new DummyIdmapDaemon(mState); + mSettings = new OverlayManagerSettings(); mOverlayConfig = mock(OverlayConfig.class); when(mOverlayConfig.getPriority(any())).thenReturn(OverlayConfig.DEFAULT_PRIORITY); when(mOverlayConfig.isEnabled(any())).thenReturn(false); when(mOverlayConfig.isMutable(any())).thenReturn(true); + mOverlayableConfigurator = null; + mOverlayableConfiguratorTargets = null; reinitializeImpl(); } - void reinitializeImpl() { + OverlayManagerServiceImpl reinitializeImpl() { mImpl = new OverlayManagerServiceImpl(mPackageManager, new IdmapManager(mIdmapDaemon, mPackageManager), - new OverlayManagerSettings(), + mSettings, mOverlayConfig, new String[0], - mListener); + mListener, + mOverlayableConfigurator, + mOverlayableConfiguratorTargets); + return mImpl; } OverlayManagerServiceImpl getImpl() { @@ -84,14 +92,14 @@ class OverlayManagerServiceImplTestsBase { return mListener; } - DummyPackageManagerHelper getPackageManager() { - return mPackageManager; - } - DummyIdmapDaemon getIdmapDaemon() { return mIdmapDaemon; } + OverlayManagerSettings getSettings() { + return mSettings; + } + void assertState(@State int expected, final String overlayPackageName, int userId) { final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId); if (info == null) { @@ -314,8 +322,6 @@ class OverlayManagerServiceImplTestsBase { static final class DummyPackageManagerHelper implements PackageManagerHelper, OverlayableInfoCallback { private final DummyDeviceState mState; - String[] overlayableConfiguratorTargets = new String[0]; - String overlayableConfigurator = ""; private DummyPackageManagerHelper(DummyDeviceState state) { mState = state; @@ -387,16 +393,6 @@ class OverlayManagerServiceImplTestsBase { public void enforcePermission(String permission, String message) throws SecurityException { throw new UnsupportedOperationException(); } - - @Override - public String[] getOverlayableConfiguratorTargets() { - return overlayableConfiguratorTargets; - } - - @Override - public String getOverlayableConfigurator() { - return overlayableConfigurator; - } } static class DummyIdmapDaemon extends IdmapDaemon { @@ -433,7 +429,8 @@ class OverlayManagerServiceImplTestsBase { if (idmap == null) { return false; } - return idmap.isUpToDate(getCrc(targetPath), getCrc(overlayPath), targetPath); + return idmap.isUpToDate(getCrc(targetPath), getCrc(overlayPath), targetPath, policies, + enforce); } @Override @@ -462,9 +459,11 @@ class OverlayManagerServiceImplTestsBase { } private boolean isUpToDate(int expectedTargetCrc, int expectedOverlayCrc, - String expectedTargetPath) { + String expectedTargetPath, int expectedPolicies, + boolean expectedEnforceOverlayable) { return expectedTargetCrc == targetCrc && expectedOverlayCrc == overlayCrc - && expectedTargetPath.equals(targetPath); + && expectedTargetPath.equals(targetPath) && expectedPolicies == policies + && expectedEnforceOverlayable == enforceOverlayable; } } } diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java index 146f60aff7243..e2cedb5e1a620 100644 --- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java @@ -367,7 +367,8 @@ public class OverlayManagerSettingsTests { + " isEnabled='false'\n" + " category='dummy-category'\n" + " isStatic='false'\n" - + " priority='0' />\n" + + " priority='0'" + + " hasConfiguratorActorPolicy='true' />\n" + "\n"; ByteArrayInputStream is = new ByteArrayInputStream(xml.getBytes("utf-8")); @@ -380,6 +381,7 @@ public class OverlayManagerSettingsTests { assertEquals(1234, oi.userId); assertEquals(STATE_DISABLED, oi.state); assertFalse(mSettings.getEnabled("com.dummy.overlay", 1234)); + assertTrue(mSettings.hasConfiguratorActorPolicy("com.dummy.overlay", 1234)); } @Test