Merge "Fix potential OOM issues when APEXs are too large."
This commit is contained in:
committed by
Android (Google) Code Review
commit
55bfb23dbe
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user