1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "first_stage_mount.h"
18
19 #include <signal.h>
20 #include <stdlib.h>
21 #include <sys/mount.h>
22 #include <unistd.h>
23
24 #include <chrono>
25 #include <filesystem>
26 #include <map>
27 #include <memory>
28 #include <set>
29 #include <string>
30 #include <vector>
31
32 #include <android-base/chrono_utils.h>
33 #include <android-base/file.h>
34 #include <android-base/logging.h>
35 #include <android-base/stringprintf.h>
36 #include <android-base/strings.h>
37 #include <android/avf_cc_flags.h>
38 #include <fs_avb/fs_avb.h>
39 #include <fs_mgr.h>
40 #include <fs_mgr_dm_linear.h>
41 #include <fs_mgr_overlayfs.h>
42 #include <libfiemap/image_manager.h>
43 #include <libgsi/libgsi.h>
44 #include <liblp/liblp.h>
45 #include <libsnapshot/snapshot.h>
46
47 #include "block_dev_initializer.h"
48 #include "devices.h"
49 #include "result.h"
50 #include "snapuserd_transition.h"
51 #include "switch_root.h"
52 #include "uevent.h"
53 #include "uevent_listener.h"
54 #include "util.h"
55
56 using android::base::ReadFileToString;
57 using android::base::Result;
58 using android::base::Split;
59 using android::base::StringPrintf;
60 using android::base::Timer;
61 using android::fiemap::IImageManager;
62 using android::fs_mgr::AvbHandle;
63 using android::fs_mgr::AvbHandleStatus;
64 using android::fs_mgr::AvbHashtreeResult;
65 using android::fs_mgr::AvbUniquePtr;
66 using android::fs_mgr::Fstab;
67 using android::fs_mgr::FstabEntry;
68 using android::fs_mgr::ReadDefaultFstab;
69 using android::fs_mgr::ReadFstabFromDt;
70 using android::fs_mgr::SkipMountingPartitions;
71 using android::fs_mgr::TransformFstabForDsu;
72 using android::snapshot::SnapshotManager;
73
74 using namespace std::literals;
75
76 namespace android {
77 namespace init {
78
79 // Class Declarations
80 // ------------------
81 class FirstStageMountVBootV2 : public FirstStageMount {
82 public:
83 friend void SetInitAvbVersionInRecovery();
84
85 FirstStageMountVBootV2(Fstab fstab);
86 virtual ~FirstStageMountVBootV2() = default;
87
88 bool DoCreateDevices() override;
89 bool DoFirstStageMount() override;
90
91 private:
92 bool InitDevices();
93 bool InitRequiredDevices(std::set<std::string> devices);
94 bool CreateLogicalPartitions();
95 bool CreateSnapshotPartitions(SnapshotManager* sm);
96 bool MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
97 Fstab::iterator* end = nullptr);
98
99 bool MountPartitions();
100 bool TrySwitchSystemAsRoot();
101 bool IsDmLinearEnabled();
102 void GetSuperDeviceName(std::set<std::string>* devices);
103 bool InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata& metadata);
104 void UseDsuIfPresent();
105 // Reads all fstab.avb_keys from the ramdisk for first-stage mount.
106 void PreloadAvbKeys();
107 // Copies /avb/*.avbpubkey used for DSU from the ramdisk to /metadata for key
108 // revocation check by DSU installation service.
109 void CopyDsuAvbKeys();
110
111 bool GetDmVerityDevices(std::set<std::string>* devices);
112 bool SetUpDmVerity(FstabEntry* fstab_entry);
113
114 bool InitAvbHandle();
115
116 bool need_dm_verity_;
117 bool dsu_not_on_userdata_ = false;
118 bool use_snapuserd_ = false;
119
120 Fstab fstab_;
121 // The super path is only set after InitDevices, and is invalid before.
122 std::string super_path_;
123 std::string super_partition_name_;
124 BlockDevInitializer block_dev_init_;
125 // Reads all AVB keys before chroot into /system, as they might be used
126 // later when mounting other partitions, e.g., /vendor and /product.
127 std::map<std::string, std::vector<std::string>> preload_avb_key_blobs_;
128
129 std::vector<std::string> vbmeta_partitions_;
130 AvbUniquePtr avb_handle_;
131 };
132
133 // Static Functions
134 // ----------------
IsDtVbmetaCompatible(const Fstab & fstab)135 static inline bool IsDtVbmetaCompatible(const Fstab& fstab) {
136 if (std::any_of(fstab.begin(), fstab.end(),
137 [](const auto& entry) { return entry.fs_mgr_flags.avb; })) {
138 return true;
139 }
140 return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
141 }
142
ReadFirstStageFstabAndroid()143 static Result<Fstab> ReadFirstStageFstabAndroid() {
144 Fstab fstab;
145 if (!ReadFstabFromDt(&fstab)) {
146 if (ReadDefaultFstab(&fstab)) {
147 fstab.erase(std::remove_if(fstab.begin(), fstab.end(),
148 [](const auto& entry) {
149 return !entry.fs_mgr_flags.first_stage_mount;
150 }),
151 fstab.end());
152 } else {
153 return Error() << "failed to read default fstab for first stage mount";
154 }
155 }
156 return fstab;
157 }
158
159 // Note: this is a temporary solution to avoid blocking devs that depend on /vendor partition in
160 // Microdroid. For the proper solution the /vendor fstab should probably be defined in the DT.
161 // TODO(b/285855430): refactor this
162 // TODO(b/285855436): verify key microdroid-vendor was signed with.
163 // TODO(b/285855436): should be mounted on top of dm-verity device.
ReadFirstStageFstabMicrodroid(const std::string & cmdline)164 static Result<Fstab> ReadFirstStageFstabMicrodroid(const std::string& cmdline) {
165 Fstab fstab;
166 if (!ReadDefaultFstab(&fstab)) {
167 return Error() << "failed to read fstab";
168 }
169 if (cmdline.find("androidboot.microdroid.mount_vendor=1") == std::string::npos) {
170 // We weren't asked to mount /vendor partition, filter it out from the fstab.
171 auto predicate = [](const auto& entry) { return entry.mount_point == "/vendor"; };
172 fstab.erase(std::remove_if(fstab.begin(), fstab.end(), predicate), fstab.end());
173 }
174 return fstab;
175 }
176
GetRootEntry(FstabEntry * root_entry)177 static bool GetRootEntry(FstabEntry* root_entry) {
178 Fstab proc_mounts;
179 if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
180 LOG(ERROR) << "Could not read /proc/mounts and /system not in fstab, /system will not be "
181 "available for overlayfs";
182 return false;
183 }
184
185 auto entry = std::find_if(proc_mounts.begin(), proc_mounts.end(), [](const auto& entry) {
186 return entry.mount_point == "/" && entry.fs_type != "rootfs";
187 });
188
189 if (entry == proc_mounts.end()) {
190 LOG(ERROR) << "Could not get mount point for '/' in /proc/mounts, /system will not be "
191 "available for overlayfs";
192 return false;
193 }
194
195 *root_entry = std::move(*entry);
196
197 // We don't know if we're avb or not, so we query device mapper as if we are avb. If we get a
198 // success, then mark as avb, otherwise default to verify.
199 auto& dm = android::dm::DeviceMapper::Instance();
200 if (dm.GetState("vroot") != android::dm::DmDeviceState::INVALID) {
201 root_entry->fs_mgr_flags.avb = true;
202 }
203 return true;
204 }
205
IsStandaloneImageRollback(const AvbHandle & builtin_vbmeta,const AvbHandle & standalone_vbmeta,const FstabEntry & fstab_entry)206 static bool IsStandaloneImageRollback(const AvbHandle& builtin_vbmeta,
207 const AvbHandle& standalone_vbmeta,
208 const FstabEntry& fstab_entry) {
209 std::string old_spl = builtin_vbmeta.GetSecurityPatchLevel(fstab_entry);
210 std::string new_spl = standalone_vbmeta.GetSecurityPatchLevel(fstab_entry);
211
212 bool rollbacked = false;
213 if (old_spl.empty() || new_spl.empty() || new_spl < old_spl) {
214 rollbacked = true;
215 }
216
217 if (rollbacked) {
218 LOG(ERROR) << "Image rollback detected for " << fstab_entry.mount_point
219 << ", SPL switches from '" << old_spl << "' to '" << new_spl << "'";
220 if (AvbHandle::IsDeviceUnlocked()) {
221 LOG(INFO) << "Allowing rollbacked standalone image when the device is unlocked";
222 return false;
223 }
224 }
225
226 return rollbacked;
227 }
228
Create(const std::string & cmdline)229 Result<std::unique_ptr<FirstStageMount>> FirstStageMount::Create(const std::string& cmdline) {
230 Result<Fstab> fstab;
231 if (IsMicrodroid()) {
232 fstab = ReadFirstStageFstabMicrodroid(cmdline);
233 } else {
234 fstab = ReadFirstStageFstabAndroid();
235 }
236 if (!fstab.ok()) {
237 return fstab.error();
238 }
239
240 return std::make_unique<FirstStageMountVBootV2>(std::move(*fstab));
241 }
242
DoCreateDevices()243 bool FirstStageMountVBootV2::DoCreateDevices() {
244 if (!InitDevices()) return false;
245
246 // Mount /metadata before creating logical partitions, since we need to
247 // know whether a snapshot merge is in progress.
248 auto metadata_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
249 return entry.mount_point == "/metadata";
250 });
251 if (metadata_partition != fstab_.end()) {
252 if (MountPartition(metadata_partition, true /* erase_same_mounts */)) {
253 // Copies DSU AVB keys from the ramdisk to /metadata.
254 // Must be done before the following TrySwitchSystemAsRoot().
255 // Otherwise, ramdisk will be inaccessible after switching root.
256 CopyDsuAvbKeys();
257 }
258 }
259
260 if (!CreateLogicalPartitions()) return false;
261
262 return true;
263 }
264
DoFirstStageMount()265 bool FirstStageMountVBootV2::DoFirstStageMount() {
266 if (!IsDmLinearEnabled() && fstab_.empty()) {
267 // Nothing to mount.
268 LOG(INFO) << "First stage mount skipped (missing/incompatible/empty fstab in device tree)";
269 return true;
270 }
271
272 if (!MountPartitions()) return false;
273
274 return true;
275 }
276
277 // TODO: should this be in a library in packages/modules/Virtualization first_stage_init links?
IsMicrodroidStrictBoot()278 static bool IsMicrodroidStrictBoot() {
279 return access("/proc/device-tree/chosen/avf,strict-boot", F_OK) == 0;
280 }
281
InitDevices()282 bool FirstStageMountVBootV2::InitDevices() {
283 std::set<std::string> devices;
284 GetSuperDeviceName(&devices);
285
286 if (!GetDmVerityDevices(&devices)) {
287 return false;
288 }
289 if (!InitRequiredDevices(std::move(devices))) {
290 return false;
291 }
292
293 if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
294 if (IsMicrodroidStrictBoot()) {
295 if (!block_dev_init_.InitPlatformDevice("open-dice0")) {
296 return false;
297 }
298 }
299 }
300
301 if (IsDmLinearEnabled()) {
302 auto super_symlink = "/dev/block/by-name/"s + super_partition_name_;
303 if (!android::base::Realpath(super_symlink, &super_path_)) {
304 PLOG(ERROR) << "realpath failed: " << super_symlink;
305 return false;
306 }
307 }
308 return true;
309 }
310
IsDmLinearEnabled()311 bool FirstStageMountVBootV2::IsDmLinearEnabled() {
312 for (const auto& entry : fstab_) {
313 if (entry.fs_mgr_flags.logical) return true;
314 }
315 return false;
316 }
317
GetSuperDeviceName(std::set<std::string> * devices)318 void FirstStageMountVBootV2::GetSuperDeviceName(std::set<std::string>* devices) {
319 // Add any additional devices required for dm-linear mappings.
320 if (!IsDmLinearEnabled()) {
321 return;
322 }
323
324 devices->emplace(super_partition_name_);
325 }
326
327 // Creates devices with uevent->partition_name matching ones in the given set.
328 // Found partitions will then be removed from it for the subsequent member
329 // function to check which devices are NOT created.
InitRequiredDevices(std::set<std::string> devices)330 bool FirstStageMountVBootV2::InitRequiredDevices(std::set<std::string> devices) {
331 if (!block_dev_init_.InitDeviceMapper()) {
332 return false;
333 }
334 if (devices.empty()) {
335 return true;
336 }
337 return block_dev_init_.InitDevices(std::move(devices));
338 }
339
InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata & metadata)340 bool FirstStageMountVBootV2::InitDmLinearBackingDevices(
341 const android::fs_mgr::LpMetadata& metadata) {
342 std::set<std::string> devices;
343
344 auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
345 for (const auto& partition_name : partition_names) {
346 // The super partition was found in the earlier pass.
347 if (partition_name == super_partition_name_) {
348 continue;
349 }
350 devices.emplace(partition_name);
351 }
352 if (devices.empty()) {
353 return true;
354 }
355 return InitRequiredDevices(std::move(devices));
356 }
357
CreateLogicalPartitions()358 bool FirstStageMountVBootV2::CreateLogicalPartitions() {
359 if (!IsDmLinearEnabled()) {
360 return true;
361 }
362 if (super_path_.empty()) {
363 LOG(ERROR) << "Could not locate logical partition tables in partition "
364 << super_partition_name_;
365 return false;
366 }
367
368 if (SnapshotManager::IsSnapshotManagerNeeded()) {
369 auto sm = SnapshotManager::NewForFirstStageMount();
370 if (!sm) {
371 return false;
372 }
373 if (sm->NeedSnapshotsInFirstStageMount()) {
374 return CreateSnapshotPartitions(sm.get());
375 }
376 }
377
378 auto metadata = android::fs_mgr::ReadCurrentMetadata(super_path_);
379 if (!metadata) {
380 LOG(ERROR) << "Could not read logical partition metadata from " << super_path_;
381 return false;
382 }
383 if (!InitDmLinearBackingDevices(*metadata.get())) {
384 return false;
385 }
386 return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path_);
387 }
388
CreateSnapshotPartitions(SnapshotManager * sm)389 bool FirstStageMountVBootV2::CreateSnapshotPartitions(SnapshotManager* sm) {
390 // When COW images are present for snapshots, they are stored on
391 // the data partition.
392 if (!InitRequiredDevices({"userdata"})) {
393 return false;
394 }
395
396 use_snapuserd_ = sm->IsSnapuserdRequired();
397 if (use_snapuserd_) {
398 if (sm->UpdateUsesUserSnapshots()) {
399 LaunchFirstStageSnapuserd();
400 } else {
401 LOG(FATAL) << "legacy virtual-ab is no longer supported";
402 return false;
403 }
404 }
405
406 sm->SetUeventRegenCallback([this](const std::string& device) -> bool {
407 if (android::base::StartsWith(device, "/dev/block/dm-")) {
408 return block_dev_init_.InitDmDevice(device);
409 }
410 if (android::base::StartsWith(device, "/dev/dm-user/")) {
411 return block_dev_init_.InitDmUser(android::base::Basename(device));
412 }
413 return block_dev_init_.InitDevices({device});
414 });
415 if (!sm->CreateLogicalAndSnapshotPartitions(super_path_)) {
416 return false;
417 }
418
419 if (use_snapuserd_) {
420 CleanupSnapuserdSocket();
421 }
422 return true;
423 }
424
MountPartition(const Fstab::iterator & begin,bool erase_same_mounts,Fstab::iterator * end)425 bool FirstStageMountVBootV2::MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
426 Fstab::iterator* end) {
427 // Sets end to begin + 1, so we can just return on failure below.
428 if (end) {
429 *end = begin + 1;
430 }
431
432 if (!fs_mgr_create_canonical_mount_point(begin->mount_point)) {
433 return false;
434 }
435
436 if (begin->fs_mgr_flags.logical) {
437 if (!fs_mgr_update_logical_partition(&(*begin))) {
438 return false;
439 }
440 if (!block_dev_init_.InitDmDevice(begin->blk_device)) {
441 return false;
442 }
443 }
444 if (!SetUpDmVerity(&(*begin))) {
445 PLOG(ERROR) << "Failed to setup verity for '" << begin->mount_point << "'";
446 return false;
447 }
448
449 bool mounted = (fs_mgr_do_mount_one(*begin) == 0);
450
451 // Try other mounts with the same mount point.
452 Fstab::iterator current = begin + 1;
453 for (; current != fstab_.end() && current->mount_point == begin->mount_point; current++) {
454 if (!mounted) {
455 // blk_device is already updated to /dev/dm-<N> by SetUpDmVerity() above.
456 // Copy it from the begin iterator.
457 current->blk_device = begin->blk_device;
458 mounted = (fs_mgr_do_mount_one(*current) == 0);
459 }
460 }
461 if (erase_same_mounts) {
462 current = fstab_.erase(begin, current);
463 }
464 if (end) {
465 *end = current;
466 }
467 return mounted;
468 }
469
PreloadAvbKeys()470 void FirstStageMountVBootV2::PreloadAvbKeys() {
471 for (const auto& entry : fstab_) {
472 // No need to cache the key content if it's empty, or is already cached.
473 if (entry.avb_keys.empty() || preload_avb_key_blobs_.count(entry.avb_keys)) {
474 continue;
475 }
476
477 // Determines all key paths first.
478 std::vector<std::string> key_paths;
479 if (is_dir(entry.avb_keys.c_str())) { // fstab_keys might be a dir, e.g., /avb.
480 const char* avb_key_dir = entry.avb_keys.c_str();
481 std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(avb_key_dir), closedir);
482 if (!dir) {
483 LOG(ERROR) << "Failed to opendir: " << dir;
484 continue;
485 }
486 // Gets all key pathes under the dir.
487 struct dirent* de;
488 while ((de = readdir(dir.get()))) {
489 if (de->d_type != DT_REG) continue;
490 std::string full_path = StringPrintf("%s/%s", avb_key_dir, de->d_name);
491 key_paths.emplace_back(std::move(full_path));
492 }
493 std::sort(key_paths.begin(), key_paths.end());
494 } else {
495 // avb_keys are key paths separated by ":", if it's not a dir.
496 key_paths = Split(entry.avb_keys, ":");
497 }
498
499 // Reads the key content then cache it.
500 std::vector<std::string> key_blobs;
501 for (const auto& path : key_paths) {
502 std::string key_value;
503 if (!ReadFileToString(path, &key_value)) {
504 continue;
505 }
506 key_blobs.emplace_back(std::move(key_value));
507 }
508
509 // Maps entry.avb_keys to actual key blobs.
510 preload_avb_key_blobs_[entry.avb_keys] = std::move(key_blobs);
511 }
512 }
513
514 // If system is in the fstab then we're not a system-as-root device, and in
515 // this case, we mount system first then pivot to it. From that point on,
516 // we are effectively identical to a system-as-root device.
TrySwitchSystemAsRoot()517 bool FirstStageMountVBootV2::TrySwitchSystemAsRoot() {
518 UseDsuIfPresent();
519 // Preloading all AVB keys from the ramdisk before switching root to /system.
520 PreloadAvbKeys();
521
522 auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
523 return entry.mount_point == "/system";
524 });
525
526 if (system_partition == fstab_.end()) return true;
527
528 if (use_snapuserd_) {
529 SaveRamdiskPathToSnapuserd();
530 }
531
532 if (!MountPartition(system_partition, false /* erase_same_mounts */)) {
533 PLOG(ERROR) << "Failed to mount /system";
534 return false;
535 }
536 if (dsu_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
537 LOG(ERROR) << "check_at_most_once forbidden on external media";
538 return false;
539 }
540
541 SwitchRoot("/system");
542
543 return true;
544 }
545
MaybeDeriveMicrodroidVendorDiceNode(Fstab * fstab)546 static bool MaybeDeriveMicrodroidVendorDiceNode(Fstab* fstab) {
547 std::optional<std::string> microdroid_vendor_block_dev;
548 for (auto entry = fstab->begin(); entry != fstab->end(); entry++) {
549 if (entry->mount_point == "/vendor") {
550 microdroid_vendor_block_dev.emplace(entry->blk_device);
551 break;
552 }
553 }
554 if (!microdroid_vendor_block_dev.has_value()) {
555 LOG(VERBOSE) << "No microdroid vendor partition to mount";
556 return true;
557 }
558 // clang-format off
559 const std::array<const char*, 8> args = {
560 "/system/bin/derive_microdroid_vendor_dice_node",
561 "--dice-driver", "/dev/open-dice0",
562 "--microdroid-vendor-disk-image", microdroid_vendor_block_dev->data(),
563 "--output", "/microdroid_resources/dice_chain.raw", nullptr,
564 };
565 // clang-format-on
566 // ForkExecveAndWaitForCompletion calls waitpid to wait for the fork-ed process to finish.
567 // The first_stage_console adds SA_NOCLDWAIT flag to the SIGCHLD handler, which means that
568 // waitpid will always return -ECHLD. Here we re-register a default handler, so that waitpid
569 // works.
570 LOG(INFO) << "Deriving dice node for microdroid vendor partition";
571 signal(SIGCHLD, SIG_DFL);
572 if (!ForkExecveAndWaitForCompletion(args[0], (char**)args.data())) {
573 LOG(ERROR) << "Failed to derive microdroid vendor dice node";
574 return false;
575 }
576 return true;
577 }
578
MountPartitions()579 bool FirstStageMountVBootV2::MountPartitions() {
580 if (!TrySwitchSystemAsRoot()) return false;
581
582 if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
583 if (!MaybeDeriveMicrodroidVendorDiceNode(&fstab_)) {
584 return false;
585 }
586 }
587
588 if (!SkipMountingPartitions(&fstab_, true /* verbose */)) return false;
589
590 for (auto current = fstab_.begin(); current != fstab_.end();) {
591 // We've already mounted /system above.
592 if (current->mount_point == "/system") {
593 ++current;
594 continue;
595 }
596
597 // Handle overlayfs entries later.
598 if (current->fs_type == "overlay") {
599 ++current;
600 continue;
601 }
602
603 // Skip raw partition entries such as boot, dtbo, etc.
604 // Having emmc fstab entries allows us to probe current->vbmeta_partition
605 // in InitDevices() when they are AVB chained partitions.
606 if (current->fs_type == "emmc") {
607 ++current;
608 continue;
609 }
610
611 Fstab::iterator end;
612 if (!MountPartition(current, false /* erase_same_mounts */, &end)) {
613 if (current->fs_mgr_flags.no_fail) {
614 LOG(INFO) << "Failed to mount " << current->mount_point
615 << ", ignoring mount for no_fail partition";
616 } else if (current->fs_mgr_flags.formattable) {
617 LOG(INFO) << "Failed to mount " << current->mount_point
618 << ", ignoring mount for formattable partition";
619 } else {
620 PLOG(ERROR) << "Failed to mount " << current->mount_point;
621 return false;
622 }
623 }
624 current = end;
625 }
626
627 for (const auto& entry : fstab_) {
628 if (entry.fs_type == "overlay") {
629 fs_mgr_mount_overlayfs_fstab_entry(entry);
630 }
631 }
632
633 // If we don't see /system or / in the fstab, then we need to create an root entry for
634 // overlayfs.
635 if (!GetEntryForMountPoint(&fstab_, "/system") && !GetEntryForMountPoint(&fstab_, "/")) {
636 FstabEntry root_entry;
637 if (GetRootEntry(&root_entry)) {
638 fstab_.emplace_back(std::move(root_entry));
639 }
640 }
641
642 // heads up for instantiating required device(s) for overlayfs logic
643 auto init_devices = [this](std::set<std::string> devices) -> bool {
644 for (auto iter = devices.begin(); iter != devices.end();) {
645 if (android::base::StartsWith(*iter, "/dev/block/dm-")) {
646 if (!block_dev_init_.InitDmDevice(*iter)) {
647 return false;
648 }
649 iter = devices.erase(iter);
650 } else {
651 iter++;
652 }
653 }
654 return InitRequiredDevices(std::move(devices));
655 };
656 MapScratchPartitionIfNeeded(&fstab_, init_devices);
657
658 fs_mgr_overlayfs_mount_all(&fstab_);
659
660 return true;
661 }
662
663 // Preserves /avb/*.avbpubkey to /metadata/gsi/dsu/avb/, so they can be used for
664 // key revocation check by DSU installation service. Note that failing to
665 // copy files to /metadata is NOT fatal, because it is auxiliary to perform
666 // public key matching before booting into DSU images on next boot. The actual
667 // public key matching will still be done on next boot to DSU.
CopyDsuAvbKeys()668 void FirstStageMountVBootV2::CopyDsuAvbKeys() {
669 std::error_code ec;
670 // Removing existing keys in gsi::kDsuAvbKeyDir as they might be stale.
671 std::filesystem::remove_all(gsi::kDsuAvbKeyDir, ec);
672 if (ec) {
673 LOG(ERROR) << "Failed to remove directory " << gsi::kDsuAvbKeyDir << ": " << ec.message();
674 }
675 // Copy keys from the ramdisk /avb/* to gsi::kDsuAvbKeyDir.
676 static constexpr char kRamdiskAvbKeyDir[] = "/avb";
677 std::filesystem::copy(kRamdiskAvbKeyDir, gsi::kDsuAvbKeyDir, ec);
678 if (ec) {
679 LOG(ERROR) << "Failed to copy " << kRamdiskAvbKeyDir << " into " << gsi::kDsuAvbKeyDir
680 << ": " << ec.message();
681 }
682 }
683
UseDsuIfPresent()684 void FirstStageMountVBootV2::UseDsuIfPresent() {
685 std::string error;
686
687 if (!android::gsi::CanBootIntoGsi(&error)) {
688 LOG(INFO) << "DSU " << error << ", proceeding with normal boot";
689 return;
690 }
691
692 auto init_devices = [this](std::set<std::string> devices) -> bool {
693 if (devices.count("userdata") == 0 || devices.size() > 1) {
694 dsu_not_on_userdata_ = true;
695 }
696 return InitRequiredDevices(std::move(devices));
697 };
698 std::string active_dsu;
699 if (!gsi::GetActiveDsu(&active_dsu)) {
700 LOG(ERROR) << "Failed to GetActiveDsu";
701 return;
702 }
703 LOG(INFO) << "DSU slot: " << active_dsu;
704 auto images = IImageManager::Open("dsu/" + active_dsu, 0ms);
705 if (!images || !images->MapAllImages(init_devices)) {
706 LOG(ERROR) << "DSU partition layout could not be instantiated";
707 return;
708 }
709
710 if (!android::gsi::MarkSystemAsGsi()) {
711 PLOG(ERROR) << "DSU indicator file could not be written";
712 return;
713 }
714
715 // Publish the logical partition names for TransformFstabForDsu() and ReadFstabFromFile().
716 const auto dsu_partitions = images->GetAllBackingImages();
717 WriteFile(gsi::kGsiLpNamesFile, android::base::Join(dsu_partitions, ","));
718 TransformFstabForDsu(&fstab_, active_dsu, dsu_partitions);
719 }
720
FirstStageMountVBootV2(Fstab fstab)721 FirstStageMountVBootV2::FirstStageMountVBootV2(Fstab fstab)
722 : need_dm_verity_(false), fstab_(std::move(fstab)), avb_handle_(nullptr) {
723 super_partition_name_ = fs_mgr_get_super_partition_name();
724
725 std::string device_tree_vbmeta_parts;
726 read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts);
727
728 for (auto&& partition : Split(device_tree_vbmeta_parts, ",")) {
729 if (!partition.empty()) {
730 vbmeta_partitions_.emplace_back(std::move(partition));
731 }
732 }
733
734 for (const auto& entry : fstab_) {
735 if (!entry.vbmeta_partition.empty()) {
736 vbmeta_partitions_.emplace_back(entry.vbmeta_partition);
737 }
738 }
739
740 if (vbmeta_partitions_.empty()) {
741 LOG(ERROR) << "Failed to read vbmeta partitions.";
742 }
743 }
744
GetDmVerityDevices(std::set<std::string> * devices)745 bool FirstStageMountVBootV2::GetDmVerityDevices(std::set<std::string>* devices) {
746 need_dm_verity_ = false;
747
748 std::set<std::string> logical_partitions;
749
750 // fstab_rec->blk_device has A/B suffix.
751 for (const auto& fstab_entry : fstab_) {
752 if (fstab_entry.fs_mgr_flags.avb) {
753 need_dm_verity_ = true;
754 }
755 // Skip pseudo filesystems.
756 if (fstab_entry.fs_type == "overlay") {
757 continue;
758 }
759 if (fstab_entry.fs_mgr_flags.logical) {
760 // Don't try to find logical partitions via uevent regeneration.
761 logical_partitions.emplace(basename(fstab_entry.blk_device.c_str()));
762 } else {
763 devices->emplace(basename(fstab_entry.blk_device.c_str()));
764 }
765 }
766
767 // Any partitions needed for verifying the partitions used in first stage mount, e.g. vbmeta
768 // must be provided as vbmeta_partitions.
769 if (need_dm_verity_) {
770 if (vbmeta_partitions_.empty()) {
771 LOG(ERROR) << "Missing vbmeta partitions";
772 return false;
773 }
774 std::string ab_suffix = fs_mgr_get_slot_suffix();
775 for (const auto& partition : vbmeta_partitions_) {
776 std::string partition_name = partition + ab_suffix;
777 if (logical_partitions.count(partition_name)) {
778 continue;
779 }
780 // devices is of type std::set so it's not an issue to emplace a
781 // partition twice. e.g., /vendor might be in both places:
782 // - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
783 // - mount_fstab_recs_: /vendor_a
784 devices->emplace(partition_name);
785 }
786 }
787 return true;
788 }
789
IsHashtreeDisabled(const AvbHandle & vbmeta,const std::string & mount_point)790 bool IsHashtreeDisabled(const AvbHandle& vbmeta, const std::string& mount_point) {
791 if (vbmeta.status() == AvbHandleStatus::kHashtreeDisabled ||
792 vbmeta.status() == AvbHandleStatus::kVerificationDisabled) {
793 LOG(ERROR) << "Top-level vbmeta is disabled, skip Hashtree setup for " << mount_point;
794 return true; // Returns true to mount the partition directly.
795 }
796 return false;
797 }
798
SetUpDmVerity(FstabEntry * fstab_entry)799 bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) {
800 AvbHashtreeResult hashtree_result;
801
802 // It's possible for a fstab_entry to have both avb_keys and avb flag.
803 // In this case, try avb_keys first, then fallback to avb flag.
804 if (!fstab_entry->avb_keys.empty()) {
805 if (!InitAvbHandle()) return false;
806 // Checks if hashtree should be disabled from the top-level /vbmeta.
807 if (IsHashtreeDisabled(*avb_handle_, fstab_entry->mount_point)) {
808 return true;
809 }
810 auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(
811 *fstab_entry, preload_avb_key_blobs_[fstab_entry->avb_keys]);
812 if (!avb_standalone_handle) {
813 LOG(ERROR) << "Failed to load offline vbmeta for " << fstab_entry->mount_point;
814 // Fallbacks to built-in hashtree if fs_mgr_flags.avb is set.
815 if (!fstab_entry->fs_mgr_flags.avb) return false;
816 LOG(INFO) << "Fallback to built-in hashtree for " << fstab_entry->mount_point;
817 hashtree_result =
818 avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */);
819 } else {
820 // Sets up hashtree via the standalone handle.
821 if (IsStandaloneImageRollback(*avb_handle_, *avb_standalone_handle, *fstab_entry)) {
822 return false;
823 }
824 hashtree_result = avb_standalone_handle->SetUpAvbHashtree(
825 fstab_entry, false /* wait_for_verity_dev */);
826 }
827 } else if (fstab_entry->fs_mgr_flags.avb) {
828 if (!InitAvbHandle()) return false;
829 hashtree_result =
830 avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */);
831 } else if (!fstab_entry->avb_hashtree_digest.empty()) {
832 // When fstab_entry has neither avb_keys nor avb flag, try using
833 // avb_hashtree_digest.
834 if (!InitAvbHandle()) return false;
835 // Checks if hashtree should be disabled from the top-level /vbmeta.
836 if (IsHashtreeDisabled(*avb_handle_, fstab_entry->mount_point)) {
837 return true;
838 }
839 auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(*fstab_entry);
840 if (!avb_standalone_handle) {
841 LOG(ERROR) << "Failed to load vbmeta based on hashtree descriptor root digest for "
842 << fstab_entry->mount_point;
843 return false;
844 }
845 hashtree_result = avb_standalone_handle->SetUpAvbHashtree(fstab_entry,
846 false /* wait_for_verity_dev */);
847 } else {
848 return true; // No need AVB, returns true to mount the partition directly.
849 }
850
851 switch (hashtree_result) {
852 case AvbHashtreeResult::kDisabled:
853 return true; // Returns true to mount the partition.
854 case AvbHashtreeResult::kSuccess:
855 // The exact block device name (fstab_rec->blk_device) is changed to
856 // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
857 // first stage.
858 return block_dev_init_.InitDmDevice(fstab_entry->blk_device);
859 default:
860 return false;
861 }
862 }
863
InitAvbHandle()864 bool FirstStageMountVBootV2::InitAvbHandle() {
865 if (avb_handle_) return true; // Returns true if the handle is already initialized.
866
867 avb_handle_ = AvbHandle::Open();
868
869 if (!avb_handle_) {
870 PLOG(ERROR) << "Failed to open AvbHandle";
871 return false;
872 }
873 // Sets INIT_AVB_VERSION here for init to set ro.boot.avb_version in the second stage.
874 setenv("INIT_AVB_VERSION", avb_handle_->avb_version().c_str(), 1);
875 return true;
876 }
877
SetInitAvbVersionInRecovery()878 void SetInitAvbVersionInRecovery() {
879 if (!IsRecoveryMode()) {
880 LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)";
881 return;
882 }
883
884 auto fstab = ReadFirstStageFstabAndroid();
885 if (!fstab.ok()) {
886 LOG(ERROR) << fstab.error();
887 return;
888 }
889
890 if (!IsDtVbmetaCompatible(*fstab)) {
891 LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not vbmeta compatible)";
892 return;
893 }
894
895 // Initializes required devices for the subsequent AvbHandle::Open()
896 // to verify AVB metadata on all partitions in the verified chain.
897 // We only set INIT_AVB_VERSION when the AVB verification succeeds, i.e., the
898 // Open() function returns a valid handle.
899 // We don't need to mount partitions here in recovery mode.
900 FirstStageMountVBootV2 avb_first_mount(std::move(*fstab));
901 if (!avb_first_mount.InitDevices()) {
902 LOG(ERROR) << "Failed to init devices for INIT_AVB_VERSION";
903 return;
904 }
905
906 AvbUniquePtr avb_handle = AvbHandle::Open();
907 if (!avb_handle) {
908 PLOG(ERROR) << "Failed to open AvbHandle for INIT_AVB_VERSION";
909 return;
910 }
911 setenv("INIT_AVB_VERSION", avb_handle->avb_version().c_str(), 1);
912 }
913
914 } // namespace init
915 } // namespace android
916