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