Merge "Provide a way to query fs-verity status"

This commit is contained in:
TreeHugger Robot
2018-12-28 00:24:35 +00:00
committed by Android (Google) Code Review
2 changed files with 47 additions and 6 deletions

View File

@@ -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();

View File

@@ -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 },