Merge "Provide a way to query fs-verity status"
This commit is contained in:
committed by
Android (Google) Code Review
commit
4a137fdb4f
@@ -16,13 +16,11 @@
|
||||
|
||||
package com.android.server.security;
|
||||
|
||||
import static android.system.OsConstants.PROT_READ;
|
||||
import static android.system.OsConstants.PROT_WRITE;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.os.SharedMemory;
|
||||
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;
|
||||
@@ -56,6 +54,21 @@ abstract public class VerityUtils {
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
/** Returns whether the file has fs-verity enabled. */
|
||||
public static boolean hasFsverity(@NonNull String filePath) {
|
||||
// NB: only measure but not check the actual measurement here. As long as this succeeds,
|
||||
// the file is on readable if the measurement can be verified against a trusted key, and
|
||||
// this is good enough for installed apps.
|
||||
int errno = measureFsverityNative(filePath);
|
||||
if (errno != 0) {
|
||||
if (errno != OsConstants.ENODATA) {
|
||||
Slog.e(TAG, "Failed to measure fs-verity, errno " + errno + ": " + filePath);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates Merkle tree and fs-verity metadata.
|
||||
*
|
||||
@@ -213,6 +226,7 @@ abstract public class VerityUtils {
|
||||
return md.digest();
|
||||
}
|
||||
|
||||
private static native int measureFsverityNative(@NonNull String filePath);
|
||||
private static native byte[] constructFsveritySignedDataNative(@NonNull byte[] measurement);
|
||||
private static native byte[] constructFsverityDescriptorNative(long fileSize);
|
||||
private static native byte[] constructFsverityExtensionNative(short extensionId,
|
||||
@@ -249,7 +263,7 @@ abstract public class VerityUtils {
|
||||
if (shm == null) {
|
||||
throw new IllegalStateException("Failed to generate verity tree into shared memory");
|
||||
}
|
||||
if (!shm.setProtect(PROT_READ)) {
|
||||
if (!shm.setProtect(OsConstants.PROT_READ)) {
|
||||
throw new SecurityException("Failed to set up shared memory correctly");
|
||||
}
|
||||
return Pair.create(shm, contentSize);
|
||||
@@ -323,7 +337,7 @@ abstract public class VerityUtils {
|
||||
throw new IllegalStateException("Multiple instantiation from this factory");
|
||||
}
|
||||
mShm = SharedMemory.create("apkverity", capacity);
|
||||
if (!mShm.setProtect(PROT_READ | PROT_WRITE)) {
|
||||
if (!mShm.setProtect(OsConstants.PROT_READ | OsConstants.PROT_WRITE)) {
|
||||
throw new SecurityException("Failed to set protection");
|
||||
}
|
||||
mBuffer = mShm.mapReadWrite();
|
||||
|
||||
@@ -20,13 +20,22 @@
|
||||
#include "jni.h"
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
// TODO(112037636): Always include once fsverity.h is upstreamed and backported.
|
||||
#define HAS_FSVERITY 0
|
||||
|
||||
#if HAS_FSVERITY
|
||||
#include <linux/fsverity.h>
|
||||
|
||||
const int kSha256Bytes = 32;
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
@@ -66,9 +75,26 @@ class JavaByteArrayHolder {
|
||||
jbyte* mElements;
|
||||
};
|
||||
|
||||
int measureFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) {
|
||||
#if HAS_FSVERITY
|
||||
auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest) + kSha256Bytes);
|
||||
fsverity_digest* data = reinterpret_cast<fsverity_digest*>(raii->getRaw());
|
||||
data->digest_size = kSha256Bytes; // the only input/output parameter
|
||||
|
||||
const char* path = env->GetStringUTFChars(filePath, nullptr);
|
||||
::android::base::unique_fd rfd(open(path, O_RDONLY));
|
||||
if (ioctl(rfd.get(), FS_IOC_MEASURE_VERITY, data) < 0) {
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
LOG_ALWAYS_FATAL("fs-verity is used while not enabled");
|
||||
return -1;
|
||||
#endif // HAS_FSVERITY
|
||||
}
|
||||
|
||||
jbyteArray constructFsveritySignedData(JNIEnv* env, jobject /* clazz */, jbyteArray digest) {
|
||||
#if HAS_FSVERITY
|
||||
const int kSha256Bytes = 32;
|
||||
auto raii = JavaByteArrayHolder::newArray(env, sizeof(fsverity_digest_disk) + kSha256Bytes);
|
||||
fsverity_digest_disk* data = reinterpret_cast<fsverity_digest_disk*>(raii->getRaw());
|
||||
|
||||
@@ -146,6 +172,7 @@ jbyteArray constructFsverityFooter(JNIEnv* env, jobject /* clazz */,
|
||||
}
|
||||
|
||||
const JNINativeMethod sMethods[] = {
|
||||
{ "measureFsverityNative", "(Ljava/lang/String;)I", (void *)measureFsverity },
|
||||
{ "constructFsveritySignedDataNative", "([B)[B", (void *)constructFsveritySignedData },
|
||||
{ "constructFsverityDescriptorNative", "(J)[B", (void *)constructFsverityDescriptor },
|
||||
{ "constructFsverityExtensionNative", "(SI)[B", (void *)constructFsverityExtension },
|
||||
|
||||
Reference in New Issue
Block a user