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

Commit b04a16d7 authored by Ryan Mitchell's avatar Ryan Mitchell Committed by Automerger Merge Worker
Browse files

Merge "Persist implicit overlay configurator actor policy" into rvc-dev am: 41b850d0

Change-Id: I9337e44ed7c662d26e0518cca1f93e00d2952e71
parents 23383e30 41b850d0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -61,7 +61,8 @@ 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::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.
+15 −55
Original line number Diff line number Diff line
@@ -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
// 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.
// 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, 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
+8 −22
Original line number Diff line number Diff line
@@ -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) {
+24 −12
Original line number Diff line number Diff line
@@ -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<PackageInfo> getOverlayPackages(final int userId) {
            final List<PackageInfo> overlays = mPackageManagerInternal.getOverlayPackages(userId);
+28 −2
Original line number Diff line number Diff line
@@ -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) {
Loading