• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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