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

Commit c863792d authored by Alex Buynytskyy's avatar Alex Buynytskyy
Browse files

Check if idsig size is within IncFs limits.

Bug: 152148243
Fixes: 152148243
Test: pm install-incremental <apk in the bug>
Test: atest PackageManagerShellCommandTest PackageManagerShellCommandIncrementalTest IncrementalServiceTest PackageManagerServiceTest ChecksumsTest
Change-Id: I33623a9240482ea36a8e1eeb97ec01294e7249ff
parent 6e943b54
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -41,6 +41,8 @@ public class V4Signature {
    public static final int HASHING_ALGORITHM_SHA256 = 1;
    public static final byte LOG2_BLOCK_SIZE_4096_BYTES = 12;

    public static final int INCFS_MAX_SIGNATURE_SIZE = 8096;  // incrementalfs.h

    /**
     * IncFS hashing data.
     */
@@ -191,8 +193,12 @@ public class V4Signature {

    private static V4Signature readFrom(InputStream stream) throws IOException {
        final int version = readIntLE(stream);
        final byte[] hashingInfo = readBytes(stream);
        final byte[] signingInfo = readBytes(stream);
        int maxSize = INCFS_MAX_SIGNATURE_SIZE;
        final byte[] hashingInfo = readBytes(stream, maxSize);
        if (hashingInfo != null) {
            maxSize -= hashingInfo.length;
        }
        final byte[] signingInfo = readBytes(stream, maxSize);
        return new V4Signature(version, hashingInfo, signingInfo);
    }

@@ -231,9 +237,13 @@ public class V4Signature {
        stream.write(buffer);
    }

    private static byte[] readBytes(InputStream stream) throws IOException {
    private static byte[] readBytes(InputStream stream, int maxSize) throws IOException {
        try {
            final int size = readIntLE(stream);
            if (size > maxSize) {
                throw new IOException(
                        "Signature is too long. Max allowed is " + INCFS_MAX_SIGNATURE_SIZE);
            }
            final byte[] bytes = new byte[size];
            readFully(stream, bytes);
            return bytes;
+19 −9
Original line number Diff line number Diff line
@@ -171,17 +171,23 @@ static inline int32_t readLEInt32(borrowed_fd fd) {
    return result;
}

static inline std::vector<char> readBytes(borrowed_fd fd) {
    int32_t size = readLEInt32(fd);
    std::vector<char> result(size);
    android::base::ReadFully(fd, result.data(), size);
    return result;
static inline bool skipBytes(borrowed_fd fd, int* max_size) {
    int32_t size = std::min(readLEInt32(fd), *max_size);
    if (size <= 0) {
        return false;
    }
    *max_size -= size;
    return (TEMP_FAILURE_RETRY(lseek64(fd.get(), size, SEEK_CUR)) >= 0);
}

static inline int32_t skipIdSigHeaders(borrowed_fd fd) {
    readLEInt32(fd);        // version
    readBytes(fd);          // hashingInfo
    readBytes(fd);          // signingInfo
    // version
    auto version = readLEInt32(fd);
    int max_size = INCFS_MAX_SIGNATURE_SIZE - sizeof(version);
    // hashingInfo and signingInfo
    if (!skipBytes(fd, &max_size) || !skipBytes(fd, &max_size)) {
        return -1;
    }
    return readLEInt32(fd); // size of the verity tree
}

@@ -253,8 +259,12 @@ static inline InputDescs openLocalFile(JNIEnv* env, const JniIds& jni, jobject s

    unique_fd idsigFd = openLocalFile(env, jni, shellCommand, idsigPath);
    if (idsigFd.ok()) {
        auto treeSize = verityTreeSizeForFile(size);
        auto actualTreeSize = skipIdSigHeaders(idsigFd);
        if (actualTreeSize < 0) {
            ALOGE("Error reading .idsig file: wrong format.");
            return {};
        }
        auto treeSize = verityTreeSizeForFile(size);
        if (treeSize != actualTreeSize) {
            ALOGE("Verity tree size mismatch: %d vs .idsig: %d.", int(treeSize),
                  int(actualTreeSize));