summaryrefslogtreecommitdiff
path: root/init
diff options
context:
space:
mode:
authorNikita Ioffe <ioffe@google.com>2024-03-05 00:23:31 +0000
committerNikita Ioffe <ioffe@google.com>2024-03-13 15:24:44 +0000
commit1e114e677b7196c0b48502f5f53fa32ae76a8a0a (patch)
treedfb45d17a049dc64a8ace8c2045e1cd2dedfe1b8 /init
parentfe7b83faeaeabe3a445c81a92e1fa22537d36d7e (diff)
downloadcore-1e114e677b7196c0b48502f5f53fa32ae76a8a0a.tar.gz
Add a step to derive microdroid vendor dice node
The derivation happens in the derive_microdroid_vendor_dice_node binary which first_stage_init forks and execvs. Since the derivation requires talking to the dice driver, its initialisation is also moved to the first stage init. The derivation happens before the microdroid vendor partition is verified & mounted. This should be safe because the first_stage_init will fail the boot if the verification of the microdroid vendor partition fails. Bug: 287593065 Test: run microdroid with and without vendor partition Test: atest MicrodroidTests Change-Id: I0d83772eb98a56c315617e66ec64bd03639cfde6
Diffstat (limited to 'init')
-rw-r--r--init/Android.bp2
-rw-r--r--init/block_dev_initializer.cpp18
-rw-r--r--init/block_dev_initializer.h3
-rw-r--r--init/first_stage_mount.cpp54
4 files changed, 71 insertions, 6 deletions
diff --git a/init/Android.bp b/init/Android.bp
index 419948454..12ca15ae3 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -463,7 +463,7 @@ cc_binary {
name: "init_first_stage.microdroid",
defaults: [
"avf_build_flags_cc",
- "init_first_stage_defaults"
+ "init_first_stage_defaults",
],
cflags: ["-DMICRODROID=1"],
installable: false,
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
index 05e00edfd..a686d0513 100644
--- a/init/block_dev_initializer.cpp
+++ b/init/block_dev_initializer.cpp
@@ -132,11 +132,19 @@ bool BlockDevInitializer::InitDevices(std::set<std::string> devices) {
bool BlockDevInitializer::InitDmDevice(const std::string& device) {
const std::string device_name(basename(device.c_str()));
const std::string syspath = "/sys/block/" + device_name;
+ return InitDevice(syspath, device_name);
+}
+
+bool BlockDevInitializer::InitPlatformDevice(const std::string& dev_name) {
+ return InitDevice("/sys/devices/platform", dev_name);
+}
+
+bool BlockDevInitializer::InitDevice(const std::string& syspath, const std::string& device_name) {
bool found = false;
- auto uevent_callback = [&device_name, &device, this, &found](const Uevent& uevent) {
+ auto uevent_callback = [&device_name, this, &found](const Uevent& uevent) {
if (uevent.device_name == device_name) {
- LOG(VERBOSE) << "Creating device-mapper device : " << device;
+ LOG(VERBOSE) << "Creating device : " << device_name;
device_handler_->HandleUevent(uevent);
found = true;
return ListenerAction::kStop;
@@ -146,13 +154,13 @@ bool BlockDevInitializer::InitDmDevice(const std::string& device) {
uevent_listener_.RegenerateUeventsForPath(syspath, uevent_callback);
if (!found) {
- LOG(INFO) << "dm device '" << device << "' not found in /sys, waiting for its uevent";
+ LOG(INFO) << "device '" << device_name << "' not found in /sys, waiting for its uevent";
Timer t;
uevent_listener_.Poll(uevent_callback, 10s);
- LOG(INFO) << "wait for dm device '" << device << "' returned after " << t;
+ LOG(INFO) << "wait for device '" << device_name << "' returned after " << t;
}
if (!found) {
- LOG(ERROR) << "dm device '" << device << "' not found after polling timeout";
+ LOG(ERROR) << "device '" << device_name << "' not found after polling timeout";
return false;
}
return true;
diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h
index ec39ce084..d5b1f6006 100644
--- a/init/block_dev_initializer.h
+++ b/init/block_dev_initializer.h
@@ -24,6 +24,7 @@
namespace android {
namespace init {
+// TODO: should this be renamed to FirstStageDevInitialize?
class BlockDevInitializer final {
public:
BlockDevInitializer();
@@ -32,11 +33,13 @@ class BlockDevInitializer final {
bool InitDmUser(const std::string& name);
bool InitDevices(std::set<std::string> devices);
bool InitDmDevice(const std::string& device);
+ bool InitPlatformDevice(const std::string& device);
private:
ListenerAction HandleUevent(const Uevent& uevent, std::set<std::string>* devices);
bool InitMiscDevice(const std::string& name);
+ bool InitDevice(const std::string& syspath, const std::string& device);
std::unique_ptr<DeviceHandler> device_handler_;
UeventListener uevent_listener_;
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index c0b928139..836d536c9 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -16,6 +16,7 @@
#include "first_stage_mount.h"
+#include <signal.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <unistd.h>
@@ -33,6 +34,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <android/avf_cc_flags.h>
#include <fs_avb/fs_avb.h>
#include <fs_mgr.h>
#include <fs_mgr_dm_linear.h>
@@ -272,6 +274,11 @@ bool FirstStageMountVBootV2::DoFirstStageMount() {
return true;
}
+// TODO: should this be in a library in packages/modules/Virtualization first_stage_init links?
+static bool IsMicrodroidStrictBoot() {
+ return access("/proc/device-tree/chosen/avf,strict-boot", F_OK) == 0;
+}
+
bool FirstStageMountVBootV2::InitDevices() {
std::set<std::string> devices;
GetSuperDeviceName(&devices);
@@ -283,6 +290,14 @@ bool FirstStageMountVBootV2::InitDevices() {
return false;
}
+ if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
+ if (IsMicrodroidStrictBoot()) {
+ if (!block_dev_init_.InitPlatformDevice("open-dice0")) {
+ return false;
+ }
+ }
+ }
+
if (IsDmLinearEnabled()) {
auto super_symlink = "/dev/block/by-name/"s + super_partition_name_;
if (!android::base::Realpath(super_symlink, &super_path_)) {
@@ -527,9 +542,48 @@ bool FirstStageMountVBootV2::TrySwitchSystemAsRoot() {
return true;
}
+static bool MaybeDeriveMicrodroidVendorDiceNode(Fstab* fstab) {
+ std::optional<std::string> microdroid_vendor_block_dev;
+ for (auto entry = fstab->begin(); entry != fstab->end(); entry++) {
+ if (entry->mount_point == "/vendor") {
+ microdroid_vendor_block_dev.emplace(entry->blk_device);
+ break;
+ }
+ }
+ if (!microdroid_vendor_block_dev.has_value()) {
+ LOG(VERBOSE) << "No microdroid vendor partition to mount";
+ return true;
+ }
+ // clang-format off
+ const std::array<const char*, 7> args = {
+ "/system/bin/derive_microdroid_vendor_dice_node",
+ "--dice-driver", "/dev/open-dice0",
+ "--microdroid-vendor-disk-image", microdroid_vendor_block_dev->data(),
+ "--output", "/microdroid_resources/dice_chain.raw",
+ };
+ // clang-format-on
+ // ForkExecveAndWaitForCompletion calls waitpid to wait for the fork-ed process to finish.
+ // The first_stage_console adds SA_NOCLDWAIT flag to the SIGCHLD handler, which means that
+ // waitpid will always return -ECHLD. Here we re-register a default handler, so that waitpid
+ // works.
+ LOG(INFO) << "Deriving dice node for microdroid vendor partition";
+ signal(SIGCHLD, SIG_DFL);
+ if (!ForkExecveAndWaitForCompletion(args[0], (char**)args.data())) {
+ LOG(ERROR) << "Failed to derive microdroid vendor dice node";
+ return false;
+ }
+ return true;
+}
+
bool FirstStageMountVBootV2::MountPartitions() {
if (!TrySwitchSystemAsRoot()) return false;
+ if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
+ if (!MaybeDeriveMicrodroidVendorDiceNode(&fstab_)) {
+ return false;
+ }
+ }
+
if (!SkipMountingPartitions(&fstab_, true /* verbose */)) return false;
for (auto current = fstab_.begin(); current != fstab_.end();) {