Merge "Fix potential OOM issues when APEXs are too large."

This commit is contained in:
TreeHugger Robot
2022-02-17 04:23:10 +00:00
committed by Android (Google) Code Review
2 changed files with 62 additions and 18 deletions

View File

@@ -18,13 +18,17 @@ package android.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.pm.Signature;
import android.text.TextUtils;
import libcore.util.HexEncoding;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
@@ -35,6 +39,9 @@ import java.util.Arrays;
*/
public final class PackageUtils {
private static final int LOW_RAM_BUFFER_SIZE_BYTES = 1 * 1000; // 1 kB
private static final int HIGH_RAM_BUFFER_SIZE_BYTES = 1 * 1000 * 1000; // 1 MB
private PackageUtils() {
/* hide constructor */
}
@@ -162,4 +169,55 @@ public final class PackageUtils {
return TextUtils.join(separator, pieces);
}
/**
* @see #computeSha256DigestForLargeFile(String, String)
*/
public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath) {
return computeSha256DigestForLargeFile(filePath, null);
}
/**
* Computes the SHA256 digest of large files.
* @param filePath The path to which the file's content is to be hashed.
* @param separator Separator between each pair of characters, such as colon, or null to omit.
* @return The digest or null if an error occurs.
*/
public static @Nullable String computeSha256DigestForLargeFile(@NonNull String filePath,
@Nullable String separator) {
MessageDigest messageDigest;
try {
messageDigest = MessageDigest.getInstance("SHA256");
messageDigest.reset();
} catch (NoSuchAlgorithmException e) {
// this shouldn't happen!
return null;
}
boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
int bufferSize = isLowRamDevice ? LOW_RAM_BUFFER_SIZE_BYTES : HIGH_RAM_BUFFER_SIZE_BYTES;
File f = new File(filePath);
try {
DigestInputStream digestStream = new DigestInputStream(new FileInputStream(f),
messageDigest);
byte[] buffer = new byte[bufferSize];
while (digestStream.read(buffer) != -1);
} catch (IOException e) {
return null;
}
byte[] resultBytes = messageDigest.digest();
if (separator == null) {
return HexEncoding.encodeToString(resultBytes, true);
}
int length = resultBytes.length;
String[] pieces = new String[length];
for (int index = 0; index < length; index++) {
pieces[index] = HexEncoding.encodeToString(resultBytes[index], true);
}
return TextUtils.join(separator, pieces);
}
}

View File

@@ -36,11 +36,8 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IBinaryTransparencyService;
import com.android.internal.util.FrameworkStatsLog;
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -434,7 +431,7 @@ public class BinaryTransparencyService extends SystemService {
entry.setValue(packageInfo.lastUpdateTime);
// compute the digest for the updated package
String sha256digest = computeSha256DigestOfFile(
String sha256digest = PackageUtils.computeSha256DigestForLargeFile(
packageInfo.applicationInfo.sourceDir);
if (sha256digest == null) {
Slog.e(TAG, "Failed to compute SHA256sum for file at "
@@ -471,7 +468,7 @@ public class BinaryTransparencyService extends SystemService {
ApplicationInfo appInfo = packageInfo.applicationInfo;
// compute SHA256 for these APEXs
String sha256digest = computeSha256DigestOfFile(appInfo.sourceDir);
String sha256digest = PackageUtils.computeSha256DigestForLargeFile(appInfo.sourceDir);
if (sha256digest == null) {
Slog.e(TAG, String.format("Failed to compute SHA256 digest for %s",
packageInfo.packageName));
@@ -506,7 +503,8 @@ public class BinaryTransparencyService extends SystemService {
ApplicationInfo appInfo = packageInfo.applicationInfo;
// compute SHA256 digest for these modules
String sha256digest = computeSha256DigestOfFile(appInfo.sourceDir);
String sha256digest = PackageUtils.computeSha256DigestForLargeFile(
appInfo.sourceDir);
if (sha256digest == null) {
Slog.e(TAG, String.format("Failed to compute SHA256 digest for %s",
packageName));
@@ -525,16 +523,4 @@ public class BinaryTransparencyService extends SystemService {
}
}
@Nullable
private String computeSha256DigestOfFile(@NonNull String pathToFile) {
File apexFile = new File(pathToFile);
try {
byte[] apexFileBytes = Files.readAllBytes(apexFile.toPath());
return PackageUtils.computeSha256Digest(apexFileBytes);
} catch (IOException e) {
Slog.e(TAG, String.format("I/O error occurs when reading from %s", pathToFile));
return null;
}
}
}