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:
Zoran Jovanovic
2020-06-09 18:51:57 +02:00
committed by Ryan Mitchell
parent 936849dd1a
commit 9336d9e13b
38 changed files with 414 additions and 174 deletions

View File

@@ -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;
}

View File

@@ -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>({})

View File

@@ -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},

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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}

View File

@@ -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()
}

View File

@@ -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")));

View File

@@ -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);
}
}

View File

@@ -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,

View File

@@ -168,6 +168,7 @@ message OverlayableItem {
ODM = 6;
OEM = 7;
ACTOR = 8;
CONFIG_SIGNATURE = 9;
}
// The location of the <item> declaration in source.

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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,