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

Commit 2e295314 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Enforce the overlayable mechanism for self-targeting"

parents 39f3eae9 a8fc0153
Loading
Loading
Loading
Loading
+45 −10
Original line number Diff line number Diff line
@@ -38,9 +38,10 @@ namespace android::self_targeting {
constexpr const mode_t kIdmapFilePermission = S_IRUSR | S_IWUSR;  // u=rw-, g=---, o=---

extern "C" bool
CreateFrroFile(std::string& out_err_result, std::string& packageName, std::string& overlayName,
               std::string& targetPackageName, std::optional<std::string>& targetOverlayable,
               std::vector<FabricatedOverlayEntryParameters>& entries_params,
CreateFrroFile(std::string& out_err_result, const std::string& packageName,
               const std::string& overlayName, const std::string& targetPackageName,
               const std::optional<std::string>& targetOverlayable,
               const std::vector<FabricatedOverlayEntryParameters>& entries_params,
               const std::string& frro_file_path) {
    android::idmap2::FabricatedOverlay::Builder builder(packageName, overlayName,
                                                        targetPackageName);
@@ -90,9 +91,46 @@ CreateFrroFile(std::string& out_err_result, std::string& packageName, std::strin
    return true;
}

static PolicyBitmask GetFulfilledPolicy(const bool isSystem, const bool isVendor,
                                        const bool isProduct, const bool isTargetSignature,
                                        const bool isOdm, const bool isOem) {
    auto fulfilled_policy = static_cast<PolicyBitmask>(PolicyFlags::PUBLIC);

    if (isSystem) {
        fulfilled_policy |= PolicyFlags::SYSTEM_PARTITION;
    }
    if (isVendor) {
        fulfilled_policy |= PolicyFlags::VENDOR_PARTITION;
    }
    if (isProduct) {
        fulfilled_policy |= PolicyFlags::PRODUCT_PARTITION;
    }
    if (isOdm) {
        fulfilled_policy |= PolicyFlags::ODM_PARTITION;
    }
    if (isOem) {
        fulfilled_policy |= PolicyFlags::OEM_PARTITION;
    }
    if (isTargetSignature) {
        fulfilled_policy |= PolicyFlags::SIGNATURE;
    }

    // Not support actor_signature and config_overlay_signature
    fulfilled_policy &=
            ~(PolicyFlags::ACTOR_SIGNATURE | PolicyFlags::CONFIG_SIGNATURE);

    ALOGV(
            "fulfilled_policy = 0x%08x, isSystem = %d, isVendor = %d, isProduct = %d,"
            " isTargetSignature = %d, isOdm = %d, isOem = %d,",
            fulfilled_policy, isSystem, isVendor, isProduct, isTargetSignature, isOdm, isOem);
    return fulfilled_policy;
}

extern "C" bool
CreateIdmapFile(std::string& out_err, const std::string& targetPath, const std::string& overlayPath,
                const std::string& idmapPath, const std::string& overlayName) {
                const std::string& idmapPath, const std::string& overlayName,
                const bool isSystem, const bool isVendor, const bool isProduct,
                const bool isTargetSignature, const bool isOdm, const bool isOem) {
    // idmap files are mapped with mmap in libandroidfw. Deleting and recreating the idmap
    // guarantees that existing memory maps will continue to be valid and unaffected. The file must
    // be deleted before attempting to create the idmap, so that if idmap  creation fails, the
@@ -114,14 +152,11 @@ CreateIdmapFile(std::string& out_err, const std::string& targetPath, const std::
    }

    // Overlay self target process. Only allow self-targeting types.
    const auto fulfilled_policies = static_cast<PolicyBitmask>(
            PolicyFlags::PUBLIC | PolicyFlags::SYSTEM_PARTITION | PolicyFlags::VENDOR_PARTITION |
            PolicyFlags::PRODUCT_PARTITION | PolicyFlags::SIGNATURE | PolicyFlags::ODM_PARTITION |
            PolicyFlags::OEM_PARTITION | PolicyFlags::ACTOR_SIGNATURE |
            PolicyFlags::CONFIG_SIGNATURE);
    const auto fulfilled_policies = GetFulfilledPolicy(isSystem, isVendor, isProduct,
                                                       isTargetSignature, isOdm, isOem);

    const auto idmap = Idmap::FromContainers(**target, **overlay, overlayName,
                                             fulfilled_policies, false /* enforce_overlayable */);
                                             fulfilled_policies, true /* enforce_overlayable */);
    if (!idmap) {
        out_err = base::StringPrintf("Failed to create idmap because of %s",
                                     idmap.GetErrorMessage().c_str());
+34 −2
Original line number Diff line number Diff line
@@ -170,6 +170,16 @@ public class OverlayManagerImpl {
        mBasePath = baseFile.toPath();
    }

    private boolean isSameWithTargetSignature(final String targetPackage) {
        final PackageManager packageManager = mContext.getPackageManager();
        final String packageName = mContext.getPackageName();
        if (TextUtils.equals(packageName, targetPackage)) {
            return true;
        }
        return packageManager.checkSignatures(packageName, targetPackage)
                == PackageManager.SIGNATURE_MATCH;
    }

    /**
     * Check if the overlay name is valid or not.
     *
@@ -202,6 +212,9 @@ public class OverlayManagerImpl {
    /**
     * Save FabricatedOverlay instance as frro and idmap files.
     *
     * <p>In order to fill the overlayable policy, it's necessary to collect the information from
     * app. And then, the information is passed to native layer to fill the overlayable policy
     *
     * @param overlayInternal the FabricatedOverlayInternal to be saved.
     */
    public void registerFabricatedOverlay(@NonNull FabricatedOverlayInternal overlayInternal)
@@ -214,6 +227,9 @@ public class OverlayManagerImpl {
        final String overlayName = checkOverlayNameValid(overlayInternal.overlayName);
        checkPackageName(overlayInternal.packageName);
        checkPackageName(overlayInternal.targetPackageName);
        Preconditions.checkStringNotEmpty(
                overlayInternal.targetOverlayable,
                "Target overlayable should be neither null nor empty string.");

        final ApplicationInfo applicationInfo = mContext.getApplicationInfo();
        final String targetPackage = Preconditions.checkStringNotEmpty(
@@ -223,7 +239,17 @@ public class OverlayManagerImpl {

        createFrroFile(frroPath.toString(), overlayInternal);
        try {
            createIdmapFile(targetPackage, frroPath.toString(), idmapPath.toString(), overlayName);
            createIdmapFile(
                    targetPackage,
                    frroPath.toString(),
                    idmapPath.toString(),
                    overlayName,
                    applicationInfo.isSystemApp() || applicationInfo.isSystemExt() /* isSystem */,
                    applicationInfo.isVendor(),
                    applicationInfo.isProduct(),
                    isSameWithTargetSignature(overlayInternal.targetPackageName),
                    applicationInfo.isOdm(),
                    applicationInfo.isOem());
        } catch (IOException e) {
            if (!frroPath.toFile().delete()) {
                Log.w(TAG, "Failed to delete file " + frroPath);
@@ -315,7 +341,13 @@ public class OverlayManagerImpl {
            @NonNull String targetPath,
            @NonNull String overlayPath,
            @NonNull String idmapPath,
            @NonNull String overlayName)
            @NonNull String overlayName,
            boolean isSystem,
            boolean isVendor,
            boolean isProduct,
            boolean isSameWithTargetSignature,
            boolean isOdm,
            boolean isOem)
            throws IOException;

    private static native FabricatedOverlayInfo getFabricatedOverlayInfo(
+18 −6
Original line number Diff line number Diff line
@@ -123,8 +123,12 @@ public:

    bool callCreateIdmapFile(std::string& out_error, const std::string& targetPath,
                             const std::string& overlayPath, const std::string& idmapPath,
                             const std::string& overlayName) {
        return createIdmapFileFuncPtr_(out_error, targetPath, overlayPath, idmapPath, overlayName);
                             const std::string& overlayName, const bool isSystem,
                             const bool isVendor, const bool isProduct,
                             const bool isTargetSignature, const bool isOdm, const bool isOem) {
        return createIdmapFileFuncPtr_(out_error, targetPath, overlayPath, idmapPath, overlayName,
                                       isSystem, isVendor, isProduct, isTargetSignature, isOdm,
                                       isOem);
    }

    bool callGetFabricatedOverlayInfo(std::string& out_error, const std::string& overlay_path,
@@ -158,7 +162,10 @@ private:
    typedef bool (*CreateIdmapFileFunc)(std::string& out_error, const std::string& targetPath,
                                        const std::string& overlayPath,
                                        const std::string& idmapPath,
                                        const std::string& overlayName);
                                        const std::string& overlayName, const jboolean isSystem,
                                        const jboolean isVendor, const jboolean isProduct,
                                        const jboolean isSameWithTargetSignature,
                                        const jboolean isOdm, const jboolean isOem);

    typedef bool (*GetFabricatedOverlayInfoFunc)(std::string& out_error,
                                                 const std::string& overlay_path,
@@ -295,7 +302,9 @@ static void CreateFrroFile(JNIEnv* env, jclass /*clazz*/, jstring jsFrroFilePath
}

static void CreateIdmapFile(JNIEnv* env, jclass /* clazz */, jstring jsTargetPath,
                            jstring jsOverlayPath, jstring jsIdmapPath, jstring jsOverlayName) {
                            jstring jsOverlayPath, jstring jsIdmapPath, jstring jsOverlayName,
                            jboolean isSystem, jboolean isVendor, jboolean isProduct,
                            jboolean isTargetSignature, jboolean isOdm, jboolean isOem) {
    DynamicLibraryLoader& dlLoader = EnsureDynamicLibraryLoader(env);
    if (!dlLoader) {
        jniThrowNullPointerException(env, "libidmap2 is not loaded");
@@ -327,7 +336,10 @@ static void CreateIdmapFile(JNIEnv* env, jclass /* clazz */, jstring jsTargetPat

    std::string err_result;
    if (!dlLoader.callCreateIdmapFile(err_result, targetPath.c_str(), overlayPath.c_str(),
                                      idmapPath.c_str(), overlayName.c_str())) {
                                      idmapPath.c_str(), overlayName.c_str(),
                                      (isSystem == JNI_TRUE), (isVendor == JNI_TRUE),
                                      (isProduct == JNI_TRUE), (isTargetSignature == JNI_TRUE),
                                      (isOdm == JNI_TRUE), (isOem == JNI_TRUE))) {
        jniThrowException(env, kIOException, err_result.c_str());
        return;
    }
@@ -374,7 +386,7 @@ static const JNINativeMethod gOverlayManagerMethods[] = {
        {"createFrroFile", "(Ljava/lang/String;Landroid/os/FabricatedOverlayInternal;)V",
         reinterpret_cast<void*>(self_targeting::CreateFrroFile)},
        {"createIdmapFile",
         "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
         "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZZZZ)V",
         reinterpret_cast<void*>(self_targeting::CreateIdmapFile)},
        {"getFabricatedOverlayInfo", "(Ljava/lang/String;)Landroid/os/FabricatedOverlayInfo;",
         reinterpret_cast<void*>(self_targeting::GetFabricatedOverlayInfo)},
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ android_test {
        "androidx.test.rules",
        "androidx.test.runner",
        "androidx.test.ext.junit",
        "mockito-target-minus-junit4",
        "truth-prebuilt",
    ],

+84 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?><!--
  ~ Copyright (C) 2022 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.
  -->

<resources>
    <overlayable name="PublicOverlayable" actor="overlay://theme">
        <!-- The app with the same signature can overlay the below resources -->
        <policy type="public">
            <item type="color" name="public_overlayable_color" />
        </policy>
    </overlayable>

    <overlayable name="SignatureOverlayable" actor="overlay://theme">
        <!-- The app with the same signature can overlay the below resources -->
        <policy type="signature">
            <item type="color" name="mycolor" />
            <item type="color" name="signature_overlayable_color" />
            <item type="string" name="mystring" />
            <item type="drawable" name="mydrawable" />
        </policy>
    </overlayable>

    <overlayable name="SystemAppOverlayable" actor="overlay://theme">
        <!-- The app in system partition can overlay the below resources -->
        <policy type="system">
            <item type="color" name="system_app_overlayable_color" />
        </policy>
    </overlayable>

    <overlayable name="OdmOverlayable" actor="overlay://theme">
        <!-- The app with the same signature can overlay the below resources -->
        <policy type="odm">
            <item type="color" name="odm_overlayable_color" />
        </policy>
    </overlayable>

    <overlayable name="OemOverlayable" actor="overlay://theme">
        <!-- The app with the same signature can overlay the below resources -->
        <policy type="oem">
            <item type="color" name="oem_overlayable_color" />
        </policy>
    </overlayable>

    <overlayable name="VendorOverlayable" actor="overlay://theme">
        <!-- The app with the same signature can overlay the below resources -->
        <policy type="vendor">
            <item type="color" name="vendor_overlayable_color" />
        </policy>
    </overlayable>

    <overlayable name="ProductOverlayable" actor="overlay://theme">
        <!-- The app with the same signature can overlay the below resources -->
        <policy type="product">
            <item type="color" name="product_overlayable_color" />
        </policy>
    </overlayable>

    <overlayable name="ActorOverlayable" actor="overlay://theme">
        <!-- The app with the same signature can overlay the below resources -->
        <policy type="actor">
            <item type="color" name="actor_overlayable_color" />
        </policy>
    </overlayable>

    <overlayable name="ConfigOverlayable" actor="overlay://theme">
        <!-- The app with the same signature can overlay the below resources -->
        <policy type="config_signature">
            <item type="color" name="config_overlayable_color" />
        </policy>
    </overlayable>

</resources>
Loading