summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Victor Hsieh <victorhsieh@google.com> 2018-01-20 15:06:39 -0800
committer Victor Hsieh <victorhsieh@google.com> 2018-01-23 07:47:49 -0800
commitc6d738a320a612454e6c7588affcfb1f8886dd8c (patch)
tree6f8b074207a3ea60e4cb004f2b8fe9f25f64de2e
parent57188c67b60d7d97fd5908ea08d5d558fe3b3abf (diff)
installd: implement measureFsverityRootHash
Test: Observed to ioctl, will soon integrate with the actual ioctl Bug: 30972906 Change-Id: I30729abbdc540093d2b33d0451a29c5bbf0fb83d
-rw-r--r--cmds/installd/InstalldNativeService.cpp40
-rw-r--r--cmds/installd/InstalldNativeService.h2
-rw-r--r--cmds/installd/binder/android/os/IInstalld.aidl1
3 files changed, 43 insertions, 0 deletions
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 1627756490..bc91285ef4 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -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,
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index cef62cde5e..887a2fc372 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -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);
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index c819e98d89..3725fc01eb 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -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,