Merge changes from topic 'avb-early-mount' into oc-dev
* changes: fs_mgr: support AVB in fs_mgr_update_verity_state() init: support early_mount with vboot 2.0 (external/avb/libavb) fs_mgr: adds/changes some public APIs for early mount in init fs_mgr_avb: refactors how vbmeta is loaded fs_mgr: adding fs_mgr_get_slot_suffix() public API
This commit is contained in:
commit
cc23327951
|
@ -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 int handle_encryptable(const struct fstab_rec* rec)
|
|||
}
|
||||
}
|
||||
|
||||
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 fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
|
|||
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 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
|
|||
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 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
|
|||
}
|
||||
}
|
||||
|
||||
if (fs_mgr_is_avb_used()) {
|
||||
fs_mgr_unload_vbmeta_images();
|
||||
}
|
||||
|
||||
if (error_count) {
|
||||
return -1;
|
||||
} else {
|
||||
|
@ -976,17 +988,12 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
|
|||
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 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
|
|||
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 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
|
|||
}
|
||||
|
||||
out:
|
||||
if (fs_mgr_is_avb_used()) {
|
||||
fs_mgr_unload_vbmeta_images();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1259,3 +1262,97 @@ int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_dev
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 @@ static std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) {
|
|||
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::unique_ptr<FsManagerAvbVerifier> avb_verifier(new FsManagerAvbVerifier());
|
||||
if (!avb_verifier) {
|
||||
LERROR << "Failed to create unique_ptr<FsManagerAvbVerifier>";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string hash_alg;
|
||||
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 @@ static bool load_vbmeta_prop(androidboot_vbmeta* vbmeta_prop) {
|
|||
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 @@ static bool verify_vbmeta_images(const AvbSlotVerifyData& verify_data,
|
|||
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_load_verity_table(struct dm_ioctl* io, const std::string& d
|
|||
|
||||
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 @@ static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry,
|
|||
// 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 @@ static bool get_hashtree_descriptor(const std::string& partition_name,
|
|||
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 @@ static bool get_hashtree_descriptor(const std::string& partition_name,
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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_ == kFsManagerAvbHandleHashtreeDisabled) {
|
||||
LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point;
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 @@ static AvbIOResult dummy_validate_vbmeta_public_key(
|
|||
// 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 @@ static AvbIOResult dummy_get_unique_guid_for_partition(AvbOps* ops ATTRIBUTE_UNU
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -572,7 +572,7 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
|
|||
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 @@ int fs_mgr_is_verified(const struct fstab_rec *fstab)
|
|||
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;
|
||||
|
|
|
@ -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 @@ __BEGIN_DECLS
|
|||
|
||||
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 */
|
||||
|
|
|
@ -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 */
|
|
@ -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 SHA256Hasher {
|
|||
};
|
||||
|
||||
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); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -653,8 +653,7 @@ static int get_verity_state_offset(struct fstab_rec *fstab, off64_t *offset)
|
|||
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 @@ static int load_verity_state(struct fstab_rec *fstab, int *mode)
|
|||
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;
|
||||
|
|
|
@ -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_do_tmpfs_mount(const char *n_name);
|
|||
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_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_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 @@ int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
|
|||
#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 */
|
||||
|
|
|
@ -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 */
|
|
@ -109,8 +109,8 @@ LOCAL_STATIC_LIBRARIES := \
|
|||
libfec_rs \
|
||||
libsquashfs_utils \
|
||||
liblogwrap \
|
||||
libcutils \
|
||||
libext4_utils \
|
||||
libcutils \
|
||||
libbase \
|
||||
libc \
|
||||
libselinux \
|
||||
|
|
|
@ -678,11 +678,11 @@ static int do_sysclktz(const std::vector<std::string>& args) {
|
|||
|
||||
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 void verity_update_property(fstab_rec *fstab, const char *mount_point,
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
237
init/init.cpp
237
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 void export_kernel_boot_props() {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ static void process_kernel_dt() {
|
|||
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 void set_usb_controller() {
|
|||
}
|
||||
}
|
||||
|
||||
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 void early_device_init(std::set<std::string>* partition_names) {
|
|||
});
|
||||
}
|
||||
|
||||
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 @@ static bool get_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs
|
|||
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 @@ static bool early_mount() {
|
|||
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 @@ static bool early_mount() {
|
|||
[&](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();
|
||||
|
|
Loading…
Reference in New Issue