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

Commit b8392d3f authored by Pechetty Sravani (xWF)'s avatar Pechetty Sravani (xWF) Committed by Android (Google) Code Review
Browse files

Merge "Revert "Implement alignment checks in PM"" into main

parents 30a4d8e0 8a34831e
Loading
Loading
Loading
Loading
+0 −53
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import static android.system.OsConstants.S_IXGRP;
import static android.system.OsConstants.S_IXOTH;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.parsing.ApkLiteParseUtils;
import android.content.pm.parsing.PackageLite;
@@ -178,13 +177,6 @@ public class NativeLibraryHelper {
    private native static int nativeCopyNativeBinaries(long handle, String sharedLibraryPath,
            String abiToCopy, boolean extractNativeLibs, boolean debuggable);

    private static native int nativeCheckAlignment(
            long handle,
            String sharedLibraryPath,
            String abi,
            boolean extractNativeLibs,
            boolean debuggable);

    private static long sumNativeBinaries(Handle handle, String abi) {
        long sum = 0;
        for (long apkHandle : handle.apkHandles) {
@@ -440,51 +432,6 @@ public class NativeLibraryHelper {
        }
    }

    /**
     * Checks alignment of APK and native libraries for 16KB device
     *
     * @param handle APK file to scan for native libraries
     * @param libraryRoot directory for libraries
     * @param abiOverride abiOverride for package
     * @return {@link Modes from ApplicationInfo.PageSizeAppCompat} if successful or error code
     *     which suggests undefined mode
     */
    @ApplicationInfo.PageSizeAppCompatFlags
    public static int checkAlignmentForCompatMode(
            Handle handle,
            String libraryRoot,
            boolean nativeLibraryRootRequiresIsa,
            String abiOverride) {
        // Keep the code below in sync with copyNativeBinariesForSupportedAbi
        int abi = findSupportedAbi(handle, Build.SUPPORTED_64_BIT_ABIS);
        if (abi < 0) {
            return ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
        }

        final String supportedAbi = Build.SUPPORTED_64_BIT_ABIS[abi];
        final String instructionSet = VMRuntime.getInstructionSet(supportedAbi);
        String subDir = libraryRoot;
        if (nativeLibraryRootRequiresIsa) {
            subDir += "/" + instructionSet;
        }

        int mode = ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED;
        for (long apkHandle : handle.apkHandles) {
            int res =
                    nativeCheckAlignment(
                            apkHandle,
                            subDir,
                            Build.SUPPORTED_64_BIT_ABIS[abi],
                            handle.extractNativeLibs,
                            handle.debuggable);
            if (res == ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_ERROR) {
                return res;
            }
            mode |= res;
        }
        return mode;
    }

    public static long sumNativeBinariesWithOverride(Handle handle, String abiOverride)
            throws IOException {
        long sum = 0;
+26 −184
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
#include <androidfw/ApkParsing.h>
#include <androidfw/ZipFileRO.h>
#include <androidfw/ZipUtils.h>
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -39,7 +38,6 @@

#include <memory>
#include <string>
#include <vector>

#include "com_android_internal_content_FileSystemUtils.h"
#include "core_jni_helpers.h"
@@ -62,12 +60,6 @@ enum install_status_t {
    NO_NATIVE_LIBRARIES = -114
};

// These code should match with PageSizeAppCompatFlags inside ApplicationInfo.java
constexpr int PAGE_SIZE_APP_COMPAT_FLAG_ERROR = -1;
constexpr int PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED = 0;
constexpr int PAGE_SIZE_APP_COMPAT_FLAG_UNCOMPRESSED_LIBS_NOT_ALIGNED = 1 << 1;
constexpr int PAGE_SIZE_APP_COMPAT_FLAG_ELF_NOT_ALIGNED = 1 << 2;

typedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);

static bool
@@ -532,7 +524,11 @@ static inline bool app_compat_16kb_enabled() {
    static const size_t kPageSize = getpagesize();

    // App compat is only applicable on 16kb-page-size devices.
    return kPageSize == 0x4000;
    if (kPageSize != 0x4000) {
        return false;
    }

    return android::base::GetBoolProperty("bionic.linker.16kb.app_compat.enabled", false);
}

static jint
@@ -630,166 +626,6 @@ com_android_internal_content_NativeLibraryHelper_openApkFd(JNIEnv *env, jclass,
    return reinterpret_cast<jlong>(zipFile);
}

static jint checkLoadSegmentAlignment(const char* fileName, off64_t offset) {
    std::vector<Elf64_Phdr> programHeaders;
    if (!getLoadSegmentPhdrs(fileName, offset, programHeaders)) {
        ALOGE("Failed to read program headers from ELF file.");
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }

    int mode = PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED;
    for (auto programHeader : programHeaders) {
        if (programHeader.p_type != PT_LOAD) {
            continue;
        }

        // Set ELF alignment bit if 4 KB aligned LOAD segment is found
        if (programHeader.p_align == 0x1000) {
            ALOGI("Setting page size compat mode PAGE_SIZE_APP_COMPAT_FLAG_ELF_NOT_ALIGNED");
            mode |= PAGE_SIZE_APP_COMPAT_FLAG_ELF_NOT_ALIGNED;
            break;
        }
    }

    return mode;
}

static jint checkExtractedLibAlignment(ZipFileRO* zipFile, ZipEntryRO zipEntry,
                                       const char* fileName, const std::string nativeLibPath) {
    // Build local file path
    const size_t fileNameLen = strlen(fileName);
    char localFileName[nativeLibPath.size() + fileNameLen + 2];

    if (strlcpy(localFileName, nativeLibPath.c_str(), sizeof(localFileName)) !=
        nativeLibPath.size()) {
        ALOGE("Couldn't allocate local file name for library");
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }

    *(localFileName + nativeLibPath.size()) = '/';

    if (strlcpy(localFileName + nativeLibPath.size() + 1, fileName,
                sizeof(localFileName) - nativeLibPath.size() - 1) != fileNameLen) {
        ALOGE("Couldn't allocate local file name for library");
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }

    struct statfs64 fsInfo;
    int result = statfs64(localFileName, &fsInfo);
    if (result < 0) {
        ALOGE("Failed to stat file :%s", localFileName);
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }

    return checkLoadSegmentAlignment(localFileName, 0);
}

static jint checkAlignment(JNIEnv* env, jstring javaNativeLibPath, jboolean extractNativeLibs,
                           ZipFileRO* zipFile, ZipEntryRO zipEntry, const char* fileName) {
    int mode = PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED;
    // Need two separate install status for APK and ELF alignment
    static const size_t kPageSize = getpagesize();
    jint ret = INSTALL_SUCCEEDED;

    ScopedUtfChars nativeLibPath(env, javaNativeLibPath);
    if (extractNativeLibs) {
        ALOGI("extractNativeLibs specified, checking for extracted lib %s", fileName);
        return checkExtractedLibAlignment(zipFile, zipEntry, fileName, nativeLibPath.c_str());
    }

    uint16_t method;
    off64_t offset;
    if (!zipFile->getEntryInfo(zipEntry, &method, nullptr, nullptr, &offset, nullptr, nullptr,
                               nullptr)) {
        ALOGE("Couldn't read zip entry info from zipFile %s", zipFile->getZipFileName());
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }

    // check if library is uncompressed and page-aligned
    if (method != ZipFileRO::kCompressStored) {
        ALOGE("Library '%s' is compressed - will not be able to open it directly from apk.\n",
              fileName);
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }

    if (offset % kPageSize != 0) {
        ALOGW("Library '%s' is not PAGE(%zu)-aligned - will not be able to open it directly "
              "from apk.\n",
              fileName, kPageSize);
        mode |= PAGE_SIZE_APP_COMPAT_FLAG_UNCOMPRESSED_LIBS_NOT_ALIGNED;
        ALOGI("Setting page size compat mode "
              "PAGE_SIZE_APP_COMPAT_FLAG_UNCOMPRESSED_LIBS_NOT_ALIGNED for %s",
              zipFile->getZipFileName());
    }

    int loadMode = checkLoadSegmentAlignment(zipFile->getZipFileName(), offset);
    if (loadMode == PAGE_SIZE_APP_COMPAT_FLAG_ERROR) {
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }
    mode |= loadMode;
    return mode;
}

// TODO(b/371049373): This function is copy of iterateOverNativeFiles with different way of handling
// and combining return values for all ELF and APKs. Find a way to consolidate two functions.
static jint com_android_internal_content_NativeLibraryHelper_checkApkAlignment(
        JNIEnv* env, jclass clazz, jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi,
        jboolean extractNativeLibs, jboolean debuggable) {
    int mode = PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED;
    ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
    if (zipFile == nullptr) {
        ALOGE("zipfile handle is null");
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }

    auto result = NativeLibrariesIterator::create(zipFile, debuggable);
    if (!result.ok()) {
        ALOGE("Can't iterate over native libs for file:%s", zipFile->getZipFileName());
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }
    std::unique_ptr<NativeLibrariesIterator> it(std::move(result.value()));

    const ScopedUtfChars cpuAbi(env, javaCpuAbi);
    if (cpuAbi.c_str() == nullptr) {
        ALOGE("cpuAbi is nullptr");
        // This would've thrown, so this return code isn't observable by Java.
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }

    while (true) {
        auto next = it->next();
        if (!next.ok()) {
            ALOGE("next iterator not found Error:%d", next.error());
            return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
        }
        auto entry = next.value();
        if (entry == nullptr) {
            break;
        }

        const char* fileName = it->currentEntry();
        const char* lastSlash = it->lastSlash();

        // Check to make sure the CPU ABI of this file is one we support.
        const char* cpuAbiOffset = fileName + APK_LIB_LEN;
        const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;

        if (cpuAbi.size() == cpuAbiRegionSize &&
            !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
            int ret = checkAlignment(env, javaNativeLibPath, extractNativeLibs, zipFile, entry,
                                     lastSlash + 1);
            if (ret == PAGE_SIZE_APP_COMPAT_FLAG_ERROR) {
                ALOGE("Alignment check returned for zipfile: %s, entry:%s",
                      zipFile->getZipFileName(), lastSlash + 1);
                return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
            }
            mode |= ret;
        }
    }

    return mode;
}

static void
com_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlong apkHandle)
{
@@ -797,23 +633,29 @@ com_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlon
}

static const JNINativeMethod gMethods[] = {
        {"nativeOpenApk", "(Ljava/lang/String;)J",
    {"nativeOpenApk",
            "(Ljava/lang/String;)J",
            (void *)com_android_internal_content_NativeLibraryHelper_openApk},
        {"nativeOpenApkFd", "(Ljava/io/FileDescriptor;Ljava/lang/String;)J",
    {"nativeOpenApkFd",
            "(Ljava/io/FileDescriptor;Ljava/lang/String;)J",
            (void *)com_android_internal_content_NativeLibraryHelper_openApkFd},
        {"nativeClose", "(J)V", (void*)com_android_internal_content_NativeLibraryHelper_close},
        {"nativeCopyNativeBinaries", "(JLjava/lang/String;Ljava/lang/String;ZZ)I",
    {"nativeClose",
            "(J)V",
            (void *)com_android_internal_content_NativeLibraryHelper_close},
    {"nativeCopyNativeBinaries",
            "(JLjava/lang/String;Ljava/lang/String;ZZ)I",
            (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
        {"nativeSumNativeBinaries", "(JLjava/lang/String;Z)J",
    {"nativeSumNativeBinaries",
            "(JLjava/lang/String;Z)J",
            (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
        {"nativeFindSupportedAbi", "(J[Ljava/lang/String;Z)I",
    {"nativeFindSupportedAbi",
            "(J[Ljava/lang/String;Z)I",
            (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
    {"hasRenderscriptBitcode", "(J)I",
            (void *)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode},
        {"nativeCheckAlignment", "(JLjava/lang/String;Ljava/lang/String;ZZ)I",
         (void*)com_android_internal_content_NativeLibraryHelper_checkApkAlignment},
};


int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env)
{
    return RegisterMethodsOrDie(env,
+2 −18
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.server.pm;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.util.ArraySet;
import android.util.Pair;

@@ -29,6 +28,8 @@ import com.android.server.pm.pkg.PackageStateInternal;

import java.io.File;



// TODO: Move to .parsing sub-package
@VisibleForTesting
public interface PackageAbiHelper {
@@ -77,23 +78,6 @@ public interface PackageAbiHelper {
    String getAdjustedAbiForSharedUser(ArraySet<? extends PackageStateInternal> packagesForUser,
            AndroidPackage scannedPackage);

    /**
     * Checks alignment of APK and native libraries for 16KB device
     *
     * @param pkg AndroidPackage for which alignment check is being done
     * @param libraryRoot directory for libraries
     * @param nativeLibraryRootRequiresIsa use isa
     * @param cpuAbiOverride ABI override mentioned in package
     * @return {ApplicationInfo.PageSizeAppCompat} if successful or error code
     *     which suggests undefined mode
     */
    @ApplicationInfo.PageSizeAppCompatFlags
    int checkPackageAlignment(
            AndroidPackage pkg,
            String libraryRoot,
            boolean nativeLibraryRootRequiresIsa,
            String cpuAbiOverride);

    /**
     * The native library paths and related properties that should be set on a
     * {@link ParsedPackage}.
+0 −16
Original line number Diff line number Diff line
@@ -625,20 +625,4 @@ final class PackageAbiHelperImpl implements PackageAbiHelper {
        }
        return adjustedAbi;
    }

    @Override
    public int checkPackageAlignment(
            AndroidPackage pkg,
            String libraryRoot,
            boolean nativeLibraryRootRequiresIsa,
            String abiOverride) {
        NativeLibraryHelper.Handle handle = null;
        try {
            handle = AndroidPackageUtils.createNativeLibraryHandle(pkg);
            return NativeLibraryHelper.checkAlignmentForCompatMode(
                            handle, libraryRoot, nativeLibraryRootRequiresIsa, abiOverride);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
+0 −32
Original line number Diff line number Diff line
@@ -52,7 +52,6 @@ import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTi
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.ApplicationInfo;
import android.content.pm.Flags;
import android.content.pm.PackageManager;
import android.content.pm.SharedLibraryInfo;
import android.content.pm.SigningDetails;
@@ -64,8 +63,6 @@ import android.os.Process;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.system.Os;
import android.system.OsConstants;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -108,9 +105,6 @@ import java.util.UUID;
 * Helper class that handles package scanning logic
 */
final class ScanPackageUtils {

    public static final int PAGE_SIZE_16KB = 16384;

    /**
     * Just scans the package without any side effects.
     *
@@ -424,32 +418,6 @@ final class ScanPackageUtils {
                    + " abiOverride=" + pkgSetting.getCpuAbiOverride());
        }

        boolean is16KbDevice = Os.sysconf(OsConstants._SC_PAGESIZE) == PAGE_SIZE_16KB;
        if (Flags.appCompatOption16kb() && is16KbDevice) {
            // Alignment checks are used decide whether this app should run in compat mode when
            // nothing was specified in manifest. Manifest should always take precedence over
            // something decided by platform.
            if (parsedPackage.getPageSizeAppCompatFlags()
                    > ApplicationInfo.PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED) {
                pkgSetting.setPageSizeAppCompatFlags(parsedPackage.getPageSizeAppCompatFlags());
            } else {
                // 16 KB is only support for 64 bit ABIs and for apps which are being installed
                // Check alignment. System, Apex and Platform packages should be page-agnostic now
                if ((Build.SUPPORTED_64_BIT_ABIS.length > 0)
                        && !isSystemApp
                        && !isApex
                        && !isPlatformPackage) {
                    int mode =
                            packageAbiHelper.checkPackageAlignment(
                                    parsedPackage,
                                    pkgSetting.getLegacyNativeLibraryPath(),
                                    parsedPackage.isNativeLibraryRootRequiresIsa(),
                                    pkgSetting.getCpuAbiOverride());
                    pkgSetting.setPageSizeAppCompatFlags(mode);
                }
            }
        }

        if ((scanFlags & SCAN_BOOTING) == 0 && oldSharedUserSetting != null) {
            // We don't do this here during boot because we can do it all
            // at once after scanning all existing packages.