Merge changes from topic 'avb-early-mount' am: d7381375bb
am: 04989a7a4b
Change-Id: I45d89c806076842ee75a772b1a8bbba2157eb46c
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 28da9db..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>
@@ -50,6 +53,7 @@
#include "fs_mgr.h"
#include "fs_mgr_avb.h"
#include "fs_mgr_priv.h"
+#include "fs_mgr_priv_dm_ioctl.h"
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
#define KEY_IN_FOOTER "footer"
@@ -1258,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_priv.h b/fs_mgr/fs_mgr_priv.h
index dedffd8..c985462 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -115,5 +115,6 @@
bool fs_mgr_update_for_slotselect(struct fstab *fstab);
bool is_dt_compatible();
bool is_device_secure();
+int load_verity_state(struct fstab_rec* fstab, int* mode);
#endif /* __CORE_FS_MGR_PRIV_H */
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 cea70b4..12db672 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -113,8 +113,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);
diff --git a/init/Android.mk b/init/Android.mk
index 7e9b613..c9bf9fc 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -111,8 +111,8 @@
libfec_rs \
libsquashfs_utils \
liblogwrap \
- libcutils \
libext4_utils \
+ libcutils \
libbase \
libc \
libselinux \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index e1d9b94..2327cdf 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -677,11 +677,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,
@@ -691,7 +691,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 543f38e..6c09c99 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -61,6 +61,7 @@
#include "bootchart.h"
#include "devices.h"
#include "fs_mgr.h"
+#include "fs_mgr_avb.h"
#include "import_parser.h"
#include "init_parser.h"
#include "keychords.h"
@@ -482,42 +483,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;
@@ -527,7 +559,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(), ',', '.');
@@ -920,38 +952,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
@@ -994,12 +1088,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)) {
@@ -1038,6 +1130,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
@@ -1072,9 +1198,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;
}
@@ -1097,10 +1225,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();