Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bfe6900f authored by Ricardo Quesada's avatar Ricardo Quesada
Browse files

fs-verity: replace ioctl(FS_IOC_MEASURE_VERITY) with statx()

This CL replaces the open(file) + ioctl(FS_IOC_MEASURE_VERITY) with
statx() to improve performance. This is because opening fs-verity files
is expensive.

This CL assumes that statx(STATX_ATTR_VERITY) is supported by the kernel.
This is the case for all the Android common kernels that support
fs-verity.

Bug: 146676114
Test: atest com.android.apkverity.ApkVerityTest
      All 17 tests passed
      Tested on Cuttlefish.
Change-Id: I21c70132682c0d4ae6922419b269aa9f5de2fb72
parent bac0268f
Loading
Loading
Loading
Loading
+6 −10
Original line number Diff line number Diff line
@@ -81,22 +81,18 @@ abstract public class VerityUtils {

    /** 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);
            }
        int retval = statxForFsverityNative(filePath);
        if (retval < 0) {
            Slog.e(TAG, "Failed to check whether fs-verity is enabled, errno " + -retval + ": "
                    + filePath);
            return false;
        }
        return true;
        return (retval == 1);
    }

    private static native int enableFsverityNative(@NonNull String filePath,
            @NonNull byte[] pkcs7Signature);
    private static native int measureFsverityNative(@NonNull String filePath);
    private static native int statxForFsverityNative(@NonNull String filePath);

    /**
     * Generates legacy Merkle tree and fs-verity metadata with Signing Block skipped.
+17 −22
Original line number Diff line number Diff line
@@ -25,17 +25,14 @@
#include <errno.h>
#include <fcntl.h>
#include <linux/fsverity.h>
#include <linux/stat.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <type_traits>

#include <android-base/unique_fd.h>

const int kSha256Bytes = 32;

namespace android {

namespace {
@@ -69,30 +66,28 @@ int enableFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath, jbyteArra
    return 0;
}

int measureFsverity(JNIEnv* env, jobject /* clazz */, jstring filePath) {
    using Storage = std::aligned_storage_t<sizeof(fsverity_digest) + kSha256Bytes>;

    Storage bytes;
    fsverity_digest *data = reinterpret_cast<fsverity_digest *>(&bytes);
    data->digest_size = kSha256Bytes;  // the only input/output parameter

// Returns whether the file has fs-verity enabled.
// 0 if it is not present, 1 if is present, and -errno if there was an error.
int statxForFsverity(JNIEnv *env, jobject /* clazz */, jstring filePath) {
    ScopedUtfChars path(env, filePath);
    if (path.c_str() == nullptr) {
        return EINVAL;
    }
    ::android::base::unique_fd rfd(open(path.c_str(), O_RDONLY | O_CLOEXEC));
    if (rfd.get() < 0) {
        return errno;

    struct statx out = {};
    if (statx(AT_FDCWD, path.c_str(), 0 /* flags */, STATX_ALL, &out) != 0) {
        return -errno;
    }
    if (ioctl(rfd.get(), FS_IOC_MEASURE_VERITY, data) < 0) {
        return errno;

    // Sanity check.
    if ((out.stx_attributes_mask & STATX_ATTR_VERITY) == 0) {
        ALOGE("Unexpected, STATX_ATTR_VERITY not supported by kernel");
        return -ENOSYS;
    }
    return 0;

    return (out.stx_attributes & STATX_ATTR_VERITY) != 0;
}

const JNINativeMethod sMethods[] = {
        {"enableFsverityNative", "(Ljava/lang/String;[B)I", (void *)enableFsverity},
    { "measureFsverityNative", "(Ljava/lang/String;)I", (void *)measureFsverity },
        {"statxForFsverityNative", "(Ljava/lang/String;)I", (void *)statxForFsverity},
};

}  // namespace