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

Commit 116c58c8 authored by Pawan Wagh's avatar Pawan Wagh
Browse files

Ignore 32 bit ELFs in alignment checks

Some apps mixup 32 bit ELFs inside of arm64 directory.
Ignore 32 bit ELFs instead of erroring out.

PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED is equivalent of
skipping the current file. on return, flag is OR'ed
with flags from other ELF files. If some app has 32 bit ELF in
64 bit directory, alignment of that ELF will be ignored.

Flag: EXEMPT bug_fix
Test: atest -c FileSystemUtilsTests
Bug: 400741951
Change-Id: Ia9787f795bf9e84e194142f7d3e114daec1db722
parent 6768e5f0
Loading
Loading
Loading
Loading
+11 −10
Original line number Diff line number Diff line
@@ -201,7 +201,7 @@ bool punchHoles(const char *filePath, const uint64_t offset,
    return true;
}

bool getLoadSegmentPhdrs(const char *filePath, const uint64_t offset,
read_elf_status_t getLoadSegmentPhdrs(const char *filePath, const uint64_t offset,
                                      std::vector<Elf64_Phdr> &programHeaders) {
    // Open Elf file
    Elf64_Ehdr ehdr;
@@ -212,13 +212,13 @@ bool getLoadSegmentPhdrs(const char *filePath, const uint64_t offset,
    // read executable headers
    inputStream.read((char *)&ehdr, sizeof(ehdr));
    if (!inputStream.good()) {
        return false;
        return ELF_READ_ERROR;
    }

    // only consider elf64 for punching holes
    // only consider ELF64 files
    if (ehdr.e_ident[EI_CLASS] != ELFCLASS64) {
        ALOGW("Provided file is not ELF64");
        return false;
        return ELF_IS_NOT_64_BIT;
    }

    // read the program headers from elf file
@@ -229,7 +229,7 @@ bool getLoadSegmentPhdrs(const char *filePath, const uint64_t offset,
    uint64_t phOffset;
    if (__builtin_add_overflow(offset, programHeaderOffset, &phOffset)) {
        ALOGE("Overflow occurred when calculating phOffset");
        return false;
        return ELF_READ_ERROR;
    }
    inputStream.seekg(phOffset);

@@ -237,7 +237,7 @@ bool getLoadSegmentPhdrs(const char *filePath, const uint64_t offset,
        Elf64_Phdr header;
        inputStream.read((char *)&header, sizeof(header));
        if (!inputStream.good()) {
            return false;
            return ELF_READ_ERROR;
        }

        if (header.p_type != PT_LOAD) {
@@ -246,13 +246,14 @@ bool getLoadSegmentPhdrs(const char *filePath, const uint64_t offset,
        programHeaders.push_back(header);
    }

    return true;
    return ELF_READ_OK;
}

bool punchHolesInElf64(const char *filePath, const uint64_t offset) {
    std::vector<Elf64_Phdr> programHeaders;
    if (!getLoadSegmentPhdrs(filePath, offset, programHeaders)) {
        ALOGE("Failed to read program headers from ELF file.");
    read_elf_status_t status = getLoadSegmentPhdrs(filePath, offset, programHeaders);
    if (status != ELF_READ_OK) {
        ALOGE("Failed to read program headers from 64 bit ELF file.");
        return false;
    }
    return punchHoles(filePath, offset, programHeaders);
+10 −4
Original line number Diff line number Diff line
@@ -22,6 +22,12 @@

namespace android {

enum read_elf_status_t {
    ELF_IS_NOT_64_BIT = -2,
    ELF_READ_ERROR = -1,
    ELF_READ_OK = 0,
};

/*
 * This function deallocates space used by zero padding at the end of LOAD segments in given
 * uncompressed ELF file. Read ELF headers and find out the offset and sizes of LOAD segments.
@@ -39,10 +45,10 @@ bool punchHolesInElf64(const char* filePath, uint64_t offset);
bool punchHolesInZip(const char* filePath, uint64_t offset, uint16_t extraFieldLen);

/*
 * This function reads program headers from ELF file. ELF can be specified with file path directly
 * or it should be at offset inside Apk. Program headers passed to function is populated.
 * This function reads program headers from 64 bit ELF file. ELF can be specified with file path
 * directly or it should be at offset inside Apk. Program headers passed to function is populated.
 */
bool getLoadSegmentPhdrs(const char* filePath, const uint64_t offset,
read_elf_status_t getLoadSegmentPhdrs(const char* filePath, const uint64_t offset,
                                      std::vector<Elf64_Phdr>& programHeaders);

} // namespace android
 No newline at end of file
+11 −1
Original line number Diff line number Diff line
@@ -640,7 +640,17 @@ com_android_internal_content_NativeLibraryHelper_openApkFd(JNIEnv *env, jclass,

static jint checkLoadSegmentAlignment(const char* fileName, off64_t offset) {
    std::vector<Elf64_Phdr> programHeaders;
    if (!getLoadSegmentPhdrs(fileName, offset, programHeaders)) {
    read_elf_status_t status = getLoadSegmentPhdrs(fileName, offset, programHeaders);
    // Ignore the ELFs which are not 64 bit.
    if (status == ELF_IS_NOT_64_BIT) {
        ALOGW("ELF file is not 64 Bit");
        // PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED is equivalent of skipping the current file.
        // on return, flag is OR'ed with flags from other ELF files. If some app has 32 bit ELF in
        // 64 bit directory, alignment of that ELF will be ignored.
        return PAGE_SIZE_APP_COMPAT_FLAG_UNDEFINED;
    }

    if (status == ELF_READ_ERROR) {
        ALOGE("Failed to read program headers from ELF file.");
        return PAGE_SIZE_APP_COMPAT_FLAG_ERROR;
    }