Delete legacy fs-verity support
The "legacy" fs-verity was introduced in P in Pixel 3 kernel. During fs-verity upstream to Linux, the API has changed. During Pixel 4 / Q development, fs-verity was upstreamed to Linux kernel. By setting ro.apk_verity.mode = 2, device vendors such as Pixel 4 can opt in to enable the support. The feature has become mandatory for new devices shipped with R. Since Pixel 3 family is no longer supported, it's time to remove the dead code. Bug: 120629632 Test: m Test: TH Change-Id: I6dacd9bbd38b502ee510ff12970e76342d7b72dd Merged-In: I6dacd9bbd38b502ee510ff12970e76342d7b72dd
This commit is contained in:
@@ -407,20 +407,6 @@ public class ApkSignatureSchemeV2Verifier {
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] generateApkVerityRootHash(String apkPath)
|
||||
throws IOException, SignatureNotFoundException, DigestException,
|
||||
NoSuchAlgorithmException {
|
||||
try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
|
||||
SignatureInfo signatureInfo = findSignature(apk);
|
||||
VerifiedSigner vSigner = verify(apk, false);
|
||||
if (vSigner.verityRootHash == null) {
|
||||
return null;
|
||||
}
|
||||
return VerityBuilder.generateApkVerityRootHash(
|
||||
apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verified APK Signature Scheme v2 signer.
|
||||
*
|
||||
|
||||
@@ -444,20 +444,6 @@ public class ApkSignatureSchemeV3Verifier {
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] generateApkVerityRootHash(String apkPath)
|
||||
throws NoSuchAlgorithmException, DigestException, IOException,
|
||||
SignatureNotFoundException {
|
||||
try (RandomAccessFile apk = new RandomAccessFile(apkPath, "r")) {
|
||||
SignatureInfo signatureInfo = findSignature(apk);
|
||||
VerifiedSigner vSigner = verify(apk, false);
|
||||
if (vSigner.verityRootHash == null) {
|
||||
return null;
|
||||
}
|
||||
return VerityBuilder.generateApkVerityRootHash(
|
||||
apk, ByteBuffer.wrap(vSigner.verityRootHash), signatureInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verified APK Signature Scheme v3 signer, including the proof of rotation structure.
|
||||
*
|
||||
|
||||
@@ -550,27 +550,6 @@ public class ApkSignatureVerifier {
|
||||
return ApkSignatureSchemeV2Verifier.generateApkVerity(apkPath, bufferFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the FSVerity root hash from FSVerity header, extensions and Merkle tree root hash
|
||||
* in Signing Block.
|
||||
*
|
||||
* @return FSverity root hash
|
||||
*/
|
||||
public static byte[] generateApkVerityRootHash(String apkPath)
|
||||
throws NoSuchAlgorithmException, DigestException, IOException {
|
||||
// first try v3
|
||||
try {
|
||||
return ApkSignatureSchemeV3Verifier.generateApkVerityRootHash(apkPath);
|
||||
} catch (SignatureNotFoundException e) {
|
||||
// try older version
|
||||
}
|
||||
try {
|
||||
return ApkSignatureSchemeV2Verifier.generateApkVerityRootHash(apkPath);
|
||||
} catch (SignatureNotFoundException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extended signing details.
|
||||
* @hide for internal use only.
|
||||
|
||||
@@ -143,25 +143,6 @@ public abstract class VerityBuilder {
|
||||
return generateFsVerityTreeInternal(apk, salt, levelOffset, tree);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Calculates the apk-verity root hash for integrity measurement. This needs to be consistent
|
||||
* to what kernel returns.
|
||||
*/
|
||||
@NonNull
|
||||
static byte[] generateApkVerityRootHash(@NonNull RandomAccessFile apk,
|
||||
@NonNull ByteBuffer apkDigest, @NonNull SignatureInfo signatureInfo)
|
||||
throws NoSuchAlgorithmException, DigestException, IOException {
|
||||
assertSigningBlockAlignedAndHasFullPages(signatureInfo);
|
||||
|
||||
ByteBuffer footer = ByteBuffer.allocate(CHUNK_SIZE_BYTES).order(ByteOrder.LITTLE_ENDIAN);
|
||||
generateApkVerityFooter(apk, signatureInfo, footer);
|
||||
footer.flip();
|
||||
|
||||
MessageDigest md = MessageDigest.getInstance(JCA_DIGEST_ALGORITHM);
|
||||
md.update(footer);
|
||||
md.update(apkDigest);
|
||||
return md.digest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the apk-verity header and hash tree to be used by kernel for the given apk. This
|
||||
|
||||
@@ -18,28 +18,15 @@ package com.android.internal.security;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.Build;
|
||||
import android.os.SharedMemory;
|
||||
import android.os.SystemProperties;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.apk.ApkSignatureVerifier;
|
||||
import android.util.apk.ByteBufferFactory;
|
||||
import android.util.apk.SignatureNotFoundException;
|
||||
|
||||
import libcore.util.HexEncoding;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.DigestException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Provides fsverity related operations. */
|
||||
public abstract class VerityUtils {
|
||||
@@ -57,8 +44,6 @@ public abstract class VerityUtils {
|
||||
/** SHA256 hash size. */
|
||||
private static final int HASH_SIZE_BYTES = 32;
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
public static boolean isFsVeritySupported() {
|
||||
return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R
|
||||
|| SystemProperties.getInt("ro.apk_verity.mode", 0) == 2;
|
||||
@@ -123,204 +108,4 @@ public abstract class VerityUtils {
|
||||
private static native int measureFsverityNative(@NonNull String filePath,
|
||||
@NonNull byte[] digest);
|
||||
private static native int statxForFsverityNative(@NonNull String filePath);
|
||||
|
||||
/**
|
||||
* Generates legacy Merkle tree and fs-verity metadata with Signing Block skipped.
|
||||
*
|
||||
* @deprecated This is only used for previous fs-verity implementation, and should never be used
|
||||
* on new devices.
|
||||
* @return {@code SetupResult} that contains the result code, and when success, the
|
||||
* {@code FileDescriptor} to read all the data from.
|
||||
*/
|
||||
@Deprecated
|
||||
public static SetupResult generateApkVeritySetupData(@NonNull String apkPath) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Trying to install legacy apk verity to " + apkPath);
|
||||
}
|
||||
SharedMemory shm = null;
|
||||
try {
|
||||
final byte[] signedVerityHash = ApkSignatureVerifier.getVerityRootHash(apkPath);
|
||||
if (signedVerityHash == null) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Skip verity tree generation since there is no signed root hash");
|
||||
}
|
||||
return SetupResult.skipped();
|
||||
}
|
||||
|
||||
Pair<SharedMemory, Integer> result =
|
||||
generateFsVerityIntoSharedMemory(apkPath, signedVerityHash);
|
||||
shm = result.first;
|
||||
int contentSize = result.second;
|
||||
FileDescriptor rfd = shm.getFileDescriptor();
|
||||
if (rfd == null || !rfd.valid()) {
|
||||
return SetupResult.failed();
|
||||
}
|
||||
return SetupResult.ok(Os.dup(rfd), contentSize);
|
||||
} catch (IOException | SecurityException | DigestException | NoSuchAlgorithmException
|
||||
| SignatureNotFoundException | ErrnoException e) {
|
||||
Slog.e(TAG, "Failed to set up apk verity: ", e);
|
||||
return SetupResult.failed();
|
||||
} finally {
|
||||
if (shm != null) {
|
||||
shm.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@see ApkSignatureVerifier#generateApkVerityRootHash(String)}.
|
||||
* @deprecated This is only used for previous fs-verity implementation, and should never be used
|
||||
* on new devices.
|
||||
*/
|
||||
@Deprecated
|
||||
public static byte[] generateApkVerityRootHash(@NonNull String apkPath)
|
||||
throws NoSuchAlgorithmException, DigestException, IOException {
|
||||
return ApkSignatureVerifier.generateApkVerityRootHash(apkPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@see ApkSignatureVerifier#getVerityRootHash(String)}.
|
||||
* @deprecated This is only used for previous fs-verity implementation, and should never be used
|
||||
* on new devices.
|
||||
*/
|
||||
@Deprecated
|
||||
public static byte[] getVerityRootHash(@NonNull String apkPath)
|
||||
throws IOException, SignatureNotFoundException {
|
||||
return ApkSignatureVerifier.getVerityRootHash(apkPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pair of {@code SharedMemory} and {@code Integer}. The {@code SharedMemory} contains
|
||||
* Merkle tree and fsverity headers for the given apk, in the form that can immediately be used
|
||||
* for fsverity setup. The data is aligned to the beginning of {@code SharedMemory}, and has
|
||||
* length equals to the returned {@code Integer}.
|
||||
*/
|
||||
private static Pair<SharedMemory, Integer> generateFsVerityIntoSharedMemory(String apkPath,
|
||||
@NonNull byte[] expectedRootHash)
|
||||
throws IOException, DigestException, NoSuchAlgorithmException,
|
||||
SignatureNotFoundException {
|
||||
TrackedShmBufferFactory shmBufferFactory = new TrackedShmBufferFactory();
|
||||
byte[] generatedRootHash =
|
||||
ApkSignatureVerifier.generateApkVerity(apkPath, shmBufferFactory);
|
||||
// We only generate Merkle tree once here, so it's important to make sure the root hash
|
||||
// matches the signed one in the apk.
|
||||
if (!Arrays.equals(expectedRootHash, generatedRootHash)) {
|
||||
throw new SecurityException("verity hash mismatch: "
|
||||
+ bytesToString(generatedRootHash) + " != " + bytesToString(expectedRootHash));
|
||||
}
|
||||
|
||||
int contentSize = shmBufferFactory.getBufferLimit();
|
||||
SharedMemory shm = shmBufferFactory.releaseSharedMemory();
|
||||
if (shm == null) {
|
||||
throw new IllegalStateException("Failed to generate verity tree into shared memory");
|
||||
}
|
||||
if (!shm.setProtect(OsConstants.PROT_READ)) {
|
||||
throw new SecurityException("Failed to set up shared memory correctly");
|
||||
}
|
||||
return Pair.create(shm, contentSize);
|
||||
}
|
||||
|
||||
private static String bytesToString(byte[] bytes) {
|
||||
return HexEncoding.encodeToString(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This is only used for previous fs-verity implementation, and should never be used
|
||||
* on new devices.
|
||||
*/
|
||||
@Deprecated
|
||||
public static class SetupResult {
|
||||
/** Result code if verity is set up correctly. */
|
||||
private static final int RESULT_OK = 1;
|
||||
|
||||
/** Result code if signature is not provided. */
|
||||
private static final int RESULT_SKIPPED = 2;
|
||||
|
||||
/** Result code if the setup failed. */
|
||||
private static final int RESULT_FAILED = 3;
|
||||
|
||||
private final int mCode;
|
||||
private final FileDescriptor mFileDescriptor;
|
||||
private final int mContentSize;
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static SetupResult ok(@NonNull FileDescriptor fileDescriptor, int contentSize) {
|
||||
return new SetupResult(RESULT_OK, fileDescriptor, contentSize);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static SetupResult skipped() {
|
||||
return new SetupResult(RESULT_SKIPPED, null, -1);
|
||||
}
|
||||
|
||||
/** @deprecated */
|
||||
@Deprecated
|
||||
public static SetupResult failed() {
|
||||
return new SetupResult(RESULT_FAILED, null, -1);
|
||||
}
|
||||
|
||||
private SetupResult(int code, FileDescriptor fileDescriptor, int contentSize) {
|
||||
this.mCode = code;
|
||||
this.mFileDescriptor = fileDescriptor;
|
||||
this.mContentSize = contentSize;
|
||||
}
|
||||
|
||||
public boolean isFailed() {
|
||||
return mCode == RESULT_FAILED;
|
||||
}
|
||||
|
||||
public boolean isOk() {
|
||||
return mCode == RESULT_OK;
|
||||
}
|
||||
|
||||
public @NonNull FileDescriptor getUnownedFileDescriptor() {
|
||||
return mFileDescriptor;
|
||||
}
|
||||
|
||||
public int getContentSize() {
|
||||
return mContentSize;
|
||||
}
|
||||
}
|
||||
|
||||
/** A {@code ByteBufferFactory} that creates a shared memory backed {@code ByteBuffer}. */
|
||||
private static class TrackedShmBufferFactory implements ByteBufferFactory {
|
||||
private SharedMemory mShm;
|
||||
private ByteBuffer mBuffer;
|
||||
|
||||
@Override
|
||||
public ByteBuffer create(int capacity) {
|
||||
try {
|
||||
if (DEBUG) Slog.d(TAG, "Creating shared memory for apk verity");
|
||||
// NB: This method is supposed to be called once according to the contract with
|
||||
// ApkSignatureSchemeV2Verifier.
|
||||
if (mBuffer != null) {
|
||||
throw new IllegalStateException("Multiple instantiation from this factory");
|
||||
}
|
||||
mShm = SharedMemory.create("apkverity", capacity);
|
||||
if (!mShm.setProtect(OsConstants.PROT_READ | OsConstants.PROT_WRITE)) {
|
||||
throw new SecurityException("Failed to set protection");
|
||||
}
|
||||
mBuffer = mShm.mapReadWrite();
|
||||
return mBuffer;
|
||||
} catch (ErrnoException e) {
|
||||
throw new SecurityException("Failed to set protection", e);
|
||||
}
|
||||
}
|
||||
|
||||
public SharedMemory releaseSharedMemory() {
|
||||
if (mBuffer != null) {
|
||||
SharedMemory.unmap(mBuffer);
|
||||
mBuffer = null;
|
||||
}
|
||||
SharedMemory tmp = mShm;
|
||||
mShm = null;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
public int getBufferLimit() {
|
||||
return mBuffer == null ? -1 : mBuffer.limit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import com.android.server.SystemService;
|
||||
import dalvik.system.BlockGuard;
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -681,28 +680,6 @@ public class Installer extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)
|
||||
throws InstallerException {
|
||||
if (!checkBeforeRemote()) return;
|
||||
BlockGuard.getVmPolicy().onPathAccess(filePath);
|
||||
try {
|
||||
mInstalld.installApkVerity(filePath, verityInput, contentSize);
|
||||
} catch (Exception e) {
|
||||
throw InstallerException.from(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash)
|
||||
throws InstallerException {
|
||||
if (!checkBeforeRemote()) return;
|
||||
BlockGuard.getVmPolicy().onPathAccess(filePath);
|
||||
try {
|
||||
mInstalld.assertFsverityRootHashMatches(filePath, expectedHash);
|
||||
} catch (Exception e) {
|
||||
throw InstallerException.from(e);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean reconcileSecondaryDexFile(String apkPath, String packageName, int uid,
|
||||
String[] isas, @Nullable String volumeUuid, int flags) throws InstallerException {
|
||||
for (int i = 0; i < isas.length; i++) {
|
||||
|
||||
@@ -12118,14 +12118,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
* Returns if forced apk verification can be skipped for the whole package, including splits.
|
||||
*/
|
||||
private boolean canSkipForcedPackageVerification(AndroidPackage pkg) {
|
||||
if (!canSkipForcedApkVerification(pkg.getBaseApkPath())) {
|
||||
if (!VerityUtils.hasFsverity(pkg.getBaseApkPath())) {
|
||||
return false;
|
||||
}
|
||||
// TODO: Allow base and splits to be verified individually.
|
||||
String[] splitCodePaths = pkg.getSplitCodePaths();
|
||||
if (!ArrayUtils.isEmpty(splitCodePaths)) {
|
||||
for (int i = 0; i < splitCodePaths.length; i++) {
|
||||
if (!canSkipForcedApkVerification(splitCodePaths[i])) {
|
||||
if (!VerityUtils.hasFsverity(splitCodePaths[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -12133,33 +12133,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if forced apk verification can be skipped, depending on current FSVerity setup and
|
||||
* whether the apk contains signed root hash. Note that the signer's certificate still needs to
|
||||
* match one in a trusted source, and should be done separately.
|
||||
*/
|
||||
private boolean canSkipForcedApkVerification(String apkPath) {
|
||||
if (!PackageManagerServiceUtils.isLegacyApkVerityEnabled()) {
|
||||
return VerityUtils.hasFsverity(apkPath);
|
||||
}
|
||||
|
||||
try {
|
||||
final byte[] rootHashObserved = VerityUtils.generateApkVerityRootHash(apkPath);
|
||||
if (rootHashObserved == null) {
|
||||
return false; // APK does not contain Merkle tree root hash.
|
||||
}
|
||||
synchronized (mInstallLock) {
|
||||
// Returns whether the observed root hash matches what kernel has.
|
||||
mInstaller.assertFsverityRootHashMatches(apkPath, rootHashObserved);
|
||||
return true;
|
||||
}
|
||||
} catch (InstallerException | IOException | DigestException |
|
||||
NoSuchAlgorithmException e) {
|
||||
Slog.w(TAG, "Error in fsverity check. Fallback to full apk verification.", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new package to the internal data structures during platform initialization.
|
||||
* <p>After adding, the package is known to the system and available for querying.
|
||||
@@ -21192,9 +21165,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
*/
|
||||
private void setUpFsVerityIfPossible(AndroidPackage pkg) throws InstallerException,
|
||||
PrepareFailure, IOException, DigestException, NoSuchAlgorithmException {
|
||||
final boolean standardMode = PackageManagerServiceUtils.isApkVerityEnabled();
|
||||
final boolean legacyMode = PackageManagerServiceUtils.isLegacyApkVerityEnabled();
|
||||
if (!standardMode && !legacyMode) {
|
||||
if (!PackageManagerServiceUtils.isApkVerityEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21205,39 +21176,25 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
||||
// Collect files we care for fs-verity setup.
|
||||
ArrayMap<String, String> fsverityCandidates = new ArrayMap<>();
|
||||
if (legacyMode) {
|
||||
synchronized (mLock) {
|
||||
final PackageSetting ps = mSettings.getPackageLPr(pkg.getPackageName());
|
||||
if (ps != null && ps.isPrivileged()) {
|
||||
fsverityCandidates.put(pkg.getBaseApkPath(), null);
|
||||
if (pkg.getSplitCodePaths() != null) {
|
||||
for (String splitPath : pkg.getSplitCodePaths()) {
|
||||
fsverityCandidates.put(splitPath, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// NB: These files will become only accessible if the signing key is loaded in kernel's
|
||||
// .fs-verity keyring.
|
||||
fsverityCandidates.put(pkg.getBaseApkPath(),
|
||||
VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath()));
|
||||
// NB: These files will become only accessible if the signing key is loaded in kernel's
|
||||
// .fs-verity keyring.
|
||||
fsverityCandidates.put(pkg.getBaseApkPath(),
|
||||
VerityUtils.getFsveritySignatureFilePath(pkg.getBaseApkPath()));
|
||||
|
||||
final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(
|
||||
pkg.getBaseApkPath());
|
||||
if (new File(dmPath).exists()) {
|
||||
fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath));
|
||||
}
|
||||
final String dmPath = DexMetadataHelper.buildDexMetadataPathForApk(
|
||||
pkg.getBaseApkPath());
|
||||
if (new File(dmPath).exists()) {
|
||||
fsverityCandidates.put(dmPath, VerityUtils.getFsveritySignatureFilePath(dmPath));
|
||||
}
|
||||
|
||||
if (pkg.getSplitCodePaths() != null) {
|
||||
for (String path : pkg.getSplitCodePaths()) {
|
||||
fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path));
|
||||
if (pkg.getSplitCodePaths() != null) {
|
||||
for (String path : pkg.getSplitCodePaths()) {
|
||||
fsverityCandidates.put(path, VerityUtils.getFsveritySignatureFilePath(path));
|
||||
|
||||
final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path);
|
||||
if (new File(splitDmPath).exists()) {
|
||||
fsverityCandidates.put(splitDmPath,
|
||||
VerityUtils.getFsveritySignatureFilePath(splitDmPath));
|
||||
}
|
||||
final String splitDmPath = DexMetadataHelper.buildDexMetadataPathForApk(path);
|
||||
if (new File(splitDmPath).exists()) {
|
||||
fsverityCandidates.put(splitDmPath,
|
||||
VerityUtils.getFsveritySignatureFilePath(splitDmPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21246,40 +21203,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final String filePath = entry.getKey();
|
||||
final String signaturePath = entry.getValue();
|
||||
|
||||
if (!legacyMode) {
|
||||
// fs-verity is optional for now. Only set up if signature is provided.
|
||||
if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
|
||||
try {
|
||||
VerityUtils.setUpFsverity(filePath, signaturePath);
|
||||
} catch (IOException e) {
|
||||
throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
|
||||
"Failed to enable fs-verity: " + e);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// In legacy mode, fs-verity can only be enabled by process with CAP_SYS_ADMIN.
|
||||
final VerityUtils.SetupResult result = VerityUtils.generateApkVeritySetupData(filePath);
|
||||
if (result.isOk()) {
|
||||
if (Build.IS_DEBUGGABLE) Slog.i(TAG, "Enabling verity to " + filePath);
|
||||
final FileDescriptor fd = result.getUnownedFileDescriptor();
|
||||
// fs-verity is optional for now. Only set up if signature is provided.
|
||||
if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
|
||||
try {
|
||||
final byte[] rootHash = VerityUtils.generateApkVerityRootHash(filePath);
|
||||
try {
|
||||
// A file may already have fs-verity, e.g. when reused during a split
|
||||
// install. If the measurement succeeds, no need to attempt to set up.
|
||||
mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
|
||||
} catch (InstallerException e) {
|
||||
mInstaller.installApkVerity(filePath, fd, result.getContentSize());
|
||||
mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
|
||||
}
|
||||
} finally {
|
||||
IoUtils.closeQuietly(fd);
|
||||
VerityUtils.setUpFsverity(filePath, signaturePath);
|
||||
} catch (IOException e) {
|
||||
throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
|
||||
"Failed to enable fs-verity: " + e);
|
||||
}
|
||||
} else if (result.isFailed()) {
|
||||
throw new PrepareFailure(PackageManager.INSTALL_FAILED_BAD_SIGNATURE,
|
||||
"Failed to generate verity");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,12 +591,6 @@ public class PackageManagerServiceUtils {
|
||||
/** Default is to not use fs-verity since it depends on kernel support. */
|
||||
private static final int FSVERITY_DISABLED = 0;
|
||||
|
||||
/**
|
||||
* Experimental implementation targeting priv apps, with Android specific kernel patches to
|
||||
* extend fs-verity.
|
||||
*/
|
||||
private static final int FSVERITY_LEGACY = 1;
|
||||
|
||||
/** Standard fs-verity. */
|
||||
private static final int FSVERITY_ENABLED = 2;
|
||||
|
||||
@@ -607,10 +601,6 @@ public class PackageManagerServiceUtils {
|
||||
== FSVERITY_ENABLED;
|
||||
}
|
||||
|
||||
static boolean isLegacyApkVerityEnabled() {
|
||||
return SystemProperties.getInt("ro.apk_verity.mode", FSVERITY_DISABLED) == FSVERITY_LEGACY;
|
||||
}
|
||||
|
||||
/** Returns true to force apk verification if the package is considered privileged. */
|
||||
static boolean isApkVerificationForced(@Nullable PackageSetting ps) {
|
||||
// TODO(b/154310064): re-enable.
|
||||
|
||||
Reference in New Issue
Block a user