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 if (!block_dev_init_.InitBootDevicesFromPartUuid()) {
284 return false;
285 }
286
287 std::set<std::string> devices;
288 GetSuperDeviceName(&devices);
289
290 if (!GetDmVerityDevices(&devices)) {
291 return false;
292 }
293 if (!InitRequiredDevices(std::move(devices))) {
294 return false;
295 }
296
297 if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
298 if (IsMicrodroidStrictBoot()) {
299 if (!block_dev_init_.InitPlatformDevice("open-dice0")) {
300 return false;
301 }
302 }
303 }
304
305 if (IsDmLinearEnabled()) {
306 auto super_symlink = "/dev/block/by-name/"s + super_partition_name_;
307 if (!android::base::Realpath(super_symlink, &super_path_)) {
308 PLOG(ERROR) << "realpath failed: " << super_symlink;
309 return false;
310 }
311 }
312 return true;
313 }
314
IsDmLinearEnabled()315 bool FirstStageMountVBootV2::IsDmLinearEnabled() {
316 for (const auto& entry : fstab_) {
317 if (entry.fs_mgr_flags.logical) return true;
318 }
319 return false;
320 }
321
GetSuperDeviceName(std::set<std::string> * devices)322 void FirstStageMountVBootV2::GetSuperDeviceName(std::set<std::string>* devices) {
323 // Add any additional devices required for dm-linear mappings.
324 if (!IsDmLinearEnabled()) {
325 return;
326 }
327
328 devices->emplace(super_partition_name_);
329 }
330
331 // Creates devices with uevent->partition_name matching ones in the given set.
332 // Found partitions will then be removed from it for the subsequent member
333 // function to check which devices are NOT created.
InitRequiredDevices(std::set<std::string> devices)334 bool FirstStageMountVBootV2::InitRequiredDevices(std::set<std::string> devices) {
335 if (!block_dev_init_.InitDeviceMapper()) {
336 return false;
337 }
338 if (devices.empty()) {
339 return true;
340 }
341 return block_dev_init_.InitDevices(std::move(devices));
342 }
343
InitDmLinearBackingDevices(const android::fs_mgr::LpMetadata & metadata)344 bool FirstStageMountVBootV2::InitDmLinearBackingDevices(
345 const android::fs_mgr::LpMetadata& metadata) {
346 std::set<std::string> devices;
347
348 auto partition_names = android::fs_mgr::GetBlockDevicePartitionNames(metadata);
349 for (const auto& partition_name : partition_names) {
350 // The super partition was found in the earlier pass.
351 if (partition_name == super_partition_name_) {
352 continue;
353 }
354 devices.emplace(partition_name);
355 }
356 if (devices.empty()) {
357 return true;
358 }
359 return InitRequiredDevices(std::move(devices));
360 }
361
CreateLogicalPartitions()362 bool FirstStageMountVBootV2::CreateLogicalPartitions() {
363 if (!IsDmLinearEnabled()) {
364 return true;
365 }
366 if (super_path_.empty()) {
367 LOG(ERROR) << "Could not locate logical partition tables in partition "
368 << super_partition_name_;
369 return false;
370 }
371
372 if (SnapshotManager::IsSnapshotManagerNeeded()) {
373 auto init_devices = [this](const std::string& device) -> bool {
374 if (android::base::StartsWith(device, "/dev/block/dm-")) {
375 return block_dev_init_.InitDmDevice(device);
376 }
377 return block_dev_init_.InitDevices({device});
378 };
379
380 SnapshotManager::MapTempOtaMetadataPartitionIfNeeded(init_devices);
381 auto sm = SnapshotManager::NewForFirstStageMount();
382 if (!sm) {
383 return false;
384 }
385 if (sm->NeedSnapshotsInFirstStageMount()) {
386 return CreateSnapshotPartitions(sm.get());
387 }
388 }
389
390 auto metadata = android::fs_mgr::ReadCurrentMetadata(super_path_);
391 if (!metadata) {
392 LOG(ERROR) << "Could not read logical partition metadata from " << super_path_;
393 return false;
394 }
395 if (!InitDmLinearBackingDevices(*metadata.get())) {
396 return false;
397 }
398 return android::fs_mgr::CreateLogicalPartitions(*metadata.get(), super_path_);
399 }
400
CreateSnapshotPartitions(SnapshotManager * sm)401 bool FirstStageMountVBootV2::CreateSnapshotPartitions(SnapshotManager* sm) {
402 // When COW images are present for snapshots, they are stored on
403 // the data partition.
404 if (!InitRequiredDevices({"userdata"})) {
405 return false;
406 }
407
408 use_snapuserd_ = sm->IsSnapuserdRequired();
409 if (use_snapuserd_) {
410 LaunchFirstStageSnapuserd();
411 }
412
413 sm->SetUeventRegenCallback([this](const std::string& device) -> bool {
414 if (android::base::StartsWith(device, "/dev/block/dm-")) {
415 return block_dev_init_.InitDmDevice(device);
416 }
417 if (android::base::StartsWith(device, "/dev/dm-user/")) {
418 return block_dev_init_.InitDmUser(android::base::Basename(device));
419 }
420 return block_dev_init_.InitDevices({device});
421 });
422 if (!sm->CreateLogicalAndSnapshotPartitions(super_path_)) {
423 return false;
424 }
425
426 if (use_snapuserd_) {
427 CleanupSnapuserdSocket();
428 }
429 return true;
430 }
431
MountPartition(const Fstab::iterator & begin,bool erase_same_mounts,Fstab::iterator * end)432 bool FirstStageMountVBootV2::MountPartition(const Fstab::iterator& begin, bool erase_same_mounts,
433 Fstab::iterator* end) {
434 // Sets end to begin + 1, so we can just return on failure below.
435 if (end) {
436 *end = begin + 1;
437 }
438
439 if (!fs_mgr_create_canonical_mount_point(begin->mount_point)) {
440 return false;
441 }
442
443 if (begin->fs_mgr_flags.logical) {
444 if (!fs_mgr_update_logical_partition(&(*begin))) {
445 return false;
446 }
447 if (!block_dev_init_.InitDmDevice(begin->blk_device)) {
448 return false;
449 }
450 }
451 if (!SetUpDmVerity(&(*begin))) {
452 PLOG(ERROR) << "Failed to setup verity for '" << begin->mount_point << "'";
453 return false;
454 }
455
456 bool mounted = (fs_mgr_do_mount_one(*begin) == 0);
457
458 // Try other mounts with the same mount point.
459 Fstab::iterator current = begin + 1;
460 for (; current != fstab_.end() && current->mount_point == begin->mount_point; current++) {
461 if (!mounted) {
462 // blk_device is already updated to /dev/dm-<N> by SetUpDmVerity() above.
463 // Copy it from the begin iterator.
464 current->blk_device = begin->blk_device;
465 mounted = (fs_mgr_do_mount_one(*current) == 0);
466 }
467 }
468 if (erase_same_mounts) {
469 current = fstab_.erase(begin, current);
470 }
471 if (end) {
472 *end = current;
473 }
474 return mounted;
475 }
476
PreloadAvbKeys()477 void FirstStageMountVBootV2::PreloadAvbKeys() {
478 for (const auto& entry : fstab_) {
479 // No need to cache the key content if it's empty, or is already cached.
480 if (entry.avb_keys.empty() || preload_avb_key_blobs_.count(entry.avb_keys)) {
481 continue;
482 }
483
484 // Determines all key paths first.
485 std::vector<std::string> key_paths;
486 if (is_dir(entry.avb_keys.c_str())) { // fstab_keys might be a dir, e.g., /avb.
487 const char* avb_key_dir = entry.avb_keys.c_str();
488 std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(avb_key_dir), closedir);
489 if (!dir) {
490 LOG(ERROR) << "Failed to opendir: " << dir;
491 continue;
492 }
493 // Gets all key pathes under the dir.
494 struct dirent* de;
495 while ((de = readdir(dir.get()))) {
496 if (de->d_type != DT_REG) continue;
497 std::string full_path = StringPrintf("%s/%s", avb_key_dir, de->d_name);
498 key_paths.emplace_back(std::move(full_path));
499 }
500 std::sort(key_paths.begin(), key_paths.end());
501 } else {
502 // avb_keys are key paths separated by ":", if it's not a dir.
503 key_paths = Split(entry.avb_keys, ":");
504 }
505
506 // Reads the key content then cache it.
507 std::vector<std::string> key_blobs;
508 for (const auto& path : key_paths) {
509 std::string key_value;
510 if (!ReadFileToString(path, &key_value)) {
511 continue;
512 }
513 key_blobs.emplace_back(std::move(key_value));
514 }
515
516 // Maps entry.avb_keys to actual key blobs.
517 preload_avb_key_blobs_[entry.avb_keys] = std::move(key_blobs);
518 }
519 }
520
521 // If system is in the fstab then we're not a system-as-root device, and in
522 // this case, we mount system first then pivot to it. From that point on,
523 // we are effectively identical to a system-as-root device.
TrySwitchSystemAsRoot()524 bool FirstStageMountVBootV2::TrySwitchSystemAsRoot() {
525 UseDsuIfPresent();
526 // Preloading all AVB keys from the ramdisk before switching root to /system.
527 PreloadAvbKeys();
528
529 auto system_partition = std::find_if(fstab_.begin(), fstab_.end(), [](const auto& entry) {
530 return entry.mount_point == "/system";
531 });
532
533 if (system_partition == fstab_.end()) return true;
534
535 if (use_snapuserd_) {
536 SaveRamdiskPathToSnapuserd();
537 }
538
539 if (!MountPartition(system_partition, false /* erase_same_mounts */)) {
540 PLOG(ERROR) << "Failed to mount /system";
541 return false;
542 }
543 if (dsu_not_on_userdata_ && fs_mgr_verity_is_check_at_most_once(*system_partition)) {
544 LOG(ERROR) << "check_at_most_once forbidden on external media";
545 return false;
546 }
547
548 SwitchRoot("/system");
549
550 return true;
551 }
552
MaybeDeriveMicrodroidVendorDiceNode(Fstab * fstab)553 static bool MaybeDeriveMicrodroidVendorDiceNode(Fstab* fstab) {
554 std::optional<std::string> microdroid_vendor_block_dev;
555 for (auto entry = fstab->begin(); entry != fstab->end(); entry++) {
556 if (entry->mount_point == "/vendor") {
557 microdroid_vendor_block_dev.emplace(entry->blk_device);
558 break;
559 }
560 }
561 if (!microdroid_vendor_block_dev.has_value()) {
562 LOG(VERBOSE) << "No microdroid vendor partition to mount";
563 return true;
564 }
565 // clang-format off
566 const std::array<const char*, 8> args = {
567 "/system/bin/derive_microdroid_vendor_dice_node",
568 "--dice-driver", "/dev/open-dice0",
569 "--microdroid-vendor-disk-image", microdroid_vendor_block_dev->data(),
570 "--output", "/microdroid_resources/dice_chain.raw", nullptr,
571 };
572 // clang-format-on
573 // ForkExecveAndWaitForCompletion calls waitpid to wait for the fork-ed process to finish.
574 // The first_stage_console adds SA_NOCLDWAIT flag to the SIGCHLD handler, which means that
575 // waitpid will always return -ECHLD. Here we re-register a default handler, so that waitpid
576 // works.
577 LOG(INFO) << "Deriving dice node for microdroid vendor partition";
578 signal(SIGCHLD, SIG_DFL);
579 if (!ForkExecveAndWaitForCompletion(args[0], (char**)args.data())) {
580 LOG(ERROR) << "Failed to derive microdroid vendor dice node";
581 return false;
582 }
583 return true;
584 }
585
MountPartitions()586 bool FirstStageMountVBootV2::MountPartitions() {
587 if (!TrySwitchSystemAsRoot()) return false;
588
589 if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
590 if (!MaybeDeriveMicrodroidVendorDiceNode(&fstab_)) {
591 return false;
592 }
593 }
594
595 if (!SkipMountingPartitions(&fstab_, true /* verbose */)) return false;
596
597 for (auto current = fstab_.begin(); current != fstab_.end();) {
598 // We've already mounted /system above.
599 if (current->mount_point == "/system") {
600 ++current;
601 continue;
602 }
603
604 // Handle overlayfs entries later.
605 if (current->fs_type == "overlay") {
606 ++current;
607 continue;
608 }
609
610 // Skip raw partition entries such as boot, dtbo, etc.
611 // Having emmc fstab entries allows us to probe current->vbmeta_partition
612 // in InitDevices() when they are AVB chained partitions.
613 if (current->fs_type == "emmc") {
614 ++current;
615 continue;
616 }
617
618 Fstab::iterator end;
619 if (!MountPartition(current, false /* erase_same_mounts */, &end)) {
620 if (current->fs_mgr_flags.no_fail) {
621 LOG(INFO) << "Failed to mount " << current->mount_point
622 << ", ignoring mount for no_fail partition";
623 } else if (current->fs_mgr_flags.formattable) {
624 LOG(INFO) << "Failed to mount " << current->mount_point
625 << ", ignoring mount for formattable partition";
626 } else {
627 PLOG(ERROR) << "Failed to mount " << current->mount_point;
628 return false;
629 }
630 }
631 current = end;
632 }
633
634 for (const auto& entry : fstab_) {
635 if (entry.fs_type == "overlay") {
636 fs_mgr_mount_overlayfs_fstab_entry(entry);
637 }
638 }
639
640 // If we don't see /system or / in the fstab, then we need to create an root entry for
641 // overlayfs.
642 if (!GetEntryForMountPoint(&fstab_, "/system") && !GetEntryForMountPoint(&fstab_, "/")) {
643 FstabEntry root_entry;
644 if (GetRootEntry(&root_entry)) {
645 fstab_.emplace_back(std::move(root_entry));
646 }
647 }
648
649 // heads up for instantiating required device(s) for overlayfs logic
650 auto init_devices = [this](std::set<std::string> devices) -> bool {
651 for (auto iter = devices.begin(); iter != devices.end();) {
652 if (android::base::StartsWith(*iter, "/dev/block/dm-")) {
653 if (!block_dev_init_.InitDmDevice(*iter)) {
654 return false;
655 }
656 iter = devices.erase(iter);
657 } else {
658 iter++;
659 }
660 }
661 return InitRequiredDevices(std::move(devices));
662 };
663 MapScratchPartitionIfNeeded(&fstab_, init_devices);
664
665 fs_mgr_overlayfs_mount_all(&fstab_);
666
667 return true;
668 }
669
670 // Preserves /avb/*.avbpubkey to /metadata/gsi/dsu/avb/, so they can be used for
671 // key revocation check by DSU installation service. Note that failing to
672 // copy files to /metadata is NOT fatal, because it is auxiliary to perform
673 // public key matching before booting into DSU images on next boot. The actual
674 // public key matching will still be done on next boot to DSU.
CopyDsuAvbKeys()675 void FirstStageMountVBootV2::CopyDsuAvbKeys() {
676 std::error_code ec;
677 // Removing existing keys in gsi::kDsuAvbKeyDir as they might be stale.
678 std::filesystem::remove_all(gsi::kDsuAvbKeyDir, ec);
679 if (ec) {
680 LOG(ERROR) << "Failed to remove directory " << gsi::kDsuAvbKeyDir << ": " << ec.message();
681 }
682 // Copy keys from the ramdisk /avb/* to gsi::kDsuAvbKeyDir.
683 static constexpr char kRamdiskAvbKeyDir[] = "/avb";
684 std::filesystem::copy(kRamdiskAvbKeyDir, gsi::kDsuAvbKeyDir, ec);
685 if (ec) {
686 LOG(ERROR) << "Failed to copy " << kRamdiskAvbKeyDir << " into " << gsi::kDsuAvbKeyDir
687 << ": " << ec.message();
688 }
689 }
690
UseDsuIfPresent()691 void FirstStageMountVBootV2::UseDsuIfPresent() {
692 std::string error;
693
694 if (!android::gsi::CanBootIntoGsi(&error)) {
695 LOG(INFO) << "DSU " << error << ", proceeding with normal boot";
696 return;
697 }
698
699 auto init_devices = [this](std::set<std::string> devices) -> bool {
700 if (devices.count("userdata") == 0 || devices.size() > 1) {
701 dsu_not_on_userdata_ = true;
702 }
703 return InitRequiredDevices(std::move(devices));
704 };
705 std::string active_dsu;
706 if (!gsi::GetActiveDsu(&active_dsu)) {
707 LOG(ERROR) << "Failed to GetActiveDsu";
708 return;
709 }
710 LOG(INFO) << "DSU slot: " << active_dsu;
711 auto images = IImageManager::Open("dsu/" + active_dsu, 0ms);
712 if (!images || !images->MapAllImages(init_devices)) {
713 LOG(ERROR) << "DSU partition layout could not be instantiated";
714 return;
715 }
716
717 if (!android::gsi::MarkSystemAsGsi()) {
718 PLOG(ERROR) << "DSU indicator file could not be written";
719 return;
720 }
721
722 // Publish the logical partition names for TransformFstabForDsu() and ReadFstabFromFile().
723 const auto dsu_partitions = images->GetAllBackingImages();
724 WriteFile(gsi::kGsiLpNamesFile, android::base::Join(dsu_partitions, ","));
725 TransformFstabForDsu(&fstab_, active_dsu, dsu_partitions);
726 }
727
FirstStageMountVBootV2(Fstab fstab)728 FirstStageMountVBootV2::FirstStageMountVBootV2(Fstab fstab)
729 : need_dm_verity_(false), fstab_(std::move(fstab)), avb_handle_(nullptr) {
730 super_partition_name_ = fs_mgr_get_super_partition_name();
731
732 std::string device_tree_vbmeta_parts;
733 read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts);
734
735 for (auto&& partition : Split(device_tree_vbmeta_parts, ",")) {
736 if (!partition.empty()) {
737 vbmeta_partitions_.emplace_back(std::move(partition));
738 }
739 }
740
741 for (const auto& entry : fstab_) {
742 if (!entry.vbmeta_partition.empty()) {
743 vbmeta_partitions_.emplace_back(entry.vbmeta_partition);
744 }
745 }
746
747 if (vbmeta_partitions_.empty()) {
748 LOG(ERROR) << "Failed to read vbmeta partitions.";
749 }
750 }
751
GetDmVerityDevices(std::set<std::string> * devices)752 bool FirstStageMountVBootV2::GetDmVerityDevices(std::set<std::string>* devices) {
753 need_dm_verity_ = false;
754
755 std::set<std::string> logical_partitions;
756
757 // fstab_rec->blk_device has A/B suffix.
758 for (const auto& fstab_entry : fstab_) {
759 if (fstab_entry.fs_mgr_flags.avb) {
760 need_dm_verity_ = true;
761 }
762 // Skip pseudo filesystems.
763 if (fstab_entry.fs_type == "overlay") {
764 continue;
765 }
766 if (fstab_entry.fs_mgr_flags.logical) {
767 // Don't try to find logical partitions via uevent regeneration.
768 logical_partitions.emplace(basename(fstab_entry.blk_device.c_str()));
769 } else {
770 devices->emplace(basename(fstab_entry.blk_device.c_str()));
771 }
772 }
773
774 // Any partitions needed for verifying the partitions used in first stage mount, e.g. vbmeta
775 // must be provided as vbmeta_partitions.
776 if (need_dm_verity_) {
777 if (vbmeta_partitions_.empty()) {
778 LOG(ERROR) << "Missing vbmeta partitions";
779 return false;
780 }
781 std::string ab_suffix = fs_mgr_get_slot_suffix();
782 for (const auto& partition : vbmeta_partitions_) {
783 std::string partition_name = partition + ab_suffix;
784 if (logical_partitions.count(partition_name)) {
785 continue;
786 }
787 // devices is of type std::set so it's not an issue to emplace a
788 // partition twice. e.g., /vendor might be in both places:
789 // - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
790 // - mount_fstab_recs_: /vendor_a
791 devices->emplace(partition_name);
792 }
793 }
794 return true;
795 }
796
IsHashtreeDisabled(const AvbHandle & vbmeta,const std::string & mount_point)797 bool IsHashtreeDisabled(const AvbHandle& vbmeta, const std::string& mount_point) {
798 if (vbmeta.status() == AvbHandleStatus::kHashtreeDisabled ||
799 vbmeta.status() == AvbHandleStatus::kVerificationDisabled) {
800 LOG(ERROR) << "Top-level vbmeta is disabled, skip Hashtree setup for " << mount_point;
801 return true; // Returns true to mount the partition directly.
802 }
803 return false;
804 }
805
SetUpDmVerity(FstabEntry * fstab_entry)806 bool FirstStageMountVBootV2::SetUpDmVerity(FstabEntry* fstab_entry) {
807 AvbHashtreeResult hashtree_result;
808
809 // It's possible for a fstab_entry to have both avb_keys and avb flag.
810 // In this case, try avb_keys first, then fallback to avb flag.
811 if (!fstab_entry->avb_keys.empty()) {
812 if (!InitAvbHandle()) return false;
813 // Checks if hashtree should be disabled from the top-level /vbmeta.
814 if (IsHashtreeDisabled(*avb_handle_, fstab_entry->mount_point)) {
815 return true;
816 }
817 auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(
818 *fstab_entry, preload_avb_key_blobs_[fstab_entry->avb_keys]);
819 if (!avb_standalone_handle) {
820 LOG(ERROR) << "Failed to load offline vbmeta for " << fstab_entry->mount_point;
821 // Fallbacks to built-in hashtree if fs_mgr_flags.avb is set.
822 if (!fstab_entry->fs_mgr_flags.avb) return false;
823 LOG(INFO) << "Fallback to built-in hashtree for " << fstab_entry->mount_point;
824 hashtree_result =
825 avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */);
826 } else {
827 // Sets up hashtree via the standalone handle.
828 if (IsStandaloneImageRollback(*avb_handle_, *avb_standalone_handle, *fstab_entry)) {
829 return false;
830 }
831 hashtree_result = avb_standalone_handle->SetUpAvbHashtree(
832 fstab_entry, false /* wait_for_verity_dev */);
833 }
834 } else if (fstab_entry->fs_mgr_flags.avb) {
835 if (!InitAvbHandle()) return false;
836 hashtree_result =
837 avb_handle_->SetUpAvbHashtree(fstab_entry, false /* wait_for_verity_dev */);
838 } else if (!fstab_entry->avb_hashtree_digest.empty()) {
839 // When fstab_entry has neither avb_keys nor avb flag, try using
840 // avb_hashtree_digest.
841 if (!InitAvbHandle()) return false;
842 // Checks if hashtree should be disabled from the top-level /vbmeta.
843 if (IsHashtreeDisabled(*avb_handle_, fstab_entry->mount_point)) {
844 return true;
845 }
846 auto avb_standalone_handle = AvbHandle::LoadAndVerifyVbmeta(*fstab_entry);
847 if (!avb_standalone_handle) {
848 LOG(ERROR) << "Failed to load vbmeta based on hashtree descriptor root digest for "
849 << fstab_entry->mount_point;
850 return false;
851 }
852 hashtree_result = avb_standalone_handle->SetUpAvbHashtree(fstab_entry,
853 false /* wait_for_verity_dev */);
854 } else {
855 return true; // No need AVB, returns true to mount the partition directly.
856 }
857
858 switch (hashtree_result) {
859 case AvbHashtreeResult::kDisabled:
860 return true; // Returns true to mount the partition.
861 case AvbHashtreeResult::kSuccess:
862 // The exact block device name (fstab_rec->blk_device) is changed to
863 // "/dev/block/dm-XX". Needs to create it because ueventd isn't started in init
864 // first stage.
865 return block_dev_init_.InitDmDevice(fstab_entry->blk_device);
866 default:
867 return false;
868 }
869 }
870
InitAvbHandle()871 bool FirstStageMountVBootV2::InitAvbHandle() {
872 if (avb_handle_) return true; // Returns true if the handle is already initialized.
873
874 avb_handle_ = AvbHandle::Open();
875
876 if (!avb_handle_) {
877 PLOG(ERROR) << "Failed to open AvbHandle";
878 return false;
879 }
880 // Sets INIT_AVB_VERSION here for init to set ro.boot.avb_version in the second stage.
881 setenv("INIT_AVB_VERSION", avb_handle_->avb_version().c_str(), 1);
882 return true;
883 }
884
SetInitAvbVersionInRecovery()885 void SetInitAvbVersionInRecovery() {
886 if (!IsRecoveryMode()) {
887 LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)";
888 return;
889 }
890
891 auto fstab = ReadFirstStageFstabAndroid();
892 if (!fstab.ok()) {
893 LOG(ERROR) << fstab.error();
894 return;
895 }
896
897 if (!IsDtVbmetaCompatible(*fstab)) {
898 LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not vbmeta compatible)";
899 return;
900 }
901
902 // Initializes required devices for the subsequent AvbHandle::Open()
903 // to verify AVB metadata on all partitions in the verified chain.
904 // We only set INIT_AVB_VERSION when the AVB verification succeeds, i.e., the
905 // Open() function returns a valid handle.
906 // We don't need to mount partitions here in recovery mode.
907 FirstStageMountVBootV2 avb_first_mount(std::move(*fstab));
908 if (!avb_first_mount.InitDevices()) {
909 LOG(ERROR) << "Failed to init devices for INIT_AVB_VERSION";
910 return;
911 }
912
913 AvbUniquePtr avb_handle = AvbHandle::Open();
914 if (!avb_handle) {
915 PLOG(ERROR) << "Failed to open AvbHandle for INIT_AVB_VERSION";
916 return;
917 }
918 setenv("INIT_AVB_VERSION", avb_handle->avb_version().c_str(), 1);
919 }
920
921 } // namespace init
922 } // namespace android
923