diff --git a/core/java/android/os/incremental/V4Signature.java b/core/java/android/os/incremental/V4Signature.java index 77d8664a64599..688e3e9d2a678 100644 --- a/core/java/android/os/incremental/V4Signature.java +++ b/core/java/android/os/incremental/V4Signature.java @@ -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; diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp index f0210eeb80e8c..db5268337f5de 100644 --- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp +++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp @@ -171,17 +171,23 @@ static inline int32_t readLEInt32(borrowed_fd fd) { return result; } -static inline std::vector readBytes(borrowed_fd fd) { - int32_t size = readLEInt32(fd); - std::vector 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));