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

Commit c6d738a3 authored by Victor Hsieh's avatar Victor Hsieh
Browse files

installd: implement measureFsverityRootHash

Test: Observed to ioctl, will soon integrate with the actual ioctl
Bug: 30972906

Change-Id: I30729abbdc540093d2b33d0451a29c5bbf0fb83d
parent 57188c67
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#define ATRACE_TAG ATRACE_TAG_PACKAGE_MANAGER

#include <algorithm>
#include <errno.h>
#include <fstream>
#include <fts.h>
@@ -90,6 +91,7 @@ static constexpr const char* IDMAP_SUFFIX = "@idmap";
// fsverity assumes the page size is always 4096. If not, the feature can not be
// enabled.
static constexpr int kVerityPageSize = 4096;
static constexpr size_t kSha256Size = 32;
static constexpr const char* kPropApkVerityMode = "ro.apk_verity.mode";

// NOTE: keep in sync with Installer
@@ -2357,6 +2359,14 @@ struct fsverity_set {
    __u64 flags;
};

struct fsverity_root_hash {
    short root_hash_algorithm;
    short flags;
    __u8 reserved[4];
    __u8 root_hash[64];
};

#define FS_IOC_MEASURE_FSVERITY        _IOW('f', 2733, struct fsverity_root_hash)
#define FS_IOC_SET_FSVERITY            _IOW('f', 2734, struct fsverity_set)

#define FSVERITY_FLAG_ENABLED          0x0001
@@ -2423,6 +2433,36 @@ binder::Status InstalldNativeService::installApkVerity(const std::string& filePa
    return ok();
}

binder::Status InstalldNativeService::assertFsverityRootHashMatches(const std::string& filePath,
        const std::vector<uint8_t>& expectedHash) {
    ENFORCE_UID(AID_SYSTEM);
    if (!android::base::GetBoolProperty(kPropApkVerityMode, false)) {
        return ok();
    }
    // TODO: also check fsverity support in the current file system if compiled with DEBUG.
    if (expectedHash.size() != kSha256Size) {
        return error("verity hash size should be " + std::to_string(kSha256Size) + " but is " +
                     std::to_string(expectedHash.size()));
    }

    // TODO(71871109): Validate filePath.
    ::android::base::unique_fd fd(open(filePath.c_str(), O_RDONLY));
    if (fd.get() < 0) {
        return error("Failed to open " + filePath + ": " + strerror(errno));
    }

    struct fsverity_root_hash config;
    memset(&config, 0, sizeof(config));
    config.root_hash_algorithm = 0;  // SHA256
    memcpy(config.root_hash, expectedHash.data(), std::min(sizeof(config.root_hash), kSha256Size));
    if (ioctl(fd.get(), FS_IOC_MEASURE_FSVERITY, &config) < 0) {
        // This includes an expected failure case with no FSVerity setup. It normally happens when
        // the apk does not contains the Merkle tree root hash.
        return error("Failed to measure fsverity on " + filePath + ": " + strerror(errno));
    }
    return ok();  // hashes match
}

binder::Status InstalldNativeService::reconcileSecondaryDexFile(
        const std::string& dexPath, const std::string& packageName, int32_t uid,
        const std::vector<std::string>& isas, const std::unique_ptr<std::string>& volumeUuid,
+2 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ public:
            const std::unique_ptr<std::string>& outputPath);
    binder::Status installApkVerity(const std::string& filePath,
            const ::android::base::unique_fd& verityInput);
    binder::Status assertFsverityRootHashMatches(const std::string& filePath,
            const std::vector<uint8_t>& expectedHash);
    binder::Status reconcileSecondaryDexFile(const std::string& dexPath,
        const std::string& packageName, int32_t uid, const std::vector<std::string>& isa,
        const std::unique_ptr<std::string>& volumeUuid, int32_t storage_flag, bool* _aidl_return);
+1 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ interface IInstalld {
    void deleteOdex(@utf8InCpp String apkPath, @utf8InCpp String instructionSet,
            @nullable @utf8InCpp String outputPath);
    void installApkVerity(@utf8InCpp String filePath, in FileDescriptor verityInput);
    void assertFsverityRootHashMatches(@utf8InCpp String filePath, in byte[] expectedHash);

    boolean reconcileSecondaryDexFile(@utf8InCpp String dexPath, @utf8InCpp String pkgName,
        int uid, in @utf8InCpp String[] isas, @nullable @utf8InCpp String volume_uuid,