Merge "Revert "Send property_service AVC messages to the kernel audit system"" into oc-dev
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 120129c..ea9cb37 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -31,7 +31,10 @@
#include <time.h>
#include <unistd.h>
+#include <memory>
+
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
#include <cutils/android_reboot.h>
@@ -47,8 +50,10 @@
#include <logwrap/logwrap.h>
#include <private/android_logger.h> // for __android_log_is_debuggable()
+#include "fs_mgr.h"
+#include "fs_mgr_avb.h"
#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_avb.h"
+#include "fs_mgr_priv_dm_ioctl.h"
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
#define KEY_IN_FOOTER "footer"
@@ -707,6 +712,23 @@
}
}
+static std::string extract_by_name_prefix(struct fstab* fstab) {
+ // We assume that there's an entry for the /misc mount point in the
+ // fstab file and use that to get the device file by-name prefix.
+ // The device needs not to have an actual /misc partition.
+ // e.g.,
+ // - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
+ // - /dev/block/platform/soc.0/7824900.sdhci/by-name/
+ struct fstab_rec* fstab_entry = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
+ if (fstab_entry == nullptr) {
+ LERROR << "/misc mount point not found in fstab";
+ return "";
+ }
+ std::string full_path(fstab_entry->blk_device);
+ size_t end_slash = full_path.find_last_of("/");
+ return full_path.substr(0, end_slash + 1);
+}
+
// TODO: add ueventd notifiers if they don't exist.
// This is just doing a wait_for_device for maximum of 1s
int fs_mgr_test_access(const char *device) {
@@ -750,17 +772,12 @@
int mret = -1;
int mount_errno = 0;
int attempted_idx = -1;
- int avb_ret = FS_MGR_SETUP_AVB_FAIL;
+ FsManagerAvbUniquePtr avb_handle(nullptr);
if (!fstab) {
return -1;
}
- if (fs_mgr_is_avb_used() &&
- (avb_ret = fs_mgr_load_vbmeta_images(fstab)) == FS_MGR_SETUP_AVB_FAIL) {
- return -1;
- }
-
for (i = 0; i < fstab->num_entries; i++) {
/* Don't mount entries that are managed by vold or not for the mount mode*/
if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) ||
@@ -799,16 +816,15 @@
wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
}
- if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) {
- /* If HASHTREE_DISABLED is set (cf. 'adb disable-verity'), we
- * should set up the device without using dm-verity.
- * The actual mounting still take place in the following
- * mount_with_alternatives().
- */
- if (avb_ret == FS_MGR_SETUP_AVB_HASHTREE_DISABLED) {
- LINFO << "AVB HASHTREE disabled";
- } else if (fs_mgr_setup_avb(&fstab->recs[i]) !=
- FS_MGR_SETUP_AVB_SUCCESS) {
+ if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
+ if (!avb_handle) {
+ avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab));
+ if (!avb_handle) {
+ LERROR << "Failed to open FsManagerAvbHandle";
+ return -1;
+ }
+ }
+ if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) {
LERROR << "Failed to set up AVB on partition: "
<< fstab->recs[i].mount_point << ", skipping!";
/* Skips mounting the device. */
@@ -934,10 +950,6 @@
}
}
- if (fs_mgr_is_avb_used()) {
- fs_mgr_unload_vbmeta_images();
- }
-
if (error_count) {
return -1;
} else {
@@ -976,17 +988,12 @@
int mount_errors = 0;
int first_mount_errno = 0;
char *m;
- int avb_ret = FS_MGR_SETUP_AVB_FAIL;
+ FsManagerAvbUniquePtr avb_handle(nullptr);
if (!fstab) {
return ret;
}
- if (fs_mgr_is_avb_used() &&
- (avb_ret = fs_mgr_load_vbmeta_images(fstab)) == FS_MGR_SETUP_AVB_FAIL) {
- return ret;
- }
-
for (i = 0; i < fstab->num_entries; i++) {
if (!fs_match(fstab->recs[i].mount_point, n_name)) {
continue;
@@ -1021,16 +1028,15 @@
do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i], &fs_stat);
}
- if (fs_mgr_is_avb_used() && (fstab->recs[i].fs_mgr_flags & MF_AVB)) {
- /* If HASHTREE_DISABLED is set (cf. 'adb disable-verity'), we
- * should set up the device without using dm-verity.
- * The actual mounting still take place in the following
- * mount_with_alternatives().
- */
- if (avb_ret == FS_MGR_SETUP_AVB_HASHTREE_DISABLED) {
- LINFO << "AVB HASHTREE disabled";
- } else if (fs_mgr_setup_avb(&fstab->recs[i]) !=
- FS_MGR_SETUP_AVB_SUCCESS) {
+ if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
+ if (!avb_handle) {
+ avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab));
+ if (!avb_handle) {
+ LERROR << "Failed to open FsManagerAvbHandle";
+ return -1;
+ }
+ }
+ if (!avb_handle->SetUpAvb(&fstab->recs[i], true /* wait_for_verity_dev */)) {
LERROR << "Failed to set up AVB on partition: "
<< fstab->recs[i].mount_point << ", skipping!";
/* Skips mounting the device. */
@@ -1079,9 +1085,6 @@
}
out:
- if (fs_mgr_is_avb_used()) {
- fs_mgr_unload_vbmeta_images();
- }
return ret;
}
@@ -1259,3 +1262,97 @@
return 0;
}
+
+bool fs_mgr_load_verity_state(int* mode) {
+ /* return the default mode, unless any of the verified partitions are in
+ * logging mode, in which case return that */
+ *mode = VERITY_MODE_DEFAULT;
+
+ std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
+ fs_mgr_free_fstab);
+ if (!fstab) {
+ LERROR << "Failed to read default fstab";
+ return false;
+ }
+
+ for (int i = 0; i < fstab->num_entries; i++) {
+ if (fs_mgr_is_avb(&fstab->recs[i])) {
+ *mode = VERITY_MODE_RESTART; // avb only supports restart mode.
+ break;
+ } else if (!fs_mgr_is_verified(&fstab->recs[i])) {
+ continue;
+ }
+
+ int current;
+ if (load_verity_state(&fstab->recs[i], ¤t) < 0) {
+ continue;
+ }
+ if (current != VERITY_MODE_DEFAULT) {
+ *mode = current;
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) {
+ if (!callback) {
+ return false;
+ }
+
+ int mode;
+ if (!fs_mgr_load_verity_state(&mode)) {
+ return false;
+ }
+
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)));
+ if (fd == -1) {
+ PERROR << "Error opening device mapper";
+ return false;
+ }
+
+ std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
+ fs_mgr_free_fstab);
+ if (!fstab) {
+ LERROR << "Failed to read default fstab";
+ return false;
+ }
+
+ alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
+ struct dm_ioctl* io = (struct dm_ioctl*)buffer;
+ bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
+
+ for (int i = 0; i < fstab->num_entries; i++) {
+ if (!fs_mgr_is_verified(&fstab->recs[i]) && !fs_mgr_is_avb(&fstab->recs[i])) {
+ continue;
+ }
+
+ std::string mount_point;
+ if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
+ mount_point = "system";
+ } else {
+ mount_point = basename(fstab->recs[i].mount_point);
+ }
+
+ fs_mgr_verity_ioctl_init(io, mount_point, 0);
+
+ const char* status;
+ if (ioctl(fd, DM_TABLE_STATUS, io)) {
+ if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
+ status = "V";
+ } else {
+ PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point.c_str();
+ continue;
+ }
+ }
+
+ status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
+
+ if (*status == 'C' || *status == 'V') {
+ callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
+ }
+ }
+
+ return true;
+}
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 7512eb9..7c82bb1 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -28,6 +28,7 @@
#include <android-base/file.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <cutils/properties.h>
@@ -37,9 +38,9 @@
#include <utils/Compat.h>
#include "fs_mgr.h"
+#include "fs_mgr_avb.h"
#include "fs_mgr_avb_ops.h"
#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_avb.h"
#include "fs_mgr_priv_dm_ioctl.h"
#include "fs_mgr_priv_sha.h"
@@ -85,24 +86,6 @@
hashtree_desc.fec_offset / hashtree_desc.data_block_size, /* fec_start */ \
VERITY_TABLE_OPT_IGNZERO, VERITY_TABLE_OPT_RESTART
-AvbSlotVerifyData* fs_mgr_avb_verify_data = nullptr;
-AvbOps* fs_mgr_avb_ops = nullptr;
-
-enum HashAlgorithm {
- kInvalid = 0,
- kSHA256 = 1,
- kSHA512 = 2,
-};
-
-struct androidboot_vbmeta {
- HashAlgorithm hash_alg;
- uint8_t digest[SHA512_DIGEST_LENGTH];
- size_t vbmeta_size;
- bool allow_verification_error;
-};
-
-androidboot_vbmeta fs_mgr_vbmeta_prop;
-
static inline bool nibble_value(const char& c, uint8_t* value) {
FS_MGR_CHECK(value != nullptr);
@@ -159,27 +142,78 @@
return hex;
}
-static bool load_vbmeta_prop(androidboot_vbmeta* vbmeta_prop) {
- FS_MGR_CHECK(vbmeta_prop != nullptr);
+template <typename Hasher>
+static std::pair<size_t, bool> verify_vbmeta_digest(const AvbSlotVerifyData& verify_data,
+ const uint8_t* expected_digest) {
+ size_t total_size = 0;
+ Hasher hasher;
+ for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) {
+ hasher.update(verify_data.vbmeta_images[n].vbmeta_data,
+ verify_data.vbmeta_images[n].vbmeta_size);
+ total_size += verify_data.vbmeta_images[n].vbmeta_size;
+ }
+ bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0);
+
+ return std::make_pair(total_size, matched);
+}
+
+// Reads the following values from kernel cmdline and provides the
+// VerifyVbmetaImages() to verify AvbSlotVerifyData.
+// - androidboot.vbmeta.device_state
+// - androidboot.vbmeta.hash_alg
+// - androidboot.vbmeta.size
+// - androidboot.vbmeta.digest
+class FsManagerAvbVerifier {
+ public:
+ // The factory method to return a unique_ptr<FsManagerAvbVerifier>
+ static std::unique_ptr<FsManagerAvbVerifier> Create();
+ bool VerifyVbmetaImages(const AvbSlotVerifyData& verify_data);
+ bool IsDeviceUnlocked() { return is_device_unlocked_; }
+
+ protected:
+ FsManagerAvbVerifier() = default;
+
+ private:
+ enum HashAlgorithm {
+ kInvalid = 0,
+ kSHA256 = 1,
+ kSHA512 = 2,
+ };
+
+ HashAlgorithm hash_alg_;
+ uint8_t digest_[SHA512_DIGEST_LENGTH];
+ size_t vbmeta_size_;
+ bool is_device_unlocked_;
+};
+
+std::unique_ptr<FsManagerAvbVerifier> FsManagerAvbVerifier::Create() {
std::string cmdline;
- android::base::ReadFileToString("/proc/cmdline", &cmdline);
+ if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) {
+ LERROR << "Failed to read /proc/cmdline";
+ return nullptr;
+ }
- std::string hash_alg;
+ std::unique_ptr<FsManagerAvbVerifier> avb_verifier(new FsManagerAvbVerifier());
+ if (!avb_verifier) {
+ LERROR << "Failed to create unique_ptr<FsManagerAvbVerifier>";
+ return nullptr;
+ }
+
std::string digest;
-
+ std::string hash_alg;
for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
std::vector<std::string> pieces = android::base::Split(entry, "=");
const std::string& key = pieces[0];
const std::string& value = pieces[1];
if (key == "androidboot.vbmeta.device_state") {
- vbmeta_prop->allow_verification_error = (value == "unlocked");
+ avb_verifier->is_device_unlocked_ = (value == "unlocked");
} else if (key == "androidboot.vbmeta.hash_alg") {
hash_alg = value;
} else if (key == "androidboot.vbmeta.size") {
- if (!android::base::ParseUint(value.c_str(), &vbmeta_prop->vbmeta_size)) {
- return false;
+ if (!android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) {
+ return nullptr;
}
} else if (key == "androidboot.vbmeta.digest") {
digest = value;
@@ -190,48 +224,31 @@
size_t expected_digest_size = 0;
if (hash_alg == "sha256") {
expected_digest_size = SHA256_DIGEST_LENGTH * 2;
- vbmeta_prop->hash_alg = kSHA256;
+ avb_verifier->hash_alg_ = kSHA256;
} else if (hash_alg == "sha512") {
expected_digest_size = SHA512_DIGEST_LENGTH * 2;
- vbmeta_prop->hash_alg = kSHA512;
+ avb_verifier->hash_alg_ = kSHA512;
} else {
LERROR << "Unknown hash algorithm: " << hash_alg.c_str();
- return false;
+ return nullptr;
}
// Reads digest.
if (digest.size() != expected_digest_size) {
LERROR << "Unexpected digest size: " << digest.size()
<< " (expected: " << expected_digest_size << ")";
- return false;
+ return nullptr;
}
- if (!hex_to_bytes(vbmeta_prop->digest, sizeof(vbmeta_prop->digest), digest)) {
+ if (!hex_to_bytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) {
LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str();
- return false;
+ return nullptr;
}
- return true;
+ return avb_verifier;
}
-template <typename Hasher>
-static std::pair<size_t, bool> verify_vbmeta_digest(const AvbSlotVerifyData& verify_data,
- const androidboot_vbmeta& vbmeta_prop) {
- size_t total_size = 0;
- Hasher hasher;
- for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) {
- hasher.update(verify_data.vbmeta_images[n].vbmeta_data,
- verify_data.vbmeta_images[n].vbmeta_size);
- total_size += verify_data.vbmeta_images[n].vbmeta_size;
- }
-
- bool matched = (memcmp(hasher.finalize(), vbmeta_prop.digest, Hasher::DIGEST_SIZE) == 0);
-
- return std::make_pair(total_size, matched);
-}
-
-static bool verify_vbmeta_images(const AvbSlotVerifyData& verify_data,
- const androidboot_vbmeta& vbmeta_prop) {
+bool FsManagerAvbVerifier::VerifyVbmetaImages(const AvbSlotVerifyData& verify_data) {
if (verify_data.num_vbmeta_images == 0) {
LERROR << "No vbmeta images";
return false;
@@ -240,17 +257,17 @@
size_t total_size = 0;
bool digest_matched = false;
- if (vbmeta_prop.hash_alg == kSHA256) {
+ if (hash_alg_ == kSHA256) {
std::tie(total_size, digest_matched) =
- verify_vbmeta_digest<SHA256Hasher>(verify_data, vbmeta_prop);
- } else if (vbmeta_prop.hash_alg == kSHA512) {
+ verify_vbmeta_digest<SHA256Hasher>(verify_data, digest_);
+ } else if (hash_alg_ == kSHA512) {
std::tie(total_size, digest_matched) =
- verify_vbmeta_digest<SHA512Hasher>(verify_data, vbmeta_prop);
+ verify_vbmeta_digest<SHA512Hasher>(verify_data, digest_);
}
- if (total_size != vbmeta_prop.vbmeta_size) {
- LERROR << "total vbmeta size mismatch: " << total_size
- << " (expected: " << vbmeta_prop.vbmeta_size << ")";
+ if (total_size != vbmeta_size_) {
+ LERROR << "total vbmeta size mismatch: " << total_size << " (expected: " << vbmeta_size_
+ << ")";
return false;
}
@@ -319,7 +336,8 @@
static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry,
const AvbHashtreeDescriptor& hashtree_desc,
- const std::string& salt, const std::string& root_digest) {
+ const std::string& salt, const std::string& root_digest,
+ bool wait_for_verity_dev) {
// Gets the device mapper fd.
android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR));
if (fd < 0) {
@@ -358,13 +376,12 @@
// Marks the underlying block device as read-only.
fs_mgr_set_blk_ro(fstab_entry->blk_device);
- // TODO(bowgotsai): support verified all partition at boot.
// Updates fstab_rec->blk_device to verity device name.
free(fstab_entry->blk_device);
fstab_entry->blk_device = strdup(verity_blk_name.c_str());
// Makes sure we've set everything up properly.
- if (fs_mgr_test_access(verity_blk_name.c_str()) < 0) {
+ if (wait_for_verity_dev && fs_mgr_test_access(verity_blk_name.c_str()) < 0) {
return false;
}
@@ -408,8 +425,7 @@
continue;
}
if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) {
- desc_partition_name =
- (const uint8_t*)descriptors[j] + sizeof(AvbHashtreeDescriptor);
+ desc_partition_name = (const uint8_t*)descriptors[j] + sizeof(AvbHashtreeDescriptor);
if (!avb_hashtree_descriptor_validate_and_byteswap(
(AvbHashtreeDescriptor*)descriptors[j], out_hashtree_desc)) {
continue;
@@ -441,140 +457,97 @@
return true;
}
-static bool init_is_avb_used() {
- // When AVB is used, boot loader should set androidboot.vbmeta.{hash_alg,
- // size, digest} in kernel cmdline or in device tree. They will then be
- // imported by init process to system properties: ro.boot.vbmeta.{hash_alg, size, digest}.
- //
- // In case of early mount, init properties are not initialized, so we also
- // ensure we look into kernel command line and device tree if the property is
- // not found
- //
- // Checks hash_alg as an indicator for whether AVB is used.
- // We don't have to parse and check all of them here. The check will
- // be done in fs_mgr_load_vbmeta_images() and FS_MGR_SETUP_AVB_FAIL will
- // be returned when there is an error.
-
- std::string hash_alg;
- if (!fs_mgr_get_boot_config("vbmeta.hash_alg", &hash_alg)) {
- return false;
- }
- if (hash_alg == "sha256" || hash_alg == "sha512") {
- return true;
- }
- return false;
-}
-
-bool fs_mgr_is_avb_used() {
- static bool result = init_is_avb_used();
- return result;
-}
-
-int fs_mgr_load_vbmeta_images(struct fstab* fstab) {
- FS_MGR_CHECK(fstab != nullptr);
-
- // Gets the expected hash value of vbmeta images from
- // kernel cmdline.
- if (!load_vbmeta_prop(&fs_mgr_vbmeta_prop)) {
- return FS_MGR_SETUP_AVB_FAIL;
+FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by_name_prefix) {
+ if (device_file_by_name_prefix.empty()) {
+ LERROR << "Missing device file by-name prefix";
+ return nullptr;
}
- fs_mgr_avb_ops = fs_mgr_dummy_avb_ops_new(fstab);
- if (fs_mgr_avb_ops == nullptr) {
- LERROR << "Failed to allocate dummy avb_ops";
- return FS_MGR_SETUP_AVB_FAIL;
+ // Gets the expected hash value of vbmeta images from kernel cmdline.
+ std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
+ if (!avb_verifier) {
+ LERROR << "Failed to create FsManagerAvbVerifier";
+ return nullptr;
}
- // Invokes avb_slot_verify() to load and verify all vbmeta images.
- // Sets requested_partitions to nullptr as it's to copy the contents
- // of HASH partitions into fs_mgr_avb_verify_data, which is not required as
- // fs_mgr only deals with HASHTREE partitions.
- const char *requested_partitions[] = {nullptr};
- std::string ab_suffix;
- std::string slot;
- if (fs_mgr_get_boot_config("slot", &slot)) {
- ab_suffix = "_" + slot;
- } else {
- // remove slot_suffix once bootloaders update to new androidboot.slot param
- fs_mgr_get_boot_config("slot_suffix", &ab_suffix);
+ FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle());
+ if (!avb_handle) {
+ LERROR << "Failed to allocate FsManagerAvbHandle";
+ return nullptr;
}
- AvbSlotVerifyResult verify_result =
- avb_slot_verify(fs_mgr_avb_ops, requested_partitions, ab_suffix.c_str(),
- fs_mgr_vbmeta_prop.allow_verification_error, &fs_mgr_avb_verify_data);
+
+ FsManagerAvbOps avb_ops(device_file_by_name_prefix);
+ AvbSlotVerifyResult verify_result = avb_ops.AvbSlotVerify(
+ fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_);
// Only allow two verify results:
// - AVB_SLOT_VERIFY_RESULT_OK.
// - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state).
if (verify_result == AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION) {
- if (!fs_mgr_vbmeta_prop.allow_verification_error) {
+ if (!avb_verifier->IsDeviceUnlocked()) {
LERROR << "ERROR_VERIFICATION isn't allowed";
- goto fail;
+ return nullptr;
}
} else if (verify_result != AVB_SLOT_VERIFY_RESULT_OK) {
LERROR << "avb_slot_verify failed, result: " << verify_result;
- goto fail;
+ return nullptr;
}
// Verifies vbmeta images against the digest passed from bootloader.
- if (!verify_vbmeta_images(*fs_mgr_avb_verify_data, fs_mgr_vbmeta_prop)) {
- LERROR << "verify_vbmeta_images failed";
- goto fail;
+ if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) {
+ LERROR << "VerifyVbmetaImages failed";
+ return nullptr;
} else {
// Checks whether FLAGS_HASHTREE_DISABLED is set.
AvbVBMetaImageHeader vbmeta_header;
avb_vbmeta_image_header_to_host_byte_order(
- (AvbVBMetaImageHeader*)fs_mgr_avb_verify_data->vbmeta_images[0].vbmeta_data,
+ (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data,
&vbmeta_header);
bool hashtree_disabled =
((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED);
if (hashtree_disabled) {
- return FS_MGR_SETUP_AVB_HASHTREE_DISABLED;
+ avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled;
+ return avb_handle;
}
}
if (verify_result == AVB_SLOT_VERIFY_RESULT_OK) {
- return FS_MGR_SETUP_AVB_SUCCESS;
+ avb_handle->status_ = kFsManagerAvbHandleSuccess;
+ return avb_handle;
}
-
-fail:
- fs_mgr_unload_vbmeta_images();
- return FS_MGR_SETUP_AVB_FAIL;
+ return nullptr;
}
-void fs_mgr_unload_vbmeta_images() {
- if (fs_mgr_avb_verify_data != nullptr) {
- avb_slot_verify_data_free(fs_mgr_avb_verify_data);
+bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_verity_dev) {
+ if (!fstab_entry) return false;
+ if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) {
+ return false;
}
-
- if (fs_mgr_avb_ops != nullptr) {
- fs_mgr_dummy_avb_ops_free(fs_mgr_avb_ops);
+ if (status_ == kFsManagerAvbHandleHashtreeDisabled) {
+ LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point;
+ return true;
}
-}
-
-int fs_mgr_setup_avb(struct fstab_rec* fstab_entry) {
- if (!fstab_entry || !fs_mgr_avb_verify_data || fs_mgr_avb_verify_data->num_vbmeta_images < 1) {
- return FS_MGR_SETUP_AVB_FAIL;
- }
+ if (status_ != kFsManagerAvbHandleSuccess) return false;
std::string partition_name(basename(fstab_entry->mount_point));
if (!avb_validate_utf8((const uint8_t*)partition_name.c_str(), partition_name.length())) {
LERROR << "Partition name: " << partition_name.c_str() << " is not valid UTF-8.";
- return FS_MGR_SETUP_AVB_FAIL;
+ return false;
}
AvbHashtreeDescriptor hashtree_descriptor;
std::string salt;
std::string root_digest;
- if (!get_hashtree_descriptor(partition_name, *fs_mgr_avb_verify_data, &hashtree_descriptor,
- &salt, &root_digest)) {
- return FS_MGR_SETUP_AVB_FAIL;
+ if (!get_hashtree_descriptor(partition_name, *avb_slot_data_, &hashtree_descriptor, &salt,
+ &root_digest)) {
+ return false;
}
// Converts HASHTREE descriptor to verity_table_params.
- if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest)) {
- return FS_MGR_SETUP_AVB_FAIL;
+ if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest,
+ wait_for_verity_dev)) {
+ return false;
}
-
- return FS_MGR_SETUP_AVB_SUCCESS;
+ return true;
}
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp
index 8e49663..981e9fc 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -39,91 +39,10 @@
#include "fs_mgr_avb_ops.h"
#include "fs_mgr_priv.h"
-static std::string fstab_by_name_prefix;
-
-static std::string extract_by_name_prefix(struct fstab* fstab) {
- // In AVB, we can assume that there's an entry for the /misc mount
- // point in the fstab file and use that to get the device file for
- // the misc partition. The device needs not to have an actual /misc
- // partition. Then returns the prefix by removing the trailing "misc":
- //
- // - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
- // - /dev/block/platform/soc.0/7824900.sdhci/by-name/
-
- struct fstab_rec* fstab_entry = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
- if (fstab_entry == nullptr) {
- LERROR << "/misc mount point not found in fstab";
- return "";
- }
-
- std::string full_path(fstab_entry->blk_device);
- size_t end_slash = full_path.find_last_of("/");
-
- return full_path.substr(0, end_slash + 1);
-}
-
-static AvbIOResult read_from_partition(AvbOps* ops ATTRIBUTE_UNUSED, const char* partition,
- int64_t offset, size_t num_bytes, void* buffer,
- size_t* out_num_read) {
- // The input |partition| name is with ab_suffix, e.g. system_a.
- // Slot suffix (e.g. _a) will be appended to the device file path
- // for partitions having 'slotselect' optin in fstab file, but it
- // won't be appended to the mount point.
- //
- // Appends |partition| to the fstab_by_name_prefix, which is obtained
- // by removing the trailing "misc" from the device file of /misc mount
- // point. e.g.,
- //
- // - /dev/block/platform/soc.0/7824900.sdhci/by-name/ ->
- // - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a
-
- std::string path = fstab_by_name_prefix + partition;
-
- // Ensures the device path (a symlink created by init) is ready to
- // access. fs_mgr_test_access() will test a few iterations if the
- // path doesn't exist yet.
- if (fs_mgr_test_access(path.c_str()) < 0) {
- return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
- }
-
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
-
- if (fd < 0) {
- PERROR << "Failed to open " << path.c_str();
- return AVB_IO_RESULT_ERROR_IO;
- }
-
- // If offset is negative, interprets its absolute value as the
- // number of bytes from the end of the partition.
- if (offset < 0) {
- off64_t total_size = lseek64(fd, 0, SEEK_END);
- if (total_size == -1) {
- LERROR << "Failed to lseek64 to end of the partition";
- return AVB_IO_RESULT_ERROR_IO;
- }
- offset = total_size + offset;
- // Repositions the offset to the beginning.
- if (lseek64(fd, 0, SEEK_SET) == -1) {
- LERROR << "Failed to lseek64 to the beginning of the partition";
- return AVB_IO_RESULT_ERROR_IO;
- }
- }
-
- // On Linux, we never get partial reads from block devices (except
- // for EOF).
- ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));
-
- if (num_read < 0 || (size_t)num_read != num_bytes) {
- PERROR << "Failed to read " << num_bytes << " bytes from " << path.c_str() << " offset "
- << offset;
- return AVB_IO_RESULT_ERROR_IO;
- }
-
- if (out_num_read != nullptr) {
- *out_num_read = num_read;
- }
-
- return AVB_IO_RESULT_OK;
+static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset,
+ size_t num_bytes, void* buffer, size_t* out_num_read) {
+ return FsManagerAvbOps::GetInstanceFromAvbOps(ops)->ReadFromPartition(
+ partition, offset, num_bytes, buffer, out_num_read);
}
static AvbIOResult dummy_read_rollback_index(AvbOps* ops ATTRIBUTE_UNUSED,
@@ -145,7 +64,6 @@
// Addtionally, user-space should check
// androidboot.vbmeta.{hash_alg, size, digest} against the digest
// of all vbmeta images after invoking avb_slot_verify().
-
*out_is_trusted = true;
return AVB_IO_RESULT_OK;
}
@@ -170,28 +88,86 @@
return AVB_IO_RESULT_OK;
}
-AvbOps* fs_mgr_dummy_avb_ops_new(struct fstab* fstab) {
- AvbOps* ops;
-
- fstab_by_name_prefix = extract_by_name_prefix(fstab);
- if (fstab_by_name_prefix.empty()) return nullptr;
-
- ops = (AvbOps*)calloc(1, sizeof(AvbOps));
- if (ops == nullptr) {
- LERROR << "Error allocating memory for AvbOps";
- return nullptr;
+FsManagerAvbOps::FsManagerAvbOps(const std::string& device_file_by_name_prefix)
+ : device_file_by_name_prefix_(device_file_by_name_prefix) {
+ if (device_file_by_name_prefix_.back() != '/') {
+ device_file_by_name_prefix_ += '/';
}
+ // We only need to provide the implementation of read_from_partition()
+ // operation since that's all what is being used by the avb_slot_verify().
+ // Other I/O operations are only required in bootloader but not in
+ // user-space so we set them as dummy operations.
+ avb_ops_.read_from_partition = read_from_partition;
+ avb_ops_.read_rollback_index = dummy_read_rollback_index;
+ avb_ops_.validate_vbmeta_public_key = dummy_validate_vbmeta_public_key;
+ avb_ops_.read_is_device_unlocked = dummy_read_is_device_unlocked;
+ avb_ops_.get_unique_guid_for_partition = dummy_get_unique_guid_for_partition;
- // We only need these operations since that's all what is being used
- // by the avb_slot_verify(); Most of them are dummy operations because
- // they're only required in bootloader but not required in user-space.
- ops->read_from_partition = read_from_partition;
- ops->read_rollback_index = dummy_read_rollback_index;
- ops->validate_vbmeta_public_key = dummy_validate_vbmeta_public_key;
- ops->read_is_device_unlocked = dummy_read_is_device_unlocked;
- ops->get_unique_guid_for_partition = dummy_get_unique_guid_for_partition;
-
- return ops;
+ // Sets user_data for GetInstanceFromAvbOps() to convert it back to FsManagerAvbOps.
+ avb_ops_.user_data = this;
}
-void fs_mgr_dummy_avb_ops_free(AvbOps* ops) { free(ops); }
+AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
+ size_t num_bytes, void* buffer,
+ size_t* out_num_read) {
+ // Appends |partition| to the device_file_by_name_prefix_, e.g.,
+ // - /dev/block/platform/soc.0/7824900.sdhci/by-name/ ->
+ // - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a
+ std::string path = device_file_by_name_prefix_ + partition;
+
+ // Ensures the device path (a symlink created by init) is ready to
+ // access. fs_mgr_test_access() will test a few iterations if the
+ // path doesn't exist yet.
+ if (fs_mgr_test_access(path.c_str()) < 0) {
+ return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+ }
+
+ android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
+ if (fd < 0) {
+ PERROR << "Failed to open " << path.c_str();
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ // If offset is negative, interprets its absolute value as the
+ // number of bytes from the end of the partition.
+ if (offset < 0) {
+ off64_t total_size = lseek64(fd, 0, SEEK_END);
+ if (total_size == -1) {
+ LERROR << "Failed to lseek64 to end of the partition";
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ offset = total_size + offset;
+ // Repositions the offset to the beginning.
+ if (lseek64(fd, 0, SEEK_SET) == -1) {
+ LERROR << "Failed to lseek64 to the beginning of the partition";
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+ }
+
+ // On Linux, we never get partial reads from block devices (except
+ // for EOF).
+ ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));
+ if (num_read < 0 || (size_t)num_read != num_bytes) {
+ PERROR << "Failed to read " << num_bytes << " bytes from " << path.c_str() << " offset "
+ << offset;
+ return AVB_IO_RESULT_ERROR_IO;
+ }
+
+ if (out_num_read != nullptr) {
+ *out_num_read = num_read;
+ }
+
+ return AVB_IO_RESULT_OK;
+}
+
+AvbSlotVerifyResult FsManagerAvbOps::AvbSlotVerify(const std::string& ab_suffix,
+ bool allow_verification_error,
+ AvbSlotVerifyData** out_data) {
+ // Invokes avb_slot_verify() to load and verify all vbmeta images.
+ // Sets requested_partitions to nullptr as it's to copy the contents
+ // of HASH partitions into handle>avb_slot_data_, which is not required as
+ // fs_mgr only deals with HASHTREE partitions.
+ const char* requested_partitions[] = {nullptr};
+ return avb_slot_verify(&avb_ops_, requested_partitions, ab_suffix.c_str(),
+ allow_verification_error, out_data);
+}
diff --git a/fs_mgr/fs_mgr_avb_ops.h b/fs_mgr/fs_mgr_avb_ops.h
index bfdec9a..ec4a8c9 100644
--- a/fs_mgr/fs_mgr_avb_ops.h
+++ b/fs_mgr/fs_mgr_avb_ops.h
@@ -29,31 +29,34 @@
#include "fs_mgr.h"
-__BEGIN_DECLS
+// This class provides C++ bindings to interact with libavb, a small
+// self-contained piece of code that's intended to be used in bootloaders.
+// It mainly contains two functions:
+// - ReadFromPartition(): to read AVB metadata from a given partition.
+// It provides the implementation of AvbOps.read_from_partition() when
+// reading metadata through libavb.
+// - AvbSlotVerify(): the C++ binding of libavb->avb_slot_verify() to
+// read and verify the metadata and store it into the out_data parameter.
+// The caller MUST check the integrity of metadata against the
+// androidboot.vbmeta.{hash_alg, size, digest} values from /proc/cmdline.
+// e.g., see class FsManagerAvbVerifier for more details.
+//
+class FsManagerAvbOps {
+ public:
+ FsManagerAvbOps(const std::string& device_file_by_name_prefix);
-/* Allocates a "dummy" AvbOps instance solely for use in user-space.
- * Returns nullptr on OOM.
- *
- * It mainly provides read_from_partitions() for user-space to get
- * AvbSlotVerifyData.vbmeta_images[] and the caller MUST check their
- * integrity against the androidboot.vbmeta.{hash_alg, size, digest}
- * values from /proc/cmdline, e.g. verify_vbmeta_images()
- * in fs_mgr_avb.cpp.
- *
- * Other I/O operations are only required in boot loader so we set
- * them as dummy operations here.
- * - Will allow any public key for signing.
- * - returns 0 for any rollback index location.
- * - returns device is unlocked regardless of the actual state.
- * - returns a dummy guid for any partition.
- *
- * Frees with fs_mgr_dummy_avb_ops_free().
- */
-AvbOps* fs_mgr_dummy_avb_ops_new(struct fstab* fstab);
+ static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) {
+ return reinterpret_cast<FsManagerAvbOps*>(ops->user_data);
+ }
-/* Frees an AvbOps instance previously allocated with fs_mgr_avb_ops_new(). */
-void fs_mgr_dummy_avb_ops_free(AvbOps* ops);
+ AvbIOResult ReadFromPartition(const char* partition, int64_t offset, size_t num_bytes,
+ void* buffer, size_t* out_num_read);
-__END_DECLS
+ AvbSlotVerifyResult AvbSlotVerify(const std::string& ab_suffix, bool allow_verification_error,
+ AvbSlotVerifyData** out_data);
+ private:
+ AvbOps avb_ops_;
+ std::string device_file_by_name_prefix_;
+};
#endif /* __CORE_FS_MGR_AVB_OPS_H */
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index a9a0df7..0a694c1 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -572,7 +572,7 @@
cnt++;
}
/* If an A/B partition, modify block device to be the real block device */
- if (fs_mgr_update_for_slotselect(fstab) != 0) {
+ if (!fs_mgr_update_for_slotselect(fstab)) {
LERROR << "Error updating for slotselect";
goto err;
}
@@ -814,6 +814,11 @@
return fstab->fs_mgr_flags & MF_VERIFY;
}
+int fs_mgr_is_avb(const struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_AVB;
+}
+
int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab)
{
return fstab->fs_mgr_flags & MF_VERIFYATBOOT;
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 377d2ec..c985462 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -41,8 +41,6 @@
#define PWARNING PLOG(WARNING) << FS_MGR_TAG
#define PERROR PLOG(ERROR) << FS_MGR_TAG
-__BEGIN_DECLS
-
#define CRYPTO_TMPFS_OPTIONS "size=256m,mode=0771,uid=1000,gid=1000"
#define WAIT_TIMEOUT 20
@@ -114,10 +112,9 @@
int fs_mgr_set_blk_ro(const char *blockdev);
int fs_mgr_test_access(const char *device);
-int fs_mgr_update_for_slotselect(struct fstab *fstab);
+bool fs_mgr_update_for_slotselect(struct fstab *fstab);
bool is_dt_compatible();
bool is_device_secure();
-
-__END_DECLS
+int load_verity_state(struct fstab_rec* fstab, int* mode);
#endif /* __CORE_FS_MGR_PRIV_H */
diff --git a/fs_mgr/fs_mgr_priv_avb.h b/fs_mgr/fs_mgr_priv_avb.h
deleted file mode 100644
index dce9f61..0000000
--- a/fs_mgr/fs_mgr_priv_avb.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __CORE_FS_MGR_PRIV_AVB_H
-#define __CORE_FS_MGR_PRIV_AVB_H
-
-#ifndef __cplusplus
-#include <stdbool.h>
-#endif
-
-#include "fs_mgr.h"
-
-__BEGIN_DECLS
-
-#define FS_MGR_SETUP_AVB_HASHTREE_DISABLED (-2)
-#define FS_MGR_SETUP_AVB_FAIL (-1)
-#define FS_MGR_SETUP_AVB_SUCCESS 0
-
-bool fs_mgr_is_avb_used();
-
-/* Gets AVB metadata through external/avb/libavb for all partitions:
- * AvbSlotVerifyData.vbmeta_images[] and checks their integrity
- * against the androidboot.vbmeta.{hash_alg, size, digest} values
- * from /proc/cmdline.
- *
- * Return values:
- * - FS_MGR_SETUP_AVB_SUCCESS: the metadata cab be trusted.
- * - FS_MGR_SETUP_AVB_FAIL: any error when reading and verifying the
- * metadata, e.g. I/O error, digest value mismatch, size mismatch.
- * - FS_MGR_SETUP_AVB_HASHTREE_DISABLED: to support the existing
- * 'adb disable-verity' feature in Android. It's very helpful for
- * developers to make the filesystem writable to allow replacing
- * binaries on the device.
- */
-int fs_mgr_load_vbmeta_images(struct fstab* fstab);
-
-void fs_mgr_unload_vbmeta_images();
-
-int fs_mgr_setup_avb(struct fstab_rec* fstab_entry);
-
-__END_DECLS
-
-#endif /* __CORE_FS_MGR_PRIV_AVB_H */
diff --git a/fs_mgr/fs_mgr_priv_sha.h b/fs_mgr/fs_mgr_priv_sha.h
index 882411b..5b53eea 100644
--- a/fs_mgr/fs_mgr_priv_sha.h
+++ b/fs_mgr/fs_mgr_priv_sha.h
@@ -20,16 +20,18 @@
#include <openssl/sha.h>
class SHA256Hasher {
- private:
+ private:
SHA256_CTX sha256_ctx;
uint8_t hash[SHA256_DIGEST_LENGTH];
- public:
+ public:
enum { DIGEST_SIZE = SHA256_DIGEST_LENGTH };
SHA256Hasher() { SHA256_Init(&sha256_ctx); }
- void update(const void* data, size_t data_size) { SHA256_Update(&sha256_ctx, data, data_size); }
+ void update(const uint8_t* data, size_t data_size) {
+ SHA256_Update(&sha256_ctx, data, data_size);
+ }
const uint8_t* finalize() {
SHA256_Final(hash, &sha256_ctx);
@@ -38,11 +40,11 @@
};
class SHA512Hasher {
- private:
+ private:
SHA512_CTX sha512_ctx;
uint8_t hash[SHA512_DIGEST_LENGTH];
- public:
+ public:
enum { DIGEST_SIZE = SHA512_DIGEST_LENGTH };
SHA512Hasher() { SHA512_Init(&sha512_ctx); }
diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp
index 7a45473..9ca15e2 100644
--- a/fs_mgr/fs_mgr_slotselect.cpp
+++ b/fs_mgr/fs_mgr_slotselect.cpp
@@ -16,37 +16,47 @@
#include <stdio.h>
+#include <string>
+
#include "fs_mgr.h"
#include "fs_mgr_priv.h"
-// Updates |fstab| for slot_suffix. Returns 0 on success, -1 on error.
-int fs_mgr_update_for_slotselect(struct fstab *fstab)
-{
+// Returns "_a" or "_b" based on two possible values in kernel cmdline:
+// - androidboot.slot = a or b OR
+// - androidboot.slot_suffix = _a or _b
+// TODO: remove slot_suffix once it's deprecated.
+std::string fs_mgr_get_slot_suffix() {
+ std::string slot;
+ std::string ab_suffix;
+
+ if (fs_mgr_get_boot_config("slot", &slot)) {
+ ab_suffix = "_" + slot;
+ } else if (!fs_mgr_get_boot_config("slot_suffix", &ab_suffix)) {
+ ab_suffix = "";
+ }
+ return ab_suffix;
+}
+
+// Updates |fstab| for slot_suffix. Returns true on success, false on error.
+bool fs_mgr_update_for_slotselect(struct fstab *fstab) {
int n;
- int got_suffix = 0;
- std::string suffix;
+ std::string ab_suffix;
for (n = 0; n < fstab->num_entries; n++) {
if (fstab->recs[n].fs_mgr_flags & MF_SLOTSELECT) {
char *tmp;
-
- if (!got_suffix) {
- std::string slot;
- if (fs_mgr_get_boot_config("slot", &slot)) {
- suffix = "_" + slot;
- } else if (!fs_mgr_get_boot_config("slot_suffix", &suffix)) {
- // remove slot_suffix once bootloaders update to new androidboot.slot param
- return -1;
- }
+ if (ab_suffix.empty()) {
+ ab_suffix = fs_mgr_get_slot_suffix();
+ // Returns false as non A/B devices should not have MF_SLOTSELECT.
+ if (ab_suffix.empty()) return false;
}
-
- if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device, suffix.c_str()) > 0) {
+ if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device, ab_suffix.c_str()) > 0) {
free(fstab->recs[n].blk_device);
fstab->recs[n].blk_device = tmp;
} else {
- return -1;
+ return false;
}
}
}
- return 0;
+ return true;
}
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index 8c7a8ca..0bf173b 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -653,8 +653,7 @@
offset);
}
-static int load_verity_state(struct fstab_rec *fstab, int *mode)
-{
+int load_verity_state(struct fstab_rec* fstab, int* mode) {
int match = 0;
off64_t offset = 0;
@@ -690,129 +689,6 @@
return read_verity_state(fstab->verity_loc, offset, mode);
}
-int fs_mgr_load_verity_state(int *mode)
-{
- int rc = -1;
- int i;
- int current;
- struct fstab *fstab = NULL;
-
- /* return the default mode, unless any of the verified partitions are in
- * logging mode, in which case return that */
- *mode = VERITY_MODE_DEFAULT;
-
- fstab = fs_mgr_read_fstab_default();
- if (!fstab) {
- LERROR << "Failed to read default fstab";
- goto out;
- }
-
- for (i = 0; i < fstab->num_entries; i++) {
- if (!fs_mgr_is_verified(&fstab->recs[i])) {
- continue;
- }
-
- rc = load_verity_state(&fstab->recs[i], ¤t);
- if (rc < 0) {
- continue;
- }
-
- if (current != VERITY_MODE_DEFAULT) {
- *mode = current;
- break;
- }
- }
-
- rc = 0;
-
-out:
- if (fstab) {
- fs_mgr_free_fstab(fstab);
- }
-
- return rc;
-}
-
-int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback)
-{
- alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
- bool system_root = false;
- std::string mount_point;
- char propbuf[PROPERTY_VALUE_MAX];
- const char *status;
- int fd = -1;
- int i;
- int mode;
- int rc = -1;
- struct dm_ioctl *io = (struct dm_ioctl *) buffer;
- struct fstab *fstab = NULL;
-
- if (!callback) {
- return -1;
- }
-
- if (fs_mgr_load_verity_state(&mode) == -1) {
- return -1;
- }
-
- fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC));
- if (fd == -1) {
- PERROR << "Error opening device mapper";
- goto out;
- }
-
- property_get("ro.build.system_root_image", propbuf, "");
- system_root = !strcmp(propbuf, "true");
- fstab = fs_mgr_read_fstab_default();
- if (!fstab) {
- LERROR << "Failed to read default fstab";
- goto out;
- }
-
- for (i = 0; i < fstab->num_entries; i++) {
- if (!fs_mgr_is_verified(&fstab->recs[i])) {
- continue;
- }
-
- if (system_root && !strcmp(fstab->recs[i].mount_point, "/")) {
- mount_point = "system";
- } else {
- mount_point = basename(fstab->recs[i].mount_point);
- }
-
- fs_mgr_verity_ioctl_init(io, mount_point, 0);
-
- if (ioctl(fd, DM_TABLE_STATUS, io)) {
- if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
- status = "V";
- } else {
- PERROR << "Failed to query DM_TABLE_STATUS for "
- << mount_point.c_str();
- continue;
- }
- }
-
- status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
-
- if (*status == 'C' || *status == 'V') {
- callback(&fstab->recs[i], mount_point.c_str(), mode, *status);
- }
- }
-
- rc = 0;
-
-out:
- if (fstab) {
- fs_mgr_free_fstab(fstab);
- }
-
- if (fd) {
- close(fd);
- }
-
- return rc;
-}
-
static void update_verity_table_blk_device(char *blk_device, char **table)
{
std::string result, word;
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 2fd5f65..fd63dfd 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -22,6 +22,12 @@
#include <stdbool.h>
#include <linux/dm-ioctl.h>
+// C++ only headers
+// TODO: move this into separate header files under include/fs_mgr/*.h
+#ifdef __cplusplus
+#include <string>
+#endif
+
// Magic number at start of verity metadata
#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
@@ -29,9 +35,7 @@
// turn verity off in userdebug builds.
#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF"
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
// Verity modes
enum verity_mode {
@@ -110,8 +114,8 @@
int fs_mgr_unmount_all(struct fstab *fstab);
int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc,
char *real_blk_device, int size);
-int fs_mgr_load_verity_state(int *mode);
-int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback);
+bool fs_mgr_load_verity_state(int* mode);
+bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback);
int fs_mgr_add_entry(struct fstab *fstab,
const char *mount_point, const char *fs_type,
const char *blk_device);
@@ -120,6 +124,7 @@
int fs_mgr_is_nonremovable(const struct fstab_rec *fstab);
int fs_mgr_is_verified(const struct fstab_rec *fstab);
int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab);
+int fs_mgr_is_avb(const struct fstab_rec *fstab);
int fs_mgr_is_encryptable(const struct fstab_rec *fstab);
int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab);
void fs_mgr_get_file_encryption_modes(const struct fstab_rec *fstab,
@@ -142,8 +147,12 @@
#define FS_MGR_SETUP_VERITY_SUCCESS 0
int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev);
+__END_DECLS
+
+// C++ only functions
+// TODO: move this into separate header files under include/fs_mgr/*.h
#ifdef __cplusplus
-}
+std::string fs_mgr_get_slot_suffix();
#endif
#endif /* __CORE_FS_MGR_H */
diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/include/fs_mgr_avb.h
new file mode 100644
index 0000000..526a5ce
--- /dev/null
+++ b/fs_mgr/include/fs_mgr_avb.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __CORE_FS_MGR_AVB_H
+#define __CORE_FS_MGR_AVB_H
+
+#include <memory>
+#include <string>
+
+#include <libavb/libavb.h>
+
+#include "fs_mgr.h"
+
+enum FsManagerAvbHandleStatus {
+ kFsManagerAvbHandleSuccess = 0,
+ kFsManagerAvbHandleHashtreeDisabled = 1,
+ kFsManagerAvbHandleFail = 2,
+};
+
+class FsManagerAvbHandle;
+using FsManagerAvbUniquePtr = std::unique_ptr<FsManagerAvbHandle>;
+
+// Provides a factory method to return a unique_ptr pointing to itself and the
+// SetUpAvb() function to extract dm-verity parameters from AVB metadata to
+// load verity table into kernel through ioctl.
+class FsManagerAvbHandle {
+ public:
+ // The factory method to return a FsManagerAvbUniquePtr that holds
+ // the verified AVB (external/avb) metadata of all verified partitions
+ // in avb_slot_data_.vbmeta_images[].
+ //
+ // The metadata is checked against the following values from /proc/cmdline.
+ // - androidboot.vbmeta.{hash_alg, size, digest}.
+ //
+ // A typical usage will be:
+ // - FsManagerAvbUniquePtr handle = FsManagerAvbHandle::Open();
+ //
+ // Possible return values:
+ // - nullptr: any error when reading and verifying the metadata,
+ // e.g., I/O error, digest value mismatch, size mismatch, etc.
+ //
+ // - a valid unique_ptr with status kFsMgrAvbHandleHashtreeDisabled:
+ // to support the existing 'adb disable-verity' feature in Android.
+ // It's very helpful for developers to make the filesystem writable to
+ // allow replacing binaries on the device.
+ //
+ // - a valid unique_ptr with status kFsMgrAvbHandleSuccess: the metadata
+ // is verified and can be trusted.
+ //
+ static FsManagerAvbUniquePtr Open(const std::string& device_file_by_name_prefix);
+
+ // Sets up dm-verity on the given fstab entry.
+ // The 'wait_for_verity_dev' parameter makes this function wait for the
+ // verity device to get created before return.
+ // Returns true if the mount point is eligible to mount, it includes:
+ // - status_ is kFsMgrAvbHandleHashtreeDisabled or
+ // - status_ is kFsMgrAvbHandleSuccess and sending ioctl DM_TABLE_LOAD
+ // to load verity table is success.
+ // Otherwise, returns false.
+ bool SetUpAvb(fstab_rec* fstab_entry, bool wait_for_verity_dev);
+
+ bool AvbHashtreeDisabled() { return status_ == kFsManagerAvbHandleHashtreeDisabled; }
+
+ FsManagerAvbHandle(const FsManagerAvbHandle&) = delete; // no copy
+ FsManagerAvbHandle& operator=(const FsManagerAvbHandle&) = delete; // no assignment
+
+ FsManagerAvbHandle(FsManagerAvbHandle&&) noexcept = delete; // no move
+ FsManagerAvbHandle& operator=(FsManagerAvbHandle&&) noexcept = delete; // no move assignment
+
+ ~FsManagerAvbHandle() {
+ if (avb_slot_data_) {
+ avb_slot_verify_data_free(avb_slot_data_);
+ }
+ };
+
+ protected:
+ FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleFail) {}
+
+ private:
+ AvbSlotVerifyData* avb_slot_data_;
+ FsManagerAvbHandleStatus status_;
+};
+
+#endif /* __CORE_FS_MGR_AVB_H */
diff --git a/init/Android.mk b/init/Android.mk
index eb27c60..3c878b5 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -109,8 +109,8 @@
libfec_rs \
libsquashfs_utils \
liblogwrap \
- libcutils \
libext4_utils \
+ libcutils \
libbase \
libc \
libselinux \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 75b3c61..2be70bf 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -678,11 +678,11 @@
static int do_verity_load_state(const std::vector<std::string>& args) {
int mode = -1;
- int rc = fs_mgr_load_verity_state(&mode);
- if (rc == 0 && mode != VERITY_MODE_DEFAULT) {
+ bool loaded = fs_mgr_load_verity_state(&mode);
+ if (loaded && mode != VERITY_MODE_DEFAULT) {
ActionManager::GetInstance().QueueEventTrigger("verity-logging");
}
- return rc;
+ return loaded ? 0 : 1;
}
static void verity_update_property(fstab_rec *fstab, const char *mount_point,
@@ -692,7 +692,7 @@
}
static int do_verity_update_state(const std::vector<std::string>& args) {
- return fs_mgr_update_verity_state(verity_update_property);
+ return fs_mgr_update_verity_state(verity_update_property) ? 0 : 1;
}
static int do_write(const std::vector<std::string>& args) {
diff --git a/init/init.cpp b/init/init.cpp
index d07c308..b05311a 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -57,6 +57,7 @@
#include "bootchart.h"
#include "devices.h"
#include "fs_mgr.h"
+#include "fs_mgr_avb.h"
#include "import_parser.h"
#include "init.h"
#include "init_parser.h"
@@ -478,42 +479,73 @@
}
}
-static constexpr char android_dt_dir[] = "/proc/device-tree/firmware/android";
-
-static bool is_dt_compatible() {
- std::string dt_value;
- std::string file_name = StringPrintf("%s/compatible", android_dt_dir);
-
- if (android::base::ReadFileToString(file_name, &dt_value)) {
- // trim the trailing '\0' out, otherwise the comparison
- // will produce false-negatives.
- dt_value.resize(dt_value.size() - 1);
- if (dt_value == "android,firmware") {
+/* Reads the content of device tree file into dt_value.
+ * Returns true if the read is success, false otherwise.
+ */
+static bool read_dt_file(const std::string& file_name, std::string* dt_value) {
+ if (android::base::ReadFileToString(file_name, dt_value)) {
+ if (!dt_value->empty()) {
+ dt_value->pop_back(); // Trim the trailing '\0' out.
return true;
}
}
-
return false;
}
-static bool is_dt_fstab_compatible() {
- std::string dt_value;
- std::string file_name = StringPrintf("%s/%s/compatible", android_dt_dir, "fstab");
+static const std::string kAndroidDtDir("/proc/device-tree/firmware/android/");
- if (android::base::ReadFileToString(file_name, &dt_value)) {
- dt_value.resize(dt_value.size() - 1);
- if (dt_value == "android,fstab") {
+static bool is_dt_value_expected(const std::string& dt_file_suffix,
+ const std::string& expected_value) {
+ std::string dt_value;
+ std::string file_name = kAndroidDtDir + dt_file_suffix;
+
+ if (read_dt_file(file_name, &dt_value)) {
+ if (dt_value == expected_value) {
return true;
}
}
-
return false;
}
+static inline bool is_dt_compatible() {
+ return is_dt_value_expected("compatible", "android,firmware");
+}
+
+static inline bool is_dt_fstab_compatible() {
+ return is_dt_value_expected("fstab/compatible", "android,fstab");
+}
+
+static inline bool is_dt_vbmeta_compatible() {
+ return is_dt_value_expected("vbmeta/compatible", "android,vbmeta");
+}
+
+// Gets the vbmeta config from device tree. Specifically, the 'parts' and 'by_name_prefix'.
+// /{
+// firmware {
+// android {
+// vbmeta {
+// compatible = "android,vbmeta";
+// parts = "vbmeta,boot,system,vendor"
+// by_name_prefix="/dev/block/platform/soc.0/f9824900.sdhci/by-name/"
+// };
+// };
+// };
+// }
+static bool get_vbmeta_config_from_dt(std::string* vbmeta_partitions,
+ std::string* device_file_by_name_prefix) {
+ std::string file_name = kAndroidDtDir + "vbmeta/parts";
+ if (!read_dt_file(file_name, vbmeta_partitions)) return false;
+
+ file_name = kAndroidDtDir + "vbmeta/by_name_prefix";
+ if (!read_dt_file(file_name, device_file_by_name_prefix)) return false;
+
+ return true;
+}
+
static void process_kernel_dt() {
if (!is_dt_compatible()) return;
- std::unique_ptr<DIR, int(*)(DIR*)>dir(opendir(android_dt_dir), closedir);
+ std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(kAndroidDtDir.c_str()), closedir);
if (!dir) return;
std::string dt_file;
@@ -523,7 +555,7 @@
continue;
}
- std::string file_name = StringPrintf("%s/%s", android_dt_dir, dp->d_name);
+ std::string file_name = kAndroidDtDir + dp->d_name;
android::base::ReadFileToString(file_name, &dt_file);
std::replace(dt_file.begin(), dt_file.end(), ',', '.');
@@ -944,38 +976,100 @@
}
}
-static bool early_mount_one(struct fstab_rec* rec) {
- if (rec && fs_mgr_is_verified(rec)) {
- // setup verity and create the dm-XX block device
- // needed to mount this partition
- int ret = fs_mgr_setup_verity(rec, false);
- if (ret == FS_MGR_SETUP_VERITY_FAIL) {
- PLOG(ERROR) << "early_mount: Failed to setup verity for '" << rec->mount_point << "'";
+// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
+static void device_init_dm_device(const std::string& dm_device) {
+ const std::string device_name(basename(dm_device.c_str()));
+ const std::string syspath = "/sys/block/" + device_name;
+
+ device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
+ if (uevent->device_name && device_name == uevent->device_name) {
+ LOG(VERBOSE) << "early_mount: creating dm-verity device : " << dm_device;
+ return COLDBOOT_STOP;
+ }
+ return COLDBOOT_CONTINUE;
+ });
+ device_close();
+}
+
+static bool vboot_1_0_mount_partitions(const std::vector<fstab_rec*>& fstab_recs) {
+ if (fstab_recs.empty()) return false;
+
+ for (auto rec : fstab_recs) {
+ bool need_create_dm_device = false;
+ if (fs_mgr_is_verified(rec)) {
+ // setup verity and create the dm-XX block device
+ // needed to mount this partition
+ int ret = fs_mgr_setup_verity(rec, false /* wait_for_verity_dev */);
+ if (ret == FS_MGR_SETUP_VERITY_DISABLED) {
+ LOG(INFO) << "verity disabled for '" << rec->mount_point << "'";
+ } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) {
+ need_create_dm_device = true;
+ } else {
+ PLOG(ERROR) << "early_mount: failed to setup verity for '" << rec->mount_point
+ << "'";
+ return false;
+ }
+ }
+ if (need_create_dm_device) {
+ // The exact block device name (rec->blk_device) is changed to "/dev/block/dm-XX".
+ // Need to create it because ueventd isn't started during early mount.
+ device_init_dm_device(rec->blk_device);
+ }
+ if (fs_mgr_do_mount_one(rec)) {
+ PLOG(ERROR) << "early_mount: failed to mount '" << rec->mount_point << "'";
return false;
}
-
- // The exact block device name is added as a mount source by
- // fs_mgr_setup_verity() in ->blk_device as "/dev/block/dm-XX"
- // We create that device by running coldboot on /sys/block/dm-XX
- std::string dm_device(basename(rec->blk_device));
- std::string syspath = StringPrintf("/sys/block/%s", dm_device.c_str());
- device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
- if (uevent->device_name && !strcmp(dm_device.c_str(), uevent->device_name)) {
- LOG(VERBOSE) << "early_mount: creating dm-verity device : " << dm_device;
- return COLDBOOT_STOP;
- }
- return COLDBOOT_CONTINUE;
- });
- }
-
- if (rec && fs_mgr_do_mount_one(rec)) {
- PLOG(ERROR) << "early_mount: Failed to mount '" << rec->mount_point << "'";
- return false;
}
return true;
}
+static bool vboot_2_0_mount_partitions(const std::vector<fstab_rec*>& fstab_recs,
+ const std::string& device_file_by_name_prefix) {
+ if (fstab_recs.empty()) return false;
+
+ FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(device_file_by_name_prefix);
+ if (!avb_handle) {
+ LOG(INFO) << "Failed to Open FsManagerAvbHandle";
+ return false;
+ }
+
+ for (auto rec : fstab_recs) {
+ bool need_create_dm_device = false;
+ if (fs_mgr_is_avb(rec)) {
+ if (avb_handle->AvbHashtreeDisabled()) {
+ LOG(INFO) << "avb hashtree disabled for '" << rec->mount_point << "'";
+ } else if (avb_handle->SetUpAvb(rec, false /* wait_for_verity_dev */)) {
+ need_create_dm_device = true;
+ } else {
+ PLOG(ERROR) << "early_mount: failed to set up AVB on partition: '"
+ << rec->mount_point << "'";
+ return false;
+ }
+ }
+ if (need_create_dm_device) {
+ // The exact block device name (rec->blk_device) is changed to "/dev/block/dm-XX".
+ // Need to create it because ueventd isn't started during early mount.
+ device_init_dm_device(rec->blk_device);
+ }
+ if (fs_mgr_do_mount_one(rec)) {
+ PLOG(ERROR) << "early_mount: failed to mount '" << rec->mount_point << "'";
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static bool mount_early_partitions(const std::vector<fstab_rec*>& fstab_recs,
+ const std::string& device_file_by_name_prefix) {
+ if (is_dt_vbmeta_compatible()) { // AVB (external/avb) is used to setup dm-verity.
+ return vboot_2_0_mount_partitions(fstab_recs, device_file_by_name_prefix);
+ } else {
+ return vboot_1_0_mount_partitions(fstab_recs);
+ }
+}
+
// Creates devices with uevent->partition_name matching one in the in/out
// partition_names. Note that the partition_names MUST have A/B suffix
// when A/B is used. Found partitions will then be removed from the
@@ -1018,12 +1112,10 @@
});
}
-static bool get_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs,
- std::set<std::string>* out_partitions, bool* out_need_verity) {
+static bool vboot_1_0_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs,
+ std::set<std::string>* out_partitions,
+ bool* out_need_verity) {
std::string meta_partition;
- out_partitions->clear();
- *out_need_verity = false;
-
for (auto fstab_rec : early_fstab_recs) {
// don't allow verifyatboot for early mounted partitions
if (fs_mgr_is_verifyatboot(fstab_rec)) {
@@ -1062,6 +1154,40 @@
return true;
}
+// a.k.a. AVB (external/avb)
+static bool vboot_2_0_early_partitions(std::set<std::string>* out_partitions, bool* out_need_verity,
+ std::string* out_device_file_by_name_prefix) {
+ std::string vbmeta_partitions;
+ if (!get_vbmeta_config_from_dt(&vbmeta_partitions, out_device_file_by_name_prefix)) {
+ return false;
+ }
+ // libavb verifies AVB metadata on all verified partitions at once.
+ // e.g., The vbmeta_partitions will be "vbmeta,boot,system,vendor"
+ // for libavb to verify metadata, even if we only need to early mount /vendor.
+ std::vector<std::string> partitions = android::base::Split(vbmeta_partitions, ",");
+ std::string ab_suffix = fs_mgr_get_slot_suffix();
+ for (const auto& partition : partitions) {
+ out_partitions->emplace(partition + ab_suffix);
+ }
+ *out_need_verity = true;
+ return true;
+}
+
+static bool get_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs,
+ std::set<std::string>* out_partitions, bool* out_need_verity,
+ std::string* out_device_file_by_name_prefix) {
+ *out_need_verity = false;
+ out_partitions->clear();
+ out_device_file_by_name_prefix->clear();
+
+ if (is_dt_vbmeta_compatible()) { // AVB (external/avb) is used to setup dm-verity.
+ return vboot_2_0_early_partitions(out_partitions, out_need_verity,
+ out_device_file_by_name_prefix);
+ } else {
+ return vboot_1_0_early_partitions(early_fstab_recs, out_partitions, out_need_verity);
+ }
+}
+
/* Early mount vendor and ODM partitions. The fstab is read from device-tree. */
static bool early_mount() {
// skip early mount if we're in recovery mode
@@ -1096,9 +1222,11 @@
if (early_fstab_recs.empty()) return true;
bool need_verity;
+ std::string device_file_by_name_prefix;
std::set<std::string> partition_names;
// partition_names MUST have A/B suffix when A/B is used
- if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity)) {
+ if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity,
+ &device_file_by_name_prefix)) {
return false;
}
@@ -1121,10 +1249,9 @@
[&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; });
}
- for (auto fstab_rec : early_fstab_recs) {
- if (!early_mount_one(fstab_rec)) goto done;
+ if (mount_early_partitions(early_fstab_recs, device_file_by_name_prefix)) {
+ success = true;
}
- success = true;
done:
device_close();
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 86fec6a..48a46c6 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -173,4 +173,18 @@
bcp_md5 :=
bcp_dep :=
+
#######################################
+# ld.config.txt
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ld.config.txt
+ifeq ($(PRODUCT_FULL_TREBLE),true)
+LOCAL_SRC_FILES := etc/ld.config.txt
+else
+LOCAL_SRC_FILES := etc/ld.config.legacy.txt
+endif
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
+LOCAL_MODULE_STEM := $(LOCAL_MODULE)
+include $(BUILD_PREBUILT)
diff --git a/rootdir/etc/ld.config.legacy.txt b/rootdir/etc/ld.config.legacy.txt
new file mode 100644
index 0000000..c22edfe
--- /dev/null
+++ b/rootdir/etc/ld.config.legacy.txt
@@ -0,0 +1,15 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Bionic loader config file.
+# This gives the exactly the same namespace setup in pre-O.
+#
+
+# All binaries gets the same configuration 'legacy'
+dir.legacy = /system
+dir.legacy = /vendor
+dir.legacy = /sbin
+
+[legacy]
+namespace.default.isolated = false
+namespace.default.search.paths = /system/${LIB}:/vendor/${LIB}
+namespace.default.asan.search.paths = /data/asan/system/${LIB}:/system/${LIB}:/data/asan/vendor/${LIB}:/vendor/${LIB}
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index e3468ca..fbe8b28 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -3,45 +3,94 @@
# Bionic loader config file.
#
-#dir.vendor=/vendor/bin/
-#dir.system=/system/bin/
-
-[vendor]
-
-# When this flag is set to true linker will
-# set target_sdk_version for this binary to
-# the version specified in <dirname>/.version
-# file, where <dirname> = dirname(executable_path)
-#
-# default value is false
-enable.target.sdk.version = true
-
-# There is always the default namespace no
-# need to mention it in this list
-additional.namespaces=system
-
-# Is the namespace isolated
-namespace.default.isolated = true
-namespace.default.search.paths = /vendor/${LIB}
-
-# TODO: property for asan search path?
-namespace.default.permitted.paths = /vendor/${LIB}
-namespace.default.asan.permitted.paths = /data/vendor/${LIB}
-namespace.default.links = system
-
-# Todo complete this list
-namespace.default.link.system.shared_libs = libc.so:libm.so:libdl.so:libstdc++.so
-
-namespace.system.isolated = true
-namespace.system.search.paths = /system/${LIB}:/system/${LIB}/framework
-namespace.system.permitted.paths = /system/${LIB}
+# Don't change the order here.
+dir.system = /system/bin/
+dir.system = /system/xbin/
+dir.vendor = /vendor/bin/
+dir.legacy = /
[system]
-namespace.default.isolated = true
-namespace.default.search.paths = /system/${LIB}
-namespace.default.permitted.paths = /system/${LIB}
+additional.namespaces = sphal,vndk,rs
-# app_process will setup additional vendor namespace manually.
-# Note that zygote will need vendor namespace to setup list of public
-# libraries provided by vendors to apps.
+###############################################################################
+# "default" namespace
+#
+# Framework-side code runs in this namespace. Anything from /vendor partition
+# can't be loaded in this namespace.
+###############################################################################
+namespace.default.isolated = false
+namespace.default.search.paths = /system/${LIB}:/vendor/${LIB}
+namespace.default.permitted.paths = /system/${LIB}:/vendor/${LIB}
+# TODO(b/37013858): remove all dependencies to /vendor/lib from system processes
+# When this is done, comment out following three lines and remove the three
+# lines above
+#namespace.default.isolated = true
+#namespace.default.search.paths = /system/${LIB}
+#namespace.default.permitted.paths = /system/${LIB}
+
+###############################################################################
+# "sphal" namespace
+#
+# SP-HAL(Sameprocess-HAL)s are the only vendor libraries that are allowed to be
+# loaded inside system processes. libEGL_<chipset>.so, libGLESv2_<chipset>.so,
+# android.hardware.graphics.mapper@2.0-impl.so, etc are SP-HALs.
+#
+# This namespace is exclusivly for SP-HALs. When the framework tries to dynami-
+# cally load SP-HALs, android_dlopen_ext() is used to explicitly specifying
+# that they should be searched and loaded from this namespace.
+#
+# Note that there is no link from the default namespace to this namespace.
+###############################################################################
+namespace.sphal.isolated = true
+namespace.sphal.visible = true
+namespace.sphal.search.paths = /vendor/${LIB}/egl:/vendor/${LIB}/hw:/vendor/${LIB}
+namespace.sphal.permitted.paths = /vendor/${LIB}
+
+# Once in this namespace, access to libraries in /system/lib is restricted. Only
+# libs listed here can be used.
+namespace.sphal.links = default,vndk
+
+# WARNING: only NDK libs can be listed here.
+# However, this is commented out because some SP-HALs (gralloc.msm8996.so, etc)
+# are currently using some non-stable libs such as libui.so. We will get back
+# to this list once the dependencies are fixed.
+#namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libsync.so
+namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libui.so:libbacktrace.so:libGLESv1_CM.so:libGLESv2.so
+
+# WARNING: only VNDK-SP libs can be listed here. DO NOT EDIT this line.
+namespace.sphal.link.vndk.shared_libs = android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:android.hidl.base@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
+
+###############################################################################
+# "vndk" namespace
+#
+# This namespace is exclusively for vndk-sp libs.
+###############################################################################
+namespace.vndk.isolated = true
+namespace.vndk.search.paths = /vendor/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.vndk.permitted.paths = /vendor/${LIB}/hw:/vendor/${LIB}/egl
+
+# When these NDK libs are required inside this namespace, then it is redirected
+# to the default namespace. This is possible since their ABI is stable across
+# Android releases.
+namespace.vndk.links = default
+
+# WARNING: only NDK libs can be listed here.
+# However, this is commented out because some SP-HALs (gralloc.msm8996.so, etc)
+# are currently using some non-stable libs such as libui.so. We will get back
+# to this list once the dependencies are fixed.
+#namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libsync.so
+namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libui.so:libbacktrace.so
+
+
+[vendor]
+namespace.default.isolated = false
+namespace.default.search.paths = /vendor/${LIB}:/vendor/${LIB}/vndk-sp:/system/${LIB}
+
+# If a binary does not belong to any of the sections above, it falls back to
+# this section, which is identical to the namespace configuration setup
+# in pre-O.
+[legacy]
+namespace.default.isolated = false
+namespace.default.search.path = /system/${LIB}:/vendor/${LIB}
+namespace.default.asan.search.path = /data/asan/system/${LIB}:/system/${LIB}:/data/asan/vendor/${LIB}:/vendor/${LIB}