diff options
| -rw-r--r-- | fs_mgr/Android.mk | 3 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr.cpp | 40 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_avb.cpp | 24 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_boot_config.cpp | 71 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_fstab.cpp | 5 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_priv.h | 1 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_priv_boot_config.h (renamed from fs_mgr/fs_mgr_priv_verity.h) | 16 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_slotselect.cpp | 93 | ||||
| -rw-r--r-- | fs_mgr/fs_mgr_verity.cpp | 16 | ||||
| -rw-r--r-- | fs_mgr/include/fs_mgr.h | 10 | ||||
| -rw-r--r-- | init/devices.cpp | 20 | ||||
| -rw-r--r-- | init/init.cpp | 104 |
12 files changed, 231 insertions, 172 deletions
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk index 693942883..f1a7ad6dd 100644 --- a/fs_mgr/Android.mk +++ b/fs_mgr/Android.mk @@ -25,7 +25,8 @@ LOCAL_SRC_FILES:= \ fs_mgr_slotselect.cpp \ fs_mgr_verity.cpp \ fs_mgr_avb.cpp \ - fs_mgr_avb_ops.cpp + fs_mgr_avb_ops.cpp \ + fs_mgr_boot_config.cpp LOCAL_C_INCLUDES := \ $(LOCAL_PATH)/include \ system/vold \ diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 176807801..25c41b96e 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -48,7 +48,6 @@ #include "fs_mgr_priv.h" #include "fs_mgr_priv_avb.h" -#include "fs_mgr_priv_verity.h" #define KEY_LOC_PROP "ro.crypto.keyfile.userdata" #define KEY_IN_FOOTER "footer" @@ -661,6 +660,8 @@ static int handle_encryptable(const struct fstab_rec* rec) } } +// 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) { int tries = 25; while (tries--) { @@ -880,6 +881,24 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) } } +/* wrapper to __mount() and expects a fully prepared fstab_rec, + * unlike fs_mgr_do_mount which does more things with avb / verity + * etc. + */ +int fs_mgr_do_mount_one(struct fstab_rec *rec) +{ + if (!rec) { + return FS_MGR_DOMNT_FAILED; + } + + int ret = __mount(rec->blk_device, rec->mount_point, rec); + if (ret) { + ret = (errno == EBUSY) ? FS_MGR_DOMNT_BUSY : FS_MGR_DOMNT_FAILED; + } + + return ret; +} + /* If tmp_mount_point is non-null, mount the filesystem there. This is for the * tmp mount we do to check the user password * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one @@ -1171,22 +1190,3 @@ int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_dev return 0; } - -int fs_mgr_early_setup_verity(struct fstab_rec *fstab_rec) -{ - if ((fstab_rec->fs_mgr_flags & MF_VERIFY) && device_is_secure()) { - int rc = fs_mgr_setup_verity(fstab_rec, false); - if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { - LINFO << "Verity disabled"; - return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY; - } else if (rc == FS_MGR_SETUP_VERITY_SUCCESS) { - return FS_MGR_EARLY_SETUP_VERITY_SUCCESS; - } else { - return FS_MGR_EARLY_SETUP_VERITY_FAIL; - } - } else if (device_is_secure()) { - LERROR << "Verity must be enabled for early mounted partitions on secured devices"; - return FS_MGR_EARLY_SETUP_VERITY_FAIL; - } - return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY; -} diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp index 68efb00a0..2cb7e3438 100644 --- a/fs_mgr/fs_mgr_avb.cpp +++ b/fs_mgr/fs_mgr_avb.cpp @@ -441,18 +441,23 @@ static bool get_hashtree_descriptor(const std::string& partition_name, static bool init_is_avb_used() { // When AVB is used, boot loader should set androidboot.vbmeta.{hash_alg, - // size, digest} in kernel cmdline. They will then be imported by init - // process to system properties: ro.boot.vbmeta.{hash_alg, size, digest}. + // 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 = android::base::GetProperty("ro.boot.vbmeta.hash_alg", ""); - - if (hash_alg == "sha256" || hash_alg == "sha512") { - return true; + std::string hash_alg; + if (fs_mgr_get_boot_config("vbmeta.hash_alg", &hash_alg) == 0) { + if (hash_alg == "sha256" || hash_alg == "sha512") { + return true; + } } return false; @@ -482,10 +487,11 @@ int fs_mgr_load_vbmeta_images(struct fstab* fstab) { // 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}; - const char* ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "").c_str(); + const char *requested_partitions[] = {nullptr}; + std::string ab_suffix; + fs_mgr_get_boot_config("slot_suffix", &ab_suffix); AvbSlotVerifyResult verify_result = - avb_slot_verify(fs_mgr_avb_ops, requested_partitions, ab_suffix, + 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); // Only allow two verify results: diff --git a/fs_mgr/fs_mgr_boot_config.cpp b/fs_mgr/fs_mgr_boot_config.cpp new file mode 100644 index 000000000..ae442cff8 --- /dev/null +++ b/fs_mgr/fs_mgr_boot_config.cpp @@ -0,0 +1,71 @@ +/* + * 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. + */ + +#include <android-base/file.h> +#include <android-base/stringprintf.h> +#include <android-base/strings.h> +#include <android-base/properties.h> + +#include "fs_mgr_priv.h" + +// Tries to get the boot config value in properties, kernel cmdline and +// device tree (in that order). returns 'true' if successfully found, 'false' +// otherwise +bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val) { + FS_MGR_CHECK(out_val != nullptr); + + // first check if we have "ro.boot" property already + *out_val = android::base::GetProperty("ro.boot." + key, ""); + if (!out_val->empty()) { + return true; + } + + // fallback to kernel cmdline, properties may not be ready yet + std::string cmdline; + std::string cmdline_key("androidboot." + key); + if (android::base::ReadFileToString("/proc/cmdline", &cmdline)) { + for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { + std::vector<std::string> pieces = android::base::Split(entry, "="); + if (pieces.size() == 2) { + if (pieces[0] == cmdline_key) { + *out_val = pieces[1]; + return true; + } + } + } + } + + // lastly, check the device tree + static const std::string android_dt_dir("/proc/device-tree/firmware/android"); + std::string file_name = android_dt_dir + "/compatible"; + std::string dt_value; + if (android::base::ReadFileToString(file_name, &dt_value)) { + if (dt_value != "android,firmware") { + LERROR << "Error finding compatible android DT node"; + return false; + } + + file_name = android_dt_dir + "/" + key; + // DT entries terminate with '\0' but so do the properties + if (android::base::ReadFileToString(file_name, out_val)) { + return true; + } + + LERROR << "Error finding '" << key << "' in device tree"; + } + + return false; +} diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp index 44789cc90..0ab9f5fb8 100644 --- a/fs_mgr/fs_mgr_fstab.cpp +++ b/fs_mgr/fs_mgr_fstab.cpp @@ -603,6 +603,11 @@ int fs_mgr_is_verified(const struct fstab_rec *fstab) return fstab->fs_mgr_flags & MF_VERIFY; } +int fs_mgr_is_verifyatboot(const struct fstab_rec *fstab) +{ + return fstab->fs_mgr_flags & MF_VERIFYATBOOT; +} + int fs_mgr_is_encryptable(const struct fstab_rec *fstab) { return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE); diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h index 79c27c425..478c145d3 100644 --- a/fs_mgr/fs_mgr_priv.h +++ b/fs_mgr/fs_mgr_priv.h @@ -19,6 +19,7 @@ #include <android-base/logging.h> #include <fs_mgr.h> +#include "fs_mgr_priv_boot_config.h" /* The CHECK() in logging.h will use program invocation name as the tag. * Thus, the log will have prefix "init: " when libfs_mgr is statically diff --git a/fs_mgr/fs_mgr_priv_verity.h b/fs_mgr/fs_mgr_priv_boot_config.h index 1a6d215cb..74bb5eb07 100644 --- a/fs_mgr/fs_mgr_priv_verity.h +++ b/fs_mgr/fs_mgr_priv_boot_config.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 The Android Open Source Project + * 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. @@ -14,14 +14,12 @@ * limitations under the License. */ -#include <sys/cdefs.h> - -#define FS_MGR_SETUP_VERITY_DISABLED (-2) -#define FS_MGR_SETUP_VERITY_FAIL (-1) -#define FS_MGR_SETUP_VERITY_SUCCESS 0 +#ifndef __CORE_FS_MGR_PRIV_BOOTCONFIG_H +#define __CORE_FS_MGR_PRIV_BOOTCONFIG_H -__BEGIN_DECLS +#include <sys/cdefs.h> +#include <string> -int fs_mgr_setup_verity(struct fstab_rec *fstab, bool verify_dev); +bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val); -__END_DECLS +#endif /* __CORE_FS_MGR_PRIV_BOOTCONFIG_H */ diff --git a/fs_mgr/fs_mgr_slotselect.cpp b/fs_mgr/fs_mgr_slotselect.cpp index b30417fdc..f3bba7b93 100644 --- a/fs_mgr/fs_mgr_slotselect.cpp +++ b/fs_mgr/fs_mgr_slotselect.cpp @@ -14,118 +14,31 @@ * limitations under the License. */ -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <ctype.h> -#include <errno.h> #include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <android-base/file.h> -#include <android-base/stringprintf.h> -#include <android-base/strings.h> -#include <cutils/properties.h> #include "fs_mgr.h" #include "fs_mgr_priv.h" -// finds slot_suffix in androidboot.slot_suffix kernel command line argument -// or in the device tree node at /firmware/android/slot_suffix property -static int get_active_slot_suffix_from_kernel(char *out_suffix, - size_t suffix_len) -{ - std::string cmdline; - if (android::base::ReadFileToString("/proc/cmdline", &cmdline)) { - for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { - std::vector<std::string> pieces = android::base::Split(entry, "="); - if (pieces.size() == 2) { - if (pieces[0] == "androidboot.slot_suffix") { - strncpy(out_suffix, pieces[1].c_str(), suffix_len); - return 0; - } - } - } - } - - // if we can't find slot_suffix in cmdline, check the DT - static constexpr char android_dt_dir[] = "/proc/device-tree/firmware/android"; - std::string file_name = android::base::StringPrintf("%s/compatible", android_dt_dir); - std::string dt_value; - if (android::base::ReadFileToString(file_name, &dt_value)) { - if (!dt_value.compare("android,firmware")) { - LERROR << "Error finding compatible android DT node"; - return -1; - } - - file_name = android::base::StringPrintf("%s/%s", android_dt_dir, "slot_suffix"); - if (!android::base::ReadFileToString(file_name, &dt_value)) { - LERROR << "Error finding slot_suffix in device tree"; - return -1; - } - - // DT entries have a terminating '\0', so 'suffix_len' is safe. - strncpy(out_suffix, dt_value.c_str(), suffix_len); - return 0; - } - - // slot_suffix missing in kernel cmdline or device tree - return -1; -} - -// Gets slot_suffix from either the kernel cmdline / device tree. Sets -// |out_suffix| on success and returns 0. Returns -1 if slot_suffix could not -// be determined. -static int get_active_slot_suffix(char *out_suffix, size_t suffix_len) -{ - char propbuf[PROPERTY_VALUE_MAX]; - - // Get the suffix from the kernel commandline (note that we don't - // allow the empty suffix). On bootloaders natively supporting A/B - // we'll hit this path every time so don't bother logging it. - property_get("ro.boot.slot_suffix", propbuf, ""); - if (propbuf[0] != '\0') { - strncpy(out_suffix, propbuf, suffix_len); - return 0; - } - - // if the property is not set, we are probably being invoked early during - // boot. Try to find the slotsuffix ourselves in the kernel command line - // or the device tree - if (get_active_slot_suffix_from_kernel(out_suffix, suffix_len) == 0) { - LINFO << "Using slot suffix '" << out_suffix << "' from kernel"; - return 0; - } - - LERROR << "Error determining slot_suffix"; - - return -1; -} - // Updates |fstab| for slot_suffix. Returns 0 on success, -1 on error. int fs_mgr_update_for_slotselect(struct fstab *fstab) { int n; - char suffix[PROPERTY_VALUE_MAX]; int got_suffix = 0; + std::string suffix; for (n = 0; n < fstab->num_entries; n++) { if (fstab->recs[n].fs_mgr_flags & MF_SLOTSELECT) { char *tmp; if (!got_suffix) { - memset(suffix, '\0', sizeof(suffix)); - if (get_active_slot_suffix(suffix, sizeof(suffix) - 1) != 0) { + if (!fs_mgr_get_boot_config("slot_suffix", &suffix)) { return -1; } got_suffix = 1; } if (asprintf(&tmp, "%s%s", fstab->recs[n].blk_device, - suffix) > 0) { + suffix.c_str()) > 0) { free(fstab->recs[n].blk_device); fstab->recs[n].blk_device = tmp; } else { diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp index 1ec454072..2c9b0a974 100644 --- a/fs_mgr/fs_mgr_verity.cpp +++ b/fs_mgr/fs_mgr_verity.cpp @@ -45,7 +45,6 @@ #include "fs_mgr.h" #include "fs_mgr_priv.h" #include "fs_mgr_priv_dm_ioctl.h" -#include "fs_mgr_priv_verity.h" #define FSTAB_PREFIX "/fstab." @@ -658,7 +657,6 @@ static int get_verity_state_offset(struct fstab_rec *fstab, off64_t *offset) static int load_verity_state(struct fstab_rec *fstab, int *mode) { - char propbuf[PROPERTY_VALUE_MAX]; int match = 0; off64_t offset = 0; @@ -666,10 +664,9 @@ static int load_verity_state(struct fstab_rec *fstab, int *mode) *mode = VERITY_MODE_EIO; /* use the kernel parameter if set */ - property_get("ro.boot.veritymode", propbuf, ""); - - if (*propbuf != '\0') { - if (!strcmp(propbuf, "enforcing")) { + std::string veritymode; + if (fs_mgr_get_boot_config("veritymode", &veritymode)) { + if (veritymode.compare("enforcing")) { *mode = VERITY_MODE_DEFAULT; } return 0; @@ -859,7 +856,10 @@ static void update_verity_table_blk_device(char *blk_device, char **table) *table = strdup(result.c_str()); } -int fs_mgr_setup_verity(struct fstab_rec *fstab, bool verify_dev) +// prepares the verity enabled (MF_VERIFY / MF_VERIFYATBOOT) fstab record for +// mount. The 'wait_for_verity_dev' parameter makes this function wait for the +// verity device to get created before return +int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev) { int retval = FS_MGR_SETUP_VERITY_FAIL; int fd = -1; @@ -1026,7 +1026,7 @@ loaded: } // make sure we've set everything up properly - if (verify_dev && fs_mgr_test_access(fstab->blk_device) < 0) { + if (wait_for_verity_dev && fs_mgr_test_access(fstab->blk_device) < 0) { goto out; } diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h index 597651448..7498521b9 100644 --- a/fs_mgr/include/fs_mgr.h +++ b/fs_mgr/include/fs_mgr.h @@ -104,6 +104,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode); int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device, char *tmp_mount_point); +int fs_mgr_do_mount_one(struct fstab_rec *rec); int fs_mgr_do_tmpfs_mount(char *n_name); int fs_mgr_unmount_all(struct fstab *fstab); int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, @@ -117,6 +118,7 @@ struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const ch int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab); 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_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, @@ -134,10 +136,10 @@ int fs_mgr_swapon_all(struct fstab *fstab); int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer); -#define FS_MGR_EARLY_SETUP_VERITY_NO_VERITY -2 -#define FS_MGR_EARLY_SETUP_VERITY_FAIL -1 -#define FS_MGR_EARLY_SETUP_VERITY_SUCCESS 0 -int fs_mgr_early_setup_verity(struct fstab_rec *fstab); +#define FS_MGR_SETUP_VERITY_DISABLED (-2) +#define FS_MGR_SETUP_VERITY_FAIL (-1) +#define FS_MGR_SETUP_VERITY_SUCCESS 0 +int fs_mgr_setup_verity(struct fstab_rec *fstab, bool wait_for_verity_dev); #ifdef __cplusplus } diff --git a/init/devices.cpp b/init/devices.cpp index b3b808b89..5f54ff8fd 100644 --- a/init/devices.cpp +++ b/init/devices.cpp @@ -999,15 +999,20 @@ static coldboot_action_t coldboot(const char *path, coldboot_callback fn) } void device_init(const char* path, coldboot_callback fn) { - sehandle = selinux_android_file_context_handle(); - selinux_status_open(true); - - /* is 256K enough? udev uses 16MB! */ - device_fd.reset(uevent_open_socket(256*1024, true)); + if (!sehandle) { + sehandle = selinux_android_file_context_handle(); + } + // open uevent socket and selinux status only if it hasn't been + // done before if (device_fd == -1) { - return; + /* is 256K enough? udev uses 16MB! */ + device_fd.reset(uevent_open_socket(256 * 1024, true)); + if (device_fd == -1) { + return; + } + fcntl(device_fd, F_SETFL, O_NONBLOCK); + selinux_status_open(true); } - fcntl(device_fd, F_SETFL, O_NONBLOCK); if (access(COLDBOOT_DONE, F_OK) == 0) { LOG(VERBOSE) << "Skipping coldboot, already done!"; @@ -1040,6 +1045,7 @@ void device_init(const char* path, coldboot_callback fn) { void device_close() { destroy_platform_devices(); device_fd.reset(); + selinux_status_close(); } int get_device_fd() { diff --git a/init/init.cpp b/init/init.cpp index 7f7eb2f00..05f2cfd66 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -736,6 +736,38 @@ static std::string import_dt_fstab() { return fstab; } +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 << "'"; + 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; +} + /* Early mount vendor and ODM partitions. The fstab is read from device-tree. */ static bool early_mount() { std::string fstab = import_dt_fstab(); @@ -759,6 +791,8 @@ static bool early_mount() { } // find out fstab records for odm, system and vendor + // TODO: add std::map<std::string, fstab_rec*> so all required information about + // them can be gathered at once in a single loop fstab_rec* odm_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/odm"); fstab_rec* system_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/system"); fstab_rec* vendor_rec = fs_mgr_get_entry_for_mount_point(tab.get(), "/vendor"); @@ -767,13 +801,41 @@ static bool early_mount() { return true; } + // don't allow verifyatboot for early mounted partitions + if ((odm_rec && fs_mgr_is_verifyatboot(odm_rec)) || + (system_rec && fs_mgr_is_verifyatboot(system_rec)) || + (vendor_rec && fs_mgr_is_verifyatboot(vendor_rec))) { + LOG(ERROR) << "Early mount partitions can't be verified at boot"; + return false; + } + // assume A/B device if we find 'slotselect' in any fstab entry bool is_ab = ((odm_rec && fs_mgr_is_slotselect(odm_rec)) || (system_rec && fs_mgr_is_slotselect(system_rec)) || (vendor_rec && fs_mgr_is_slotselect(vendor_rec))); + + // check for verified partitions + bool need_verity = ((odm_rec && fs_mgr_is_verified(odm_rec)) || + (system_rec && fs_mgr_is_verified(system_rec)) || + (vendor_rec && fs_mgr_is_verified(vendor_rec))); + + // check if verity metadata is on a separate partition and get partition + // name from the end of the ->verity_loc path. verity state is not partition + // specific, so there must be only 1 additional partition that carries + // verity state. + std::string meta_partition; + if (odm_rec && odm_rec->verity_loc) { + meta_partition = basename(odm_rec->verity_loc); + } else if (system_rec && system_rec->verity_loc) { + meta_partition = basename(system_rec->verity_loc); + } else if (vendor_rec && vendor_rec->verity_loc) { + meta_partition = basename(vendor_rec->verity_loc); + } + bool found_odm = !odm_rec; bool found_system = !system_rec; bool found_vendor = !vendor_rec; + bool found_meta = meta_partition.empty(); int count_odm = 0, count_vendor = 0, count_system = 0; // create the devices we need.. @@ -802,9 +864,7 @@ static bool early_mount() { // wait twice for A/B-ed partitions count_odm++; - if (!is_ab) { - found_odm = true; - } else if (count_odm == 2) { + if (!is_ab || count_odm == 2) { found_odm = true; } @@ -813,9 +873,7 @@ static bool early_mount() { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; count_system++; - if (!is_ab) { - found_system = true; - } else if (count_system == 2) { + if (!is_ab || count_system == 2) { found_system = true; } @@ -823,13 +881,15 @@ static bool early_mount() { } else if (!found_vendor && !strncmp(uevent->partition_name, "vendor", 6)) { LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; count_vendor++; - if (!is_ab) { - found_vendor = true; - } else if (count_vendor == 2) { + if (!is_ab || count_vendor == 2) { found_vendor = true; } create_this_node = true; + } else if (!found_meta && (meta_partition == uevent->partition_name)) { + LOG(VERBOSE) << "early_mount: found (" << uevent->partition_name << ") partition"; + found_meta = true; + create_this_node = true; } } @@ -837,7 +897,7 @@ static bool early_mount() { // node and stop coldboot. If this is a prefix matched // partition, create device node and continue. For everything // else skip the device node - if (found_odm && found_system && found_vendor) { + if (found_meta && found_odm && found_system && found_vendor) { ret = COLDBOOT_STOP; } else if (create_this_node) { ret = COLDBOOT_CREATE; @@ -848,24 +908,20 @@ static bool early_mount() { return ret; }); - // TODO: add support to mount partitions w/ verity - - int ret = 0; - if (odm_rec && - (ret = fs_mgr_do_mount(tab.get(), odm_rec->mount_point, odm_rec->blk_device, NULL))) { - PLOG(ERROR) << "early_mount: fs_mgr_do_mount returned error for mounting odm"; - return false; + if (need_verity) { + // create /dev/device mapper + device_init("/sys/devices/virtual/misc/device-mapper", + [&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; }); } - if (vendor_rec && - (ret = fs_mgr_do_mount(tab.get(), vendor_rec->mount_point, vendor_rec->blk_device, NULL))) { - PLOG(ERROR) << "early_mount: fs_mgr_do_mount returned error for mounting vendor"; - return false; - } + bool success = true; + if (odm_rec && !(success = early_mount_one(odm_rec))) goto done; + if (system_rec && !(success = early_mount_one(system_rec))) goto done; + if (vendor_rec && !(success = early_mount_one(vendor_rec))) goto done; +done: device_close(); - - return true; + return success; } int main(int argc, char** argv) { |
