Merge changes from topic 'early-mount-support'
* changes: fs_mgr: add a generic fs_mgr_get_boot_config internal API init: early_mount: create device node for verity metadata partition init: early_mount: disallow partitions to be verified at boot init: early_mount: add support to mount verity enabled partitions early fs_mgr: make fs_mgr_setup_verity public API fs_mgr: fix the fs_mgr_setup_verity param name init: refactor to allow successive device_init calls fs_mgr: add fs_mgr_do_mount_one() API
This commit is contained in:
commit
4bd3facbb1
12 changed files with 232 additions and 173 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
71
fs_mgr/fs_mgr_boot_config.cpp
Normal file
71
fs_mgr/fs_mgr_boot_config.cpp
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -557,6 +557,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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
||||
#ifndef __CORE_FS_MGR_PRIV_BOOTCONFIG_H
|
||||
#define __CORE_FS_MGR_PRIV_BOOTCONFIG_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <string>
|
||||
|
||||
#define FS_MGR_SETUP_VERITY_DISABLED (-2)
|
||||
#define FS_MGR_SETUP_VERITY_FAIL (-1)
|
||||
#define FS_MGR_SETUP_VERITY_SUCCESS 0
|
||||
bool fs_mgr_get_boot_config(const std::string& key, std::string* out_val);
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int fs_mgr_setup_verity(struct fstab_rec *fstab, bool verify_dev);
|
||||
|
||||
__END_DECLS
|
||||
#endif /* __CORE_FS_MGR_PRIV_BOOTCONFIG_H */
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,6 +103,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,
|
||||
|
|
@ -116,6 +117,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);
|
||||
const char* fs_mgr_get_file_encryption_mode(const struct fstab_rec *fstab);
|
||||
|
|
@ -131,10 +133,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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 (device_fd == -1) {
|
||||
return;
|
||||
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) {
|
||||
/* 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() {
|
||||
|
|
|
|||
104
init/init.cpp
104
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,12 +881,14 @@ 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) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue