• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <libsnapshot/snapshot.h>
16 
17 #include <dirent.h>
18 #include <fcntl.h>
19 #include <math.h>
20 #include <sys/file.h>
21 #include <sys/types.h>
22 #include <sys/unistd.h>
23 #include <sys/xattr.h>
24 
25 #include <chrono>
26 #include <filesystem>
27 #include <optional>
28 #include <thread>
29 
30 #include <android-base/file.h>
31 #include <android-base/logging.h>
32 #include <android-base/parseint.h>
33 #include <android-base/properties.h>
34 #include <android-base/stringprintf.h>
35 #include <android-base/strings.h>
36 #include <android-base/unique_fd.h>
37 #include <cutils/sockets.h>
38 #include <ext4_utils/ext4_utils.h>
39 #include <fs_mgr.h>
40 #include <fs_mgr/file_wait.h>
41 #include <fs_mgr_dm_linear.h>
42 #include <fstab/fstab.h>
43 #include <libdm/dm.h>
44 #include <libfiemap/image_manager.h>
45 #include <liblp/liblp.h>
46 
47 #include <android/snapshot/snapshot.pb.h>
48 #include <libsnapshot/snapshot_stats.h>
49 #include "device_info.h"
50 #include "partition_cow_creator.h"
51 #include "scratch_super.h"
52 #include "snapshot_metadata_updater.h"
53 #include "utility.h"
54 
55 namespace android {
56 namespace snapshot {
57 
58 using aidl::android::hardware::boot::MergeStatus;
59 using android::base::unique_fd;
60 using android::dm::DeviceMapper;
61 using android::dm::DmDeviceState;
62 using android::dm::DmTable;
63 using android::dm::DmTargetLinear;
64 using android::dm::DmTargetSnapshot;
65 using android::dm::DmTargetUser;
66 using android::dm::kSectorSize;
67 using android::dm::SnapshotStorageMode;
68 using android::fiemap::FiemapStatus;
69 using android::fiemap::IImageManager;
70 using android::fs_mgr::CreateDmTable;
71 using android::fs_mgr::CreateLogicalPartition;
72 using android::fs_mgr::CreateLogicalPartitionParams;
73 using android::fs_mgr::GetPartitionGroupName;
74 using android::fs_mgr::GetPartitionName;
75 using android::fs_mgr::LpMetadata;
76 using android::fs_mgr::MetadataBuilder;
77 using android::fs_mgr::SlotNumberForSlotSuffix;
78 using chromeos_update_engine::DeltaArchiveManifest;
79 using chromeos_update_engine::Extent;
80 using chromeos_update_engine::FileDescriptor;
81 using chromeos_update_engine::PartitionUpdate;
82 template <typename T>
83 using RepeatedPtrField = google::protobuf::RepeatedPtrField<T>;
84 using std::chrono::duration_cast;
85 using namespace std::chrono_literals;
86 using namespace std::string_literals;
87 using android::base::Realpath;
88 using android::base::StringPrintf;
89 
90 static constexpr char kBootSnapshotsWithoutSlotSwitch[] =
91         "/metadata/ota/snapshot-boot-without-slot-switch";
92 static constexpr char kBootIndicatorPath[] = "/metadata/ota/snapshot-boot";
93 static constexpr char kRollbackIndicatorPath[] = "/metadata/ota/rollback-indicator";
94 static constexpr char kSnapuserdFromSystem[] = "/metadata/ota/snapuserd-from-system";
95 static constexpr auto kUpdateStateCheckInterval = 2s;
96 static constexpr char kOtaFileContext[] = "u:object_r:ota_metadata_file:s0";
97 
98 /*
99  * The readahead size is set to 32kb so that
100  * there is no significant memory pressure (/proc/pressure/memory) during boot.
101  * After OTA, during boot, partitions are scanned before marking slot as successful.
102  * This scan will trigger readahead both on source and COW block device thereby
103  * leading to Inactive(file) pages to be very high.
104  *
105  * A lower value may help reduce memory pressure further, however, that will
106  * increase the boot time. Thus, for device which don't care about OTA boot
107  * time, they could use O_DIRECT functionality wherein the I/O to the source
108  * block device will be O_DIRECT.
109  */
110 static constexpr auto kReadAheadSizeKb = 32;
111 
112 // Note: IImageManager is an incomplete type in the header, so the default
113 // destructor doesn't work.
~SnapshotManager()114 SnapshotManager::~SnapshotManager() {}
115 
New(IDeviceInfo * info)116 std::unique_ptr<SnapshotManager> SnapshotManager::New(IDeviceInfo* info) {
117     if (!info) {
118         info = new DeviceInfo();
119     }
120 
121     auto sm = std::unique_ptr<SnapshotManager>(new SnapshotManager(info));
122     if (info->IsTempMetadata()) {
123         LOG(INFO) << "Using temp metadata from super";
124     }
125     return sm;
126 }
127 
NewForFirstStageMount(IDeviceInfo * info)128 std::unique_ptr<SnapshotManager> SnapshotManager::NewForFirstStageMount(IDeviceInfo* info) {
129     if (!info) {
130         DeviceInfo* impl = new DeviceInfo();
131         impl->set_first_stage_init(true);
132         info = impl;
133     }
134     auto sm = New(info);
135 
136     // The first-stage version of snapuserd is explicitly started by init. Do
137     // not attempt to using it during tests (which run in normal AOSP).
138     if (!sm->device()->IsTestDevice()) {
139         sm->use_first_stage_snapuserd_ = true;
140     }
141     return sm;
142 }
143 
SnapshotManager(IDeviceInfo * device)144 SnapshotManager::SnapshotManager(IDeviceInfo* device)
145     : dm_(device->GetDeviceMapper()), device_(device), metadata_dir_(device_->GetMetadataDir()) {}
146 
GetCowName(const std::string & snapshot_name)147 static std::string GetCowName(const std::string& snapshot_name) {
148     return snapshot_name + "-cow";
149 }
150 
GetSnapshotDriver(LockedFile * lock)151 SnapshotManager::SnapshotDriver SnapshotManager::GetSnapshotDriver(LockedFile* lock) {
152     if (UpdateUsesUserSnapshots(lock)) {
153         return SnapshotManager::SnapshotDriver::DM_USER;
154     } else {
155         return SnapshotManager::SnapshotDriver::DM_SNAPSHOT;
156     }
157 }
158 
GetDmUserCowName(const std::string & snapshot_name,SnapshotManager::SnapshotDriver driver)159 static std::string GetDmUserCowName(const std::string& snapshot_name,
160                                     SnapshotManager::SnapshotDriver driver) {
161     // dm-user block device will act as a snapshot device. We identify it with
162     // the same partition name so that when partitions can be mounted off
163     // dm-user.
164 
165     switch (driver) {
166         case SnapshotManager::SnapshotDriver::DM_USER: {
167             return snapshot_name;
168         }
169 
170         case SnapshotManager::SnapshotDriver::DM_SNAPSHOT: {
171             return snapshot_name + "-user-cow";
172         }
173 
174         default: {
175             LOG(ERROR) << "Invalid snapshot driver";
176             return "";
177         }
178     }
179 }
180 
GetCowImageDeviceName(const std::string & snapshot_name)181 static std::string GetCowImageDeviceName(const std::string& snapshot_name) {
182     return snapshot_name + "-cow-img";
183 }
184 
GetBaseDeviceName(const std::string & partition_name)185 static std::string GetBaseDeviceName(const std::string& partition_name) {
186     return partition_name + "-base";
187 }
188 
GetSourceDeviceName(const std::string & partition_name)189 static std::string GetSourceDeviceName(const std::string& partition_name) {
190     return partition_name + "-src";
191 }
192 
BeginUpdate()193 bool SnapshotManager::BeginUpdate() {
194     switch (TryCancelUpdate()) {
195         case CancelResult::OK:
196             break;
197         case CancelResult::NEEDS_MERGE: {
198             LOG(INFO) << "Wait for merge (if any) before beginning a new update.";
199             auto state = ProcessUpdateState();
200             LOG(INFO) << "Merged with end state: " << state;
201             break;
202         }
203         default:
204             LOG(ERROR) << "Cannot begin update, existing update cannot be cancelled.";
205             return false;
206     }
207 
208     auto file = LockExclusive();
209     if (!file) return false;
210 
211     // Purge the ImageManager just in case there is a corrupt lp_metadata file
212     // lying around. (NB: no need to return false on an error, we can let the
213     // update try to progress.)
214     if (EnsureImageManager()) {
215         images_->RemoveAllImages();
216     }
217 
218     // Clear any cached metadata (this allows re-using one manager across tests).
219     old_partition_metadata_ = nullptr;
220 
221     auto state = ReadUpdateState(file.get());
222     if (state != UpdateState::None) {
223         LOG(ERROR) << "An update is already in progress, cannot begin a new update";
224         return false;
225     }
226     return WriteUpdateState(file.get(), UpdateState::Initiated);
227 }
228 
CancelUpdate()229 bool SnapshotManager::CancelUpdate() {
230     return TryCancelUpdate() == CancelResult::OK;
231 }
232 
TryCancelUpdate()233 CancelResult SnapshotManager::TryCancelUpdate() {
234     auto lock = LockExclusive();
235     if (!lock) return CancelResult::ERROR;
236 
237     UpdateState state = ReadUpdateState(lock.get());
238     CancelResult result = IsCancelUpdateSafe(state);
239 
240     if (result != CancelResult::OK && device_->IsRecovery()) {
241         LOG(ERROR) << "Cancel result " << result << " will be overridden in recovery.";
242         result = CancelResult::OK;
243     }
244 
245     switch (result) {
246         case CancelResult::OK:
247             LOG(INFO) << "Cancelling update from state: " << state;
248             RemoveAllUpdateState(lock.get());
249             RemoveInvalidSnapshots(lock.get());
250             break;
251         case CancelResult::NEEDS_MERGE:
252             LOG(ERROR) << "Cannot cancel an update while a merge is in progress.";
253             break;
254         case CancelResult::LIVE_SNAPSHOTS:
255             LOG(ERROR) << "Cannot cancel an update while snapshots are live.";
256             break;
257         case CancelResult::ERROR:
258             // Error was already reported.
259             break;
260     }
261     return result;
262 }
263 
IsCancelUpdateSafe()264 bool SnapshotManager::IsCancelUpdateSafe() {
265     // This may be called in recovery, so ensure we have /metadata.
266     auto mount = EnsureMetadataMounted();
267     if (!mount || !mount->HasDevice()) {
268         return true;
269     }
270 
271     auto lock = LockExclusive();
272     if (!lock) {
273         return false;
274     }
275 
276     UpdateState state = ReadUpdateState(lock.get());
277     return IsCancelUpdateSafe(state) == CancelResult::OK;
278 }
279 
IsCancelUpdateSafe(UpdateState state)280 CancelResult SnapshotManager::IsCancelUpdateSafe(UpdateState state) {
281     if (IsSnapshotWithoutSlotSwitch()) {
282         return CancelResult::LIVE_SNAPSHOTS;
283     }
284 
285     switch (state) {
286         case UpdateState::Merging:
287         case UpdateState::MergeNeedsReboot:
288         case UpdateState::MergeFailed:
289             return CancelResult::NEEDS_MERGE;
290         case UpdateState::Unverified: {
291             // We completed an update, but it can still be canceled if we haven't booted into it.
292             auto slot = GetCurrentSlot();
293             if (slot == Slot::Target) {
294                 return CancelResult::LIVE_SNAPSHOTS;
295             }
296             return CancelResult::OK;
297         }
298         case UpdateState::None:
299         case UpdateState::Initiated:
300         case UpdateState::Cancelled:
301             return CancelResult::OK;
302         default:
303             LOG(ERROR) << "Unknown state: " << state;
304             return CancelResult::ERROR;
305     }
306 }
307 
ReadUpdateSourceSlotSuffix()308 std::string SnapshotManager::ReadUpdateSourceSlotSuffix() {
309     auto boot_file = GetSnapshotBootIndicatorPath();
310     std::string contents;
311     if (!android::base::ReadFileToString(boot_file, &contents)) {
312         return {};
313     }
314     return contents;
315 }
316 
GetCurrentSlot()317 SnapshotManager::Slot SnapshotManager::GetCurrentSlot() {
318     auto contents = ReadUpdateSourceSlotSuffix();
319     if (contents.empty()) {
320         return Slot::Unknown;
321     }
322     if (device_->GetSlotSuffix() == contents) {
323         return Slot::Source;
324     }
325     return Slot::Target;
326 }
327 
GetSnapshotSlotSuffix()328 std::string SnapshotManager::GetSnapshotSlotSuffix() {
329     switch (GetCurrentSlot()) {
330         case Slot::Target:
331             return device_->GetSlotSuffix();
332         default:
333             return device_->GetOtherSlotSuffix();
334     }
335 }
336 
RemoveFileIfExists(const std::string & path)337 static bool RemoveFileIfExists(const std::string& path) {
338     std::string message;
339     if (!android::base::RemoveFileIfExists(path, &message)) {
340         LOG(ERROR) << "Remove failed: " << path << ": " << message;
341         return false;
342     }
343     return true;
344 }
345 
RemoveAllUpdateState(LockedFile * lock,const std::function<bool ()> & prolog)346 bool SnapshotManager::RemoveAllUpdateState(LockedFile* lock, const std::function<bool()>& prolog) {
347     if (prolog && !prolog()) {
348         LOG(WARNING) << "Can't RemoveAllUpdateState: prolog failed.";
349         return false;
350     }
351 
352     LOG(INFO) << "Removing all update state.";
353 
354     if (ReadUpdateState(lock) != UpdateState::None) {
355         // Only call this if we're actually cancelling an update. It's not
356         // expected to yield anything otherwise, and firing up gsid on normal
357         // boot is expensive.
358         if (!RemoveAllSnapshots(lock)) {
359             LOG(ERROR) << "Could not remove all snapshots";
360             return false;
361         }
362     }
363 
364     // It's okay if these fail:
365     // - For SnapshotBoot and Rollback, first-stage init performs a deeper check after
366     // reading the indicator file, so it's not a problem if it still exists
367     // after the update completes.
368     // - For ForwardMerge, FinishedSnapshotWrites asserts that the existence of the indicator
369     // matches the incoming update.
370     std::vector<std::string> files = {
371             GetSnapshotBootIndicatorPath(),          GetRollbackIndicatorPath(),
372             GetForwardMergeIndicatorPath(),          GetOldPartitionMetadataPath(),
373             GetBootSnapshotsWithoutSlotSwitchPath(), GetSnapuserdFromSystemPath(),
374     };
375     for (const auto& file : files) {
376         RemoveFileIfExists(file);
377     }
378 
379     // If this fails, we'll keep trying to remove the update state (as the
380     // device reboots or starts a new update) until it finally succeeds.
381     return WriteUpdateState(lock, UpdateState::None);
382 }
383 
FinishedSnapshotWrites(bool wipe)384 bool SnapshotManager::FinishedSnapshotWrites(bool wipe) {
385     auto lock = LockExclusive();
386     if (!lock) return false;
387 
388     auto update_state = ReadUpdateState(lock.get());
389     if (update_state == UpdateState::Unverified) {
390         LOG(INFO) << "FinishedSnapshotWrites already called before. Ignored.";
391         return true;
392     }
393 
394     if (update_state != UpdateState::Initiated) {
395         LOG(ERROR) << "Can only transition to the Unverified state from the Initiated state.";
396         return false;
397     }
398 
399     if (!EnsureNoOverflowSnapshot(lock.get())) {
400         LOG(ERROR) << "Cannot ensure there are no overflow snapshots.";
401         return false;
402     }
403 
404     if (!UpdateForwardMergeIndicator(wipe)) {
405         return false;
406     }
407 
408     // This file is written on boot to detect whether a rollback occurred. It
409     // MUST NOT exist before rebooting, otherwise, we're at risk of deleting
410     // snapshots too early.
411     if (!RemoveFileIfExists(GetRollbackIndicatorPath())) {
412         return false;
413     }
414 
415     // This file acts as both a quick indicator for init (it can use access(2)
416     // to decide how to do first-stage mounts), and it stores the old slot, so
417     // we can tell whether or not we performed a rollback.
418     auto contents = device_->GetSlotSuffix();
419     auto boot_file = GetSnapshotBootIndicatorPath();
420     if (!WriteStringToFileAtomic(contents, boot_file)) {
421         PLOG(ERROR) << "write failed: " << boot_file;
422         return false;
423     }
424     return WriteUpdateState(lock.get(), UpdateState::Unverified);
425 }
426 
CreateSnapshot(LockedFile * lock,PartitionCowCreator * cow_creator,SnapshotStatus * status)427 bool SnapshotManager::CreateSnapshot(LockedFile* lock, PartitionCowCreator* cow_creator,
428                                      SnapshotStatus* status) {
429     CHECK(lock);
430     CHECK(lock->lock_mode() == LOCK_EX);
431     CHECK(status);
432 
433     if (status->name().empty()) {
434         LOG(ERROR) << "SnapshotStatus has no name.";
435         return false;
436     }
437     // Check these sizes. Like liblp, we guarantee the partition size is
438     // respected, which means it has to be sector-aligned. (This guarantee is
439     // useful for locating avb footers correctly). The COW file size, however,
440     // can be arbitrarily larger than specified, so we can safely round it up.
441     if (status->device_size() % kSectorSize != 0) {
442         LOG(ERROR) << "Snapshot " << status->name()
443                    << " device size is not a multiple of the sector size: "
444                    << status->device_size();
445         return false;
446     }
447     if (status->snapshot_size() % kSectorSize != 0) {
448         LOG(ERROR) << "Snapshot " << status->name()
449                    << " snapshot size is not a multiple of the sector size: "
450                    << status->snapshot_size();
451         return false;
452     }
453     if (status->cow_partition_size() % kSectorSize != 0) {
454         LOG(ERROR) << "Snapshot " << status->name()
455                    << " cow partition size is not a multiple of the sector size: "
456                    << status->cow_partition_size();
457         return false;
458     }
459     if (status->cow_file_size() % kSectorSize != 0) {
460         LOG(ERROR) << "Snapshot " << status->name()
461                    << " cow file size is not a multiple of the sector size: "
462                    << status->cow_file_size();
463         return false;
464     }
465 
466     status->set_state(SnapshotState::CREATED);
467     status->set_sectors_allocated(0);
468     status->set_metadata_sectors(0);
469     status->set_using_snapuserd(cow_creator->using_snapuserd);
470     status->set_compression_algorithm(cow_creator->compression_algorithm);
471     status->set_compression_factor(cow_creator->compression_factor);
472     status->set_read_ahead_size(cow_creator->read_ahead_size);
473     if (cow_creator->enable_threading) {
474         status->set_enable_threading(cow_creator->enable_threading);
475     }
476     if (cow_creator->batched_writes) {
477         status->set_batched_writes(cow_creator->batched_writes);
478     }
479 
480     if (!WriteSnapshotStatus(lock, *status)) {
481         PLOG(ERROR) << "Could not write snapshot status: " << status->name();
482         return false;
483     }
484     return true;
485 }
486 
CreateCowImage(LockedFile * lock,const std::string & name)487 Return SnapshotManager::CreateCowImage(LockedFile* lock, const std::string& name) {
488     CHECK(lock);
489     CHECK(lock->lock_mode() == LOCK_EX);
490     if (!EnsureImageManager()) return Return::Error();
491 
492     SnapshotStatus status;
493     if (!ReadSnapshotStatus(lock, name, &status)) {
494         return Return::Error();
495     }
496 
497     // The COW file size should have been rounded up to the nearest sector in CreateSnapshot.
498     if (status.cow_file_size() % kSectorSize != 0) {
499         LOG(ERROR) << "Snapshot " << name << " COW file size is not a multiple of the sector size: "
500                    << status.cow_file_size();
501         return Return::Error();
502     }
503 
504     std::string cow_image_name = GetCowImageDeviceName(name);
505     int cow_flags = IImageManager::CREATE_IMAGE_DEFAULT;
506     return Return(images_->CreateBackingImage(cow_image_name, status.cow_file_size(), cow_flags));
507 }
508 
MapDmUserCow(LockedFile * lock,const std::string & name,const std::string & cow_file,const std::string & base_device,const std::string & base_path_merge,const std::chrono::milliseconds & timeout_ms,std::string * path)509 bool SnapshotManager::MapDmUserCow(LockedFile* lock, const std::string& name,
510                                    const std::string& cow_file, const std::string& base_device,
511                                    const std::string& base_path_merge,
512                                    const std::chrono::milliseconds& timeout_ms, std::string* path) {
513     CHECK(lock);
514 
515     if (UpdateUsesUserSnapshots(lock)) {
516         SnapshotStatus status;
517         if (!ReadSnapshotStatus(lock, name, &status)) {
518             LOG(ERROR) << "MapDmUserCow: ReadSnapshotStatus failed...";
519             return false;
520         }
521 
522         if (status.state() == SnapshotState::NONE ||
523             status.state() == SnapshotState::MERGE_COMPLETED) {
524             LOG(ERROR) << "Should not create a snapshot device for " << name
525                        << " after merging has completed.";
526             return false;
527         }
528 
529         SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
530         if (update_status.state() == UpdateState::MergeCompleted ||
531             update_status.state() == UpdateState::MergeNeedsReboot) {
532             LOG(ERROR) << "Should not create a snapshot device for " << name
533                        << " after global merging has completed.";
534             return false;
535         }
536     }
537 
538     // Use an extra decoration for first-stage init, so we can transition
539     // to a new table entry in second-stage.
540     std::string misc_name = name;
541     if (use_first_stage_snapuserd_) {
542         misc_name += "-init";
543     }
544 
545     if (!EnsureSnapuserdConnected()) {
546         return false;
547     }
548 
549     uint64_t base_sectors = 0;
550     if (!UpdateUsesUserSnapshots(lock)) {
551         base_sectors = snapuserd_client_->InitDmUserCow(misc_name, cow_file, base_device);
552         if (base_sectors == 0) {
553             LOG(ERROR) << "Failed to retrieve base_sectors from Snapuserd";
554             return false;
555         }
556     } else if (IsSnapshotWithoutSlotSwitch()) {
557         // When snapshots are on current slot, we determine the size
558         // of block device based on the number of COW operations. We cannot
559         // use base device as it will be from older image.
560         unique_fd fd(open(cow_file.c_str(), O_RDONLY | O_CLOEXEC));
561         if (fd < 0) {
562             PLOG(ERROR) << "Failed to open " << cow_file;
563             return false;
564         }
565 
566         CowReader reader;
567         if (!reader.Parse(std::move(fd))) {
568             LOG(ERROR) << "Failed to parse cow " << cow_file;
569             return false;
570         }
571 
572         uint64_t dev_sz = 0;
573         const auto& header = reader.GetHeader();
574         if (header.prefix.major_version == 2) {
575             const size_t num_ops = reader.get_num_total_data_ops();
576             dev_sz = (num_ops * header.block_size);
577         } else {
578             // create_snapshot will skip in-place copy ops. Hence, fetch this
579             // information directly from v3 header.
580             const auto& v3_header = reader.header_v3();
581             dev_sz = v3_header.op_count_max * v3_header.block_size;
582         }
583 
584         base_sectors = dev_sz >> 9;
585     } else {
586         // For userspace snapshots, the size of the base device is taken as the
587         // size of the dm-user block device. Since there is no pseudo mapping
588         // created in the daemon, we no longer need to rely on the daemon for
589         // sizing the dm-user block device.
590         unique_fd fd(TEMP_FAILURE_RETRY(open(base_path_merge.c_str(), O_RDONLY | O_CLOEXEC)));
591         if (fd < 0) {
592             LOG(ERROR) << "Cannot open block device: " << base_path_merge;
593             return false;
594         }
595 
596         uint64_t dev_sz = get_block_device_size(fd.get());
597         if (!dev_sz) {
598             LOG(ERROR) << "Failed to find block device size: " << base_path_merge;
599             return false;
600         }
601 
602         base_sectors = dev_sz >> 9;
603     }
604 
605     DmTable table;
606     table.Emplace<DmTargetUser>(0, base_sectors, misc_name);
607     if (!dm_.CreateDevice(name, table, path, timeout_ms)) {
608         LOG(ERROR) << " dm-user: CreateDevice failed... ";
609         return false;
610     }
611     if (!WaitForDevice(*path, timeout_ms)) {
612         LOG(ERROR) << " dm-user: timeout: Failed to create block device for: " << name;
613         return false;
614     }
615 
616     auto control_device = "/dev/dm-user/" + misc_name;
617     if (!WaitForDevice(control_device, timeout_ms)) {
618         return false;
619     }
620 
621     if (UpdateUsesUserSnapshots(lock)) {
622         // Now that the dm-user device is created, initialize the daemon and
623         // spin up the worker threads.
624         if (!snapuserd_client_->InitDmUserCow(misc_name, cow_file, base_device, base_path_merge)) {
625             LOG(ERROR) << "InitDmUserCow failed";
626             return false;
627         }
628     }
629 
630     return snapuserd_client_->AttachDmUser(misc_name);
631 }
632 
MapSnapshot(LockedFile * lock,const std::string & name,const std::string & base_device,const std::string & cow_device,const std::chrono::milliseconds & timeout_ms,std::string * dev_path)633 bool SnapshotManager::MapSnapshot(LockedFile* lock, const std::string& name,
634                                   const std::string& base_device, const std::string& cow_device,
635                                   const std::chrono::milliseconds& timeout_ms,
636                                   std::string* dev_path) {
637     CHECK(lock);
638 
639     SnapshotStatus status;
640     if (!ReadSnapshotStatus(lock, name, &status)) {
641         return false;
642     }
643     if (status.state() == SnapshotState::NONE || status.state() == SnapshotState::MERGE_COMPLETED) {
644         LOG(ERROR) << "Should not create a snapshot device for " << name
645                    << " after merging has completed.";
646         return false;
647     }
648 
649     // Validate the block device size, as well as the requested snapshot size.
650     // Note that during first-stage init, we don't have the device paths.
651     if (android::base::StartsWith(base_device, "/")) {
652         unique_fd fd(open(base_device.c_str(), O_RDONLY | O_CLOEXEC));
653         if (fd < 0) {
654             PLOG(ERROR) << "open failed: " << base_device;
655             return false;
656         }
657         auto dev_size = get_block_device_size(fd);
658         if (!dev_size) {
659             PLOG(ERROR) << "Could not determine block device size: " << base_device;
660             return false;
661         }
662         if (status.device_size() != dev_size) {
663             LOG(ERROR) << "Block device size for " << base_device << " does not match"
664                        << "(expected " << status.device_size() << ", got " << dev_size << ")";
665             return false;
666         }
667     }
668     if (status.device_size() % kSectorSize != 0) {
669         LOG(ERROR) << "invalid blockdev size for " << base_device << ": " << status.device_size();
670         return false;
671     }
672     if (status.snapshot_size() % kSectorSize != 0 ||
673         status.snapshot_size() > status.device_size()) {
674         LOG(ERROR) << "Invalid snapshot size for " << base_device << ": " << status.snapshot_size();
675         return false;
676     }
677     if (status.device_size() != status.snapshot_size()) {
678         LOG(ERROR) << "Device size and snapshot size must be the same (device size = "
679                    << status.device_size() << ", snapshot size = " << status.snapshot_size();
680         return false;
681     }
682 
683     uint64_t snapshot_sectors = status.snapshot_size() / kSectorSize;
684 
685     // Note that merging is a global state. We do track whether individual devices
686     // have completed merging, but the start of the merge process is considered
687     // atomic.
688     SnapshotStorageMode mode;
689     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
690     switch (update_status.state()) {
691         case UpdateState::MergeCompleted:
692         case UpdateState::MergeNeedsReboot:
693             LOG(ERROR) << "Should not create a snapshot device for " << name
694                        << " after global merging has completed.";
695             return false;
696         case UpdateState::Merging:
697         case UpdateState::MergeFailed:
698             // Note: MergeFailed indicates that a merge is in progress, but
699             // is possibly stalled. We still have to honor the merge.
700             if (DecideMergePhase(status) == update_status.merge_phase()) {
701                 mode = SnapshotStorageMode::Merge;
702             } else {
703                 mode = SnapshotStorageMode::Persistent;
704             }
705             break;
706         default:
707             mode = SnapshotStorageMode::Persistent;
708             break;
709     }
710 
711     if (mode == SnapshotStorageMode::Persistent && status.state() == SnapshotState::MERGING) {
712         LOG(ERROR) << "Snapshot: " << name
713                    << " has snapshot status Merging but mode set to Persistent."
714                    << " Changing mode to Snapshot-Merge.";
715         mode = SnapshotStorageMode::Merge;
716     }
717 
718     DmTable table;
719     table.Emplace<DmTargetSnapshot>(0, snapshot_sectors, base_device, cow_device, mode,
720                                     kSnapshotChunkSize);
721     if (!dm_.CreateDevice(name, table, dev_path, timeout_ms)) {
722         LOG(ERROR) << "Could not create snapshot device: " << name;
723         return false;
724     }
725     return true;
726 }
727 
MapCowImage(const std::string & name,const std::chrono::milliseconds & timeout_ms)728 std::optional<std::string> SnapshotManager::MapCowImage(
729         const std::string& name, const std::chrono::milliseconds& timeout_ms) {
730     if (!EnsureImageManager()) return std::nullopt;
731     auto cow_image_name = GetCowImageDeviceName(name);
732 
733     bool ok;
734     std::string cow_dev;
735     if (device_->IsRecovery() || device_->IsFirstStageInit()) {
736         const auto& opener = device_->GetPartitionOpener();
737         ok = images_->MapImageWithDeviceMapper(opener, cow_image_name, &cow_dev);
738     } else {
739         ok = images_->MapImageDevice(cow_image_name, timeout_ms, &cow_dev);
740     }
741 
742     if (ok) {
743         LOG(INFO) << "Mapped " << cow_image_name << " to " << cow_dev;
744         return cow_dev;
745     }
746     LOG(ERROR) << "Could not map image device: " << cow_image_name;
747     return std::nullopt;
748 }
749 
MapSourceDevice(LockedFile * lock,const std::string & name,const std::chrono::milliseconds & timeout_ms,std::string * path)750 bool SnapshotManager::MapSourceDevice(LockedFile* lock, const std::string& name,
751                                       const std::chrono::milliseconds& timeout_ms,
752                                       std::string* path) {
753     CHECK(lock);
754 
755     auto metadata = ReadOldPartitionMetadata(lock);
756     if (!metadata) {
757         LOG(ERROR) << "Could not map source device due to missing or corrupt metadata";
758         return false;
759     }
760 
761     auto old_name = GetOtherPartitionName(name);
762     auto slot_suffix = device_->GetSlotSuffix();
763     auto slot = SlotNumberForSlotSuffix(slot_suffix);
764 
765     CreateLogicalPartitionParams params = {
766             .block_device = device_->GetSuperDevice(slot),
767             .metadata = metadata,
768             .partition_name = old_name,
769             .timeout_ms = timeout_ms,
770             .device_name = GetSourceDeviceName(name),
771             .partition_opener = &device_->GetPartitionOpener(),
772     };
773     if (!CreateLogicalPartition(std::move(params), path)) {
774         LOG(ERROR) << "Could not create source device for snapshot " << name;
775         return false;
776     }
777     return true;
778 }
779 
UnmapSnapshot(LockedFile * lock,const std::string & name)780 bool SnapshotManager::UnmapSnapshot(LockedFile* lock, const std::string& name) {
781     CHECK(lock);
782 
783     if (UpdateUsesUserSnapshots(lock)) {
784         if (!UnmapUserspaceSnapshotDevice(lock, name)) {
785             return false;
786         }
787     } else {
788         if (!DeleteDeviceIfExists(name)) {
789             LOG(ERROR) << "Could not delete snapshot device: " << name;
790             return false;
791         }
792     }
793     return true;
794 }
795 
UnmapCowImage(const std::string & name)796 bool SnapshotManager::UnmapCowImage(const std::string& name) {
797     if (!EnsureImageManager()) return false;
798     return images_->UnmapImageIfExists(GetCowImageDeviceName(name));
799 }
800 
DeleteSnapshot(LockedFile * lock,const std::string & name)801 bool SnapshotManager::DeleteSnapshot(LockedFile* lock, const std::string& name) {
802     CHECK(lock);
803     CHECK(lock->lock_mode() == LOCK_EX);
804     if (!EnsureImageManager()) return false;
805 
806     if (!UnmapCowDevices(lock, name)) {
807         return false;
808     }
809 
810     // We can't delete snapshots in recovery. The only way we'd try is it we're
811     // completing or canceling a merge in preparation for a data wipe, in which
812     // case, we don't care if the file sticks around.
813     if (device_->IsRecovery()) {
814         LOG(INFO) << "Skipping delete of snapshot " << name << " in recovery.";
815         return true;
816     }
817 
818     auto cow_image_name = GetCowImageDeviceName(name);
819     if (images_->BackingImageExists(cow_image_name)) {
820         if (!images_->DeleteBackingImage(cow_image_name)) {
821             return false;
822         }
823     }
824 
825     std::string error;
826     auto file_path = GetSnapshotStatusFilePath(name);
827     if (!android::base::RemoveFileIfExists(file_path, &error)) {
828         LOG(ERROR) << "Failed to remove status file " << file_path << ": " << error;
829         return false;
830     }
831 
832     // This path may never exist. If it is present, then it's a stale
833     // snapshot status file. Just remove the file and log the message.
834     const std::string tmp_path = file_path + ".tmp";
835     if (!android::base::RemoveFileIfExists(tmp_path, &error)) {
836         LOG(ERROR) << "Failed to remove stale snapshot file " << tmp_path;
837     }
838 
839     return true;
840 }
841 
InitiateMerge()842 bool SnapshotManager::InitiateMerge() {
843     auto lock = LockExclusive();
844     if (!lock) return false;
845 
846     UpdateState state = ReadUpdateState(lock.get());
847     if (state != UpdateState::Unverified) {
848         LOG(ERROR) << "Cannot begin a merge if an update has not been verified";
849         return false;
850     }
851 
852     auto slot = GetCurrentSlot();
853     if (slot != Slot::Target) {
854         LOG(ERROR) << "Device cannot merge while not booting from new slot";
855         return false;
856     }
857 
858     std::vector<std::string> snapshots;
859     if (!ListSnapshots(lock.get(), &snapshots)) {
860         LOG(ERROR) << "Could not list snapshots";
861         return false;
862     }
863 
864     auto current_slot_suffix = device_->GetSlotSuffix();
865 
866     for (const auto& snapshot : snapshots) {
867         if (!android::base::EndsWith(snapshot, current_slot_suffix)) {
868             // Allow the merge to continue, but log this unexpected case.
869             LOG(ERROR) << "Unexpected snapshot found during merge: " << snapshot;
870             continue;
871         }
872 
873         // The device has to be mapped, since everything should be merged at
874         // the same time. This is a fairly serious error. We could forcefully
875         // map everything here, but it should have been mapped during first-
876         // stage init.
877         if (dm_.GetState(snapshot) == DmDeviceState::INVALID) {
878             LOG(ERROR) << "Cannot begin merge; device " << snapshot << " is not mapped.";
879             return false;
880         }
881     }
882 
883     auto metadata = ReadCurrentMetadata();
884     for (auto it = snapshots.begin(); it != snapshots.end();) {
885         switch (GetMetadataPartitionState(*metadata, *it)) {
886             case MetadataPartitionState::Flashed:
887                 LOG(WARNING) << "Detected re-flashing for partition " << *it
888                              << ". Skip merging it.";
889                 [[fallthrough]];
890             case MetadataPartitionState::None: {
891                 LOG(WARNING) << "Deleting snapshot for partition " << *it;
892                 if (!DeleteSnapshot(lock.get(), *it)) {
893                     LOG(WARNING) << "Cannot delete snapshot for partition " << *it
894                                  << ". Skip merging it anyways.";
895                 }
896                 it = snapshots.erase(it);
897             } break;
898             case MetadataPartitionState::Updated: {
899                 ++it;
900             } break;
901         }
902     }
903 
904     bool using_snapuserd = false;
905 
906     std::vector<std::string> first_merge_group;
907 
908     DmTargetSnapshot::Status initial_target_values = {};
909     for (const auto& snapshot : snapshots) {
910         if (!UpdateUsesUserSnapshots(lock.get())) {
911             DmTargetSnapshot::Status current_status;
912             if (!QuerySnapshotStatus(snapshot, nullptr, &current_status)) {
913                 return false;
914             }
915             initial_target_values.sectors_allocated += current_status.sectors_allocated;
916             initial_target_values.total_sectors += current_status.total_sectors;
917             initial_target_values.metadata_sectors += current_status.metadata_sectors;
918         }
919 
920         SnapshotStatus snapshot_status;
921         if (!ReadSnapshotStatus(lock.get(), snapshot, &snapshot_status)) {
922             return false;
923         }
924 
925         using_snapuserd |= snapshot_status.using_snapuserd();
926         if (DecideMergePhase(snapshot_status) == MergePhase::FIRST_PHASE) {
927             first_merge_group.emplace_back(snapshot);
928         }
929     }
930 
931     SnapshotUpdateStatus initial_status = ReadSnapshotUpdateStatus(lock.get());
932     initial_status.set_state(UpdateState::Merging);
933     initial_status.set_using_snapuserd(using_snapuserd);
934 
935     if (!UpdateUsesUserSnapshots(lock.get())) {
936         initial_status.set_sectors_allocated(initial_target_values.sectors_allocated);
937         initial_status.set_total_sectors(initial_target_values.total_sectors);
938         initial_status.set_metadata_sectors(initial_target_values.metadata_sectors);
939     }
940 
941     // If any partitions shrunk, we need to merge them before we merge any other
942     // partitions (see b/177935716). Otherwise, a merge from another partition
943     // may overwrite the source block of a copy operation.
944     const std::vector<std::string>* merge_group;
945     if (first_merge_group.empty()) {
946         merge_group = &snapshots;
947         initial_status.set_merge_phase(MergePhase::SECOND_PHASE);
948     } else {
949         merge_group = &first_merge_group;
950         initial_status.set_merge_phase(MergePhase::FIRST_PHASE);
951     }
952 
953     // Point of no return - mark that we're starting a merge. From now on every
954     // eligible snapshot must be a merge target.
955     if (!WriteSnapshotUpdateStatus(lock.get(), initial_status)) {
956         return false;
957     }
958 
959     auto reported_code = MergeFailureCode::Ok;
960     for (const auto& snapshot : *merge_group) {
961         // If this fails, we have no choice but to continue. Everything must
962         // be merged. This is not an ideal state to be in, but it is safe,
963         // because we the next boot will try again.
964         auto code = SwitchSnapshotToMerge(lock.get(), snapshot);
965         if (code != MergeFailureCode::Ok) {
966             LOG(ERROR) << "Failed to switch snapshot to a merge target: " << snapshot;
967             if (reported_code == MergeFailureCode::Ok) {
968                 reported_code = code;
969             }
970         }
971     }
972 
973     // If we couldn't switch everything to a merge target, pre-emptively mark
974     // this merge as failed. It will get acknowledged when WaitForMerge() is
975     // called.
976     if (reported_code != MergeFailureCode::Ok) {
977         WriteUpdateState(lock.get(), UpdateState::MergeFailed, reported_code);
978     }
979 
980     // Return true no matter what, because a merge was initiated.
981     return true;
982 }
983 
SwitchSnapshotToMerge(LockedFile * lock,const std::string & name)984 MergeFailureCode SnapshotManager::SwitchSnapshotToMerge(LockedFile* lock, const std::string& name) {
985     SnapshotStatus status;
986     if (!ReadSnapshotStatus(lock, name, &status)) {
987         return MergeFailureCode::ReadStatus;
988     }
989     if (status.state() != SnapshotState::CREATED) {
990         LOG(WARNING) << "Snapshot " << name
991                      << " has unexpected state: " << SnapshotState_Name(status.state());
992     }
993 
994     if (UpdateUsesUserSnapshots(lock)) {
995         if (EnsureSnapuserdConnected()) {
996             // This is the point where we inform the daemon to initiate/resume
997             // the merge
998             if (!snapuserd_client_->InitiateMerge(name)) {
999                 return MergeFailureCode::UnknownTable;
1000             }
1001         } else {
1002             LOG(ERROR) << "Failed to connect to snapuserd daemon to initiate merge";
1003             return MergeFailureCode::UnknownTable;
1004         }
1005     } else {
1006         // After this, we return true because we technically did switch to a merge
1007         // target. Everything else we do here is just informational.
1008         if (auto code = RewriteSnapshotDeviceTable(name); code != MergeFailureCode::Ok) {
1009             return code;
1010         }
1011     }
1012 
1013     status.set_state(SnapshotState::MERGING);
1014 
1015     if (!UpdateUsesUserSnapshots(lock)) {
1016         DmTargetSnapshot::Status dm_status;
1017         if (!QuerySnapshotStatus(name, nullptr, &dm_status)) {
1018             LOG(ERROR) << "Could not query merge status for snapshot: " << name;
1019         }
1020         status.set_sectors_allocated(dm_status.sectors_allocated);
1021         status.set_metadata_sectors(dm_status.metadata_sectors);
1022     }
1023 
1024     if (!WriteSnapshotStatus(lock, status)) {
1025         LOG(ERROR) << "Could not update status file for snapshot: " << name;
1026     }
1027     return MergeFailureCode::Ok;
1028 }
1029 
RewriteSnapshotDeviceTable(const std::string & name)1030 MergeFailureCode SnapshotManager::RewriteSnapshotDeviceTable(const std::string& name) {
1031     std::vector<DeviceMapper::TargetInfo> old_targets;
1032     if (!dm_.GetTableInfo(name, &old_targets)) {
1033         LOG(ERROR) << "Could not read snapshot device table: " << name;
1034         return MergeFailureCode::GetTableInfo;
1035     }
1036     if (old_targets.size() != 1 || DeviceMapper::GetTargetType(old_targets[0].spec) != "snapshot") {
1037         LOG(ERROR) << "Unexpected device-mapper table for snapshot: " << name;
1038         return MergeFailureCode::UnknownTable;
1039     }
1040 
1041     std::string base_device, cow_device;
1042     if (!DmTargetSnapshot::GetDevicesFromParams(old_targets[0].data, &base_device, &cow_device)) {
1043         LOG(ERROR) << "Could not derive underlying devices for snapshot: " << name;
1044         return MergeFailureCode::GetTableParams;
1045     }
1046 
1047     DmTable table;
1048     table.Emplace<DmTargetSnapshot>(0, old_targets[0].spec.length, base_device, cow_device,
1049                                     SnapshotStorageMode::Merge, kSnapshotChunkSize);
1050     if (!dm_.LoadTableAndActivate(name, table)) {
1051         LOG(ERROR) << "Could not swap device-mapper tables on snapshot device " << name;
1052         return MergeFailureCode::ActivateNewTable;
1053     }
1054     LOG(INFO) << "Successfully switched snapshot device to a merge target: " << name;
1055     return MergeFailureCode::Ok;
1056 }
1057 
GetSingleTarget(const std::string & dm_name,TableQuery query,DeviceMapper::TargetInfo * target)1058 bool SnapshotManager::GetSingleTarget(const std::string& dm_name, TableQuery query,
1059                                       DeviceMapper::TargetInfo* target) {
1060     if (dm_.GetState(dm_name) == DmDeviceState::INVALID) {
1061         return false;
1062     }
1063 
1064     std::vector<DeviceMapper::TargetInfo> targets;
1065     bool result;
1066     if (query == TableQuery::Status) {
1067         result = dm_.GetTableStatus(dm_name, &targets);
1068     } else {
1069         result = dm_.GetTableInfo(dm_name, &targets);
1070     }
1071     if (!result) {
1072         LOG(ERROR) << "Could not query device: " << dm_name;
1073         return false;
1074     }
1075     if (targets.size() != 1) {
1076         return false;
1077     }
1078 
1079     *target = std::move(targets[0]);
1080     return true;
1081 }
1082 
IsSnapshotDevice(const std::string & dm_name,TargetInfo * target)1083 bool SnapshotManager::IsSnapshotDevice(const std::string& dm_name, TargetInfo* target) {
1084     DeviceMapper::TargetInfo snap_target;
1085     if (!GetSingleTarget(dm_name, TableQuery::Status, &snap_target)) {
1086         return false;
1087     }
1088     auto type = DeviceMapper::GetTargetType(snap_target.spec);
1089 
1090     // If this is not a user-snapshot device then it should either
1091     // be a dm-snapshot or dm-snapshot-merge target
1092     if (type != "user") {
1093         if (type != "snapshot" && type != "snapshot-merge") {
1094             return false;
1095         }
1096     }
1097 
1098     if (target) {
1099         *target = std::move(snap_target);
1100     }
1101     return true;
1102 }
1103 
UpdateStateToStr(const enum UpdateState state)1104 auto SnapshotManager::UpdateStateToStr(const enum UpdateState state) {
1105     switch (state) {
1106         case None:
1107             return "None";
1108         case Initiated:
1109             return "Initiated";
1110         case Unverified:
1111             return "Unverified";
1112         case Merging:
1113             return "Merging";
1114         case MergeNeedsReboot:
1115             return "MergeNeedsReboot";
1116         case MergeCompleted:
1117             return "MergeCompleted";
1118         case MergeFailed:
1119             return "MergeFailed";
1120         case Cancelled:
1121             return "Cancelled";
1122         default:
1123             return "Unknown";
1124     }
1125 }
1126 
QuerySnapshotStatus(const std::string & dm_name,std::string * target_type,DmTargetSnapshot::Status * status)1127 bool SnapshotManager::QuerySnapshotStatus(const std::string& dm_name, std::string* target_type,
1128                                           DmTargetSnapshot::Status* status) {
1129     DeviceMapper::TargetInfo target;
1130     if (!IsSnapshotDevice(dm_name, &target)) {
1131         LOG(ERROR) << "Device " << dm_name << " is not a snapshot or snapshot-merge device";
1132         return false;
1133     }
1134     if (!DmTargetSnapshot::ParseStatusText(target.data, status)) {
1135         LOG(ERROR) << "Could not parse snapshot status text: " << dm_name;
1136         return false;
1137     }
1138     if (target_type) {
1139         *target_type = DeviceMapper::GetTargetType(target.spec);
1140     }
1141     if (!status->error.empty()) {
1142         LOG(ERROR) << "Snapshot: " << dm_name << " returned error code: " << status->error;
1143         return false;
1144     }
1145     return true;
1146 }
1147 
1148 // Note that when a merge fails, we will *always* try again to complete the
1149 // merge each time the device boots. There is no harm in doing so, and if
1150 // the problem was transient, we might manage to get a new outcome.
ProcessUpdateState(const std::function<bool ()> & callback,const std::function<bool ()> & before_cancel)1151 UpdateState SnapshotManager::ProcessUpdateState(const std::function<bool()>& callback,
1152                                                 const std::function<bool()>& before_cancel) {
1153     while (true) {
1154         auto result = CheckMergeState(before_cancel);
1155         LOG(INFO) << "ProcessUpdateState handling state: " << UpdateStateToStr(result.state);
1156 
1157         if (result.state == UpdateState::MergeFailed) {
1158             AcknowledgeMergeFailure(result.failure_code);
1159         }
1160 
1161         if (result.state == UpdateState::MergeCompleted) {
1162             if (device_->IsTempMetadata()) {
1163                 CleanupScratchOtaMetadataIfPresent();
1164             }
1165         }
1166 
1167         if (result.state != UpdateState::Merging) {
1168             // Either there is no merge, or the merge was finished, so no need
1169             // to keep waiting.
1170             return result.state;
1171         }
1172 
1173         if (callback && !callback()) {
1174             return result.state;
1175         }
1176 
1177         // This wait is not super time sensitive, so we have a relatively
1178         // low polling frequency.
1179         std::this_thread::sleep_for(kUpdateStateCheckInterval);
1180     }
1181 }
1182 
CheckMergeState(const std::function<bool ()> & before_cancel)1183 auto SnapshotManager::CheckMergeState(const std::function<bool()>& before_cancel) -> MergeResult {
1184     auto lock = LockExclusive();
1185     if (!lock) {
1186         return MergeResult(UpdateState::MergeFailed, MergeFailureCode::AcquireLock);
1187     }
1188 
1189     auto result = CheckMergeState(lock.get(), before_cancel);
1190     LOG(INFO) << "CheckMergeState for snapshots returned: " << UpdateStateToStr(result.state);
1191 
1192     if (result.state == UpdateState::MergeCompleted) {
1193         // Do this inside the same lock. Failures get acknowledged without the
1194         // lock, because flock() might have failed.
1195         AcknowledgeMergeSuccess(lock.get());
1196     } else if (result.state == UpdateState::Cancelled) {
1197         if (!device_->IsRecovery() && !RemoveAllUpdateState(lock.get(), before_cancel)) {
1198             LOG(ERROR) << "Failed to remove all update state after acknowleding cancelled update.";
1199         }
1200     }
1201     return result;
1202 }
1203 
CheckMergeState(LockedFile * lock,const std::function<bool ()> & before_cancel)1204 auto SnapshotManager::CheckMergeState(LockedFile* lock,
1205                                       const std::function<bool()>& before_cancel) -> MergeResult {
1206     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
1207     switch (update_status.state()) {
1208         case UpdateState::None:
1209         case UpdateState::MergeCompleted:
1210             // Harmless races are allowed between two callers of WaitForMerge,
1211             // so in both of these cases we just propagate the state.
1212             return MergeResult(update_status.state());
1213 
1214         case UpdateState::Merging:
1215         case UpdateState::MergeNeedsReboot:
1216         case UpdateState::MergeFailed:
1217             // We'll poll each snapshot below. Note that for the NeedsReboot
1218             // case, we always poll once to give cleanup another opportunity to
1219             // run.
1220             break;
1221 
1222         case UpdateState::Unverified:
1223             // This is an edge case. Normally cancelled updates are detected
1224             // via the merge poll below, but if we never started a merge, we
1225             // need to also check here.
1226             if (HandleCancelledUpdate(lock, before_cancel)) {
1227                 return MergeResult(UpdateState::Cancelled);
1228             }
1229             return MergeResult(update_status.state());
1230 
1231         default:
1232             return MergeResult(update_status.state());
1233     }
1234 
1235     std::vector<std::string> snapshots;
1236     if (!ListSnapshots(lock, &snapshots)) {
1237         return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ListSnapshots);
1238     }
1239 
1240     auto current_slot_suffix = device_->GetSlotSuffix();
1241 
1242     bool cancelled = false;
1243     bool merging = false;
1244     bool needs_reboot = false;
1245     bool wrong_phase = false;
1246     MergeFailureCode failure_code = MergeFailureCode::Ok;
1247     for (const auto& snapshot : snapshots) {
1248         if (!android::base::EndsWith(snapshot, current_slot_suffix)) {
1249             // This will have triggered an error message in InitiateMerge already.
1250             LOG(ERROR) << "Skipping merge validation of unexpected snapshot: " << snapshot;
1251             continue;
1252         }
1253 
1254         auto result = CheckTargetMergeState(lock, snapshot, update_status);
1255         LOG(INFO) << "CheckTargetMergeState for " << snapshot
1256                   << " returned: " << UpdateStateToStr(result.state);
1257 
1258         switch (result.state) {
1259             case UpdateState::MergeFailed:
1260                 // Take the first failure code in case other failures compound.
1261                 if (failure_code == MergeFailureCode::Ok) {
1262                     failure_code = result.failure_code;
1263                 }
1264                 break;
1265             case UpdateState::Merging:
1266                 merging = true;
1267                 break;
1268             case UpdateState::MergeNeedsReboot:
1269                 needs_reboot = true;
1270                 break;
1271             case UpdateState::MergeCompleted:
1272                 break;
1273             case UpdateState::Cancelled:
1274                 cancelled = true;
1275                 break;
1276             case UpdateState::None:
1277                 wrong_phase = true;
1278                 break;
1279             default:
1280                 LOG(ERROR) << "Unknown merge status for \"" << snapshot << "\": " << "\""
1281                            << result.state << "\"";
1282                 if (failure_code == MergeFailureCode::Ok) {
1283                     failure_code = MergeFailureCode::UnexpectedMergeState;
1284                 }
1285                 break;
1286         }
1287     }
1288 
1289     if (merging) {
1290         // Note that we handle "Merging" before we handle anything else. We
1291         // want to poll until *nothing* is merging if we can, so everything has
1292         // a chance to get marked as completed or failed.
1293         return MergeResult(UpdateState::Merging);
1294     }
1295     if (failure_code != MergeFailureCode::Ok) {
1296         // Note: since there are many drop-out cases for failure, we acknowledge
1297         // it in WaitForMerge rather than here and elsewhere.
1298         return MergeResult(UpdateState::MergeFailed, failure_code);
1299     }
1300     if (wrong_phase) {
1301         // If we got here, no other partitions are being merged, and nothing
1302         // failed to merge. It's safe to move to the next merge phase.
1303         auto code = MergeSecondPhaseSnapshots(lock);
1304         if (code != MergeFailureCode::Ok) {
1305             return MergeResult(UpdateState::MergeFailed, code);
1306         }
1307         return MergeResult(UpdateState::Merging);
1308     }
1309     if (needs_reboot) {
1310         WriteUpdateState(lock, UpdateState::MergeNeedsReboot);
1311         return MergeResult(UpdateState::MergeNeedsReboot);
1312     }
1313     if (cancelled) {
1314         // This is an edge case, that we handle as correctly as we sensibly can.
1315         // The underlying partition has changed behind update_engine, and we've
1316         // removed the snapshot as a result. The exact state of the update is
1317         // undefined now, but this can only happen on an unlocked device where
1318         // partitions can be flashed without wiping userdata.
1319         return MergeResult(UpdateState::Cancelled);
1320     }
1321     return MergeResult(UpdateState::MergeCompleted);
1322 }
1323 
CheckTargetMergeState(LockedFile * lock,const std::string & name,const SnapshotUpdateStatus & update_status)1324 auto SnapshotManager::CheckTargetMergeState(LockedFile* lock, const std::string& name,
1325                                             const SnapshotUpdateStatus& update_status)
1326         -> MergeResult {
1327     SnapshotStatus snapshot_status;
1328     if (!ReadSnapshotStatus(lock, name, &snapshot_status)) {
1329         return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ReadStatus);
1330     }
1331 
1332     std::unique_ptr<LpMetadata> current_metadata;
1333 
1334     if (!IsSnapshotDevice(name)) {
1335         if (!current_metadata) {
1336             current_metadata = ReadCurrentMetadata();
1337         }
1338 
1339         if (!current_metadata ||
1340             GetMetadataPartitionState(*current_metadata, name) != MetadataPartitionState::Updated) {
1341             DeleteSnapshot(lock, name);
1342             return MergeResult(UpdateState::Cancelled);
1343         }
1344 
1345         // During a check, we decided the merge was complete, but we were unable to
1346         // collapse the device-mapper stack and perform COW cleanup. If we haven't
1347         // rebooted after this check, the device will still be a snapshot-merge
1348         // target. If we have rebooted, the device will now be a linear target,
1349         // and we can try cleanup again.
1350         if (snapshot_status.state() == SnapshotState::MERGE_COMPLETED) {
1351             // NB: It's okay if this fails now, we gave cleanup our best effort.
1352             OnSnapshotMergeComplete(lock, name, snapshot_status);
1353             return MergeResult(UpdateState::MergeCompleted);
1354         }
1355 
1356         LOG(ERROR) << "Expected snapshot or snapshot-merge for device: " << name;
1357         return MergeResult(UpdateState::MergeFailed, MergeFailureCode::UnknownTargetType);
1358     }
1359 
1360     // This check is expensive so it is only enabled for debugging.
1361     DCHECK((current_metadata = ReadCurrentMetadata()) &&
1362            GetMetadataPartitionState(*current_metadata, name) == MetadataPartitionState::Updated);
1363 
1364     if (UpdateUsesUserSnapshots(lock)) {
1365         if (!EnsureSnapuserdConnected()) {
1366             return MergeResult(UpdateState::MergeFailed, MergeFailureCode::QuerySnapshotStatus);
1367         }
1368 
1369         // Query the snapshot status from the daemon
1370         const auto merge_status = snapuserd_client_->QuerySnapshotStatus(name);
1371         if (merge_status == "snapshot-merge-failed") {
1372             return MergeResult(UpdateState::MergeFailed, MergeFailureCode::UnknownTargetType);
1373         }
1374 
1375         // This is the case when device reboots during merge. Once the device boots,
1376         // snapuserd daemon will not resume merge immediately in first stage init.
1377         // This is slightly different as compared to dm-snapshot-merge; In this
1378         // case, metadata file will have "MERGING" state whereas the daemon will be
1379         // waiting to resume the merge. Thus, we resume the merge at this point.
1380         if (merge_status == "snapshot" && snapshot_status.state() == SnapshotState::MERGING) {
1381             if (!snapuserd_client_->InitiateMerge(name)) {
1382                 return MergeResult(UpdateState::MergeFailed, MergeFailureCode::UnknownTargetType);
1383             }
1384             return MergeResult(UpdateState::Merging);
1385         }
1386 
1387         if (merge_status == "snapshot" &&
1388             DecideMergePhase(snapshot_status) == MergePhase::SECOND_PHASE) {
1389             if (update_status.merge_phase() == MergePhase::FIRST_PHASE) {
1390                 // The snapshot is not being merged because it's in the wrong phase.
1391                 return MergeResult(UpdateState::None);
1392             } else {
1393                 // update_status is already in second phase but the
1394                 // snapshot_status is still not set to SnapshotState::MERGING.
1395                 //
1396                 // Resume the merge at this point. see b/374225913
1397                 LOG(INFO) << "SwitchSnapshotToMerge: " << name << " after resuming merge";
1398                 auto code = SwitchSnapshotToMerge(lock, name);
1399                 if (code != MergeFailureCode::Ok) {
1400                     LOG(ERROR) << "Failed to switch snapshot: " << name
1401                                << " to merge during second phase";
1402                     return MergeResult(UpdateState::MergeFailed,
1403                                        MergeFailureCode::UnknownTargetType);
1404                 }
1405                 return MergeResult(UpdateState::Merging);
1406             }
1407         }
1408 
1409         if (merge_status == "snapshot-merge") {
1410             if (snapshot_status.state() == SnapshotState::MERGE_COMPLETED) {
1411                 LOG(ERROR) << "Snapshot " << name
1412                            << " is merging after being marked merge-complete.";
1413                 return MergeResult(UpdateState::MergeFailed,
1414                                    MergeFailureCode::UnmergedSectorsAfterCompletion);
1415             }
1416             return MergeResult(UpdateState::Merging);
1417         }
1418 
1419         if (merge_status != "snapshot-merge-complete") {
1420             LOG(ERROR) << "Snapshot " << name << " has incorrect status: " << merge_status;
1421             return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ExpectedMergeTarget);
1422         }
1423     } else {
1424         // dm-snapshot in the kernel
1425         std::string target_type;
1426         DmTargetSnapshot::Status status;
1427         if (!QuerySnapshotStatus(name, &target_type, &status)) {
1428             return MergeResult(UpdateState::MergeFailed, MergeFailureCode::QuerySnapshotStatus);
1429         }
1430         if (target_type == "snapshot" &&
1431             DecideMergePhase(snapshot_status) == MergePhase::SECOND_PHASE &&
1432             update_status.merge_phase() == MergePhase::FIRST_PHASE) {
1433             // The snapshot is not being merged because it's in the wrong phase.
1434             return MergeResult(UpdateState::None);
1435         }
1436         if (target_type != "snapshot-merge") {
1437             // We can get here if we failed to rewrite the target type in
1438             // InitiateMerge(). If we failed to create the target in first-stage
1439             // init, boot would not succeed.
1440             LOG(ERROR) << "Snapshot " << name << " has incorrect target type: " << target_type;
1441             return MergeResult(UpdateState::MergeFailed, MergeFailureCode::ExpectedMergeTarget);
1442         }
1443 
1444         // These two values are equal when merging is complete.
1445         if (status.sectors_allocated != status.metadata_sectors) {
1446             if (snapshot_status.state() == SnapshotState::MERGE_COMPLETED) {
1447                 LOG(ERROR) << "Snapshot " << name
1448                            << " is merging after being marked merge-complete.";
1449                 return MergeResult(UpdateState::MergeFailed,
1450                                    MergeFailureCode::UnmergedSectorsAfterCompletion);
1451             }
1452             return MergeResult(UpdateState::Merging);
1453         }
1454     }
1455 
1456     // Merging is done. First, update the status file to indicate the merge
1457     // is complete. We do this before calling OnSnapshotMergeComplete, even
1458     // though this means the write is potentially wasted work (since in the
1459     // ideal case we'll immediately delete the file).
1460     //
1461     // This makes it simpler to reason about the next reboot: no matter what
1462     // part of cleanup failed, first-stage init won't try to create another
1463     // snapshot device for this partition.
1464     snapshot_status.set_state(SnapshotState::MERGE_COMPLETED);
1465     if (!WriteSnapshotStatus(lock, snapshot_status)) {
1466         return MergeResult(UpdateState::MergeFailed, MergeFailureCode::WriteStatus);
1467     }
1468     if (!OnSnapshotMergeComplete(lock, name, snapshot_status)) {
1469         return MergeResult(UpdateState::MergeNeedsReboot);
1470     }
1471     return MergeResult(UpdateState::MergeCompleted, MergeFailureCode::Ok);
1472 }
1473 
1474 // This returns the backing device, not the dm-user layer.
GetMappedCowDeviceName(const std::string & snapshot,const SnapshotStatus & status)1475 static std::string GetMappedCowDeviceName(const std::string& snapshot,
1476                                           const SnapshotStatus& status) {
1477     // If no partition was created (the COW exists entirely on /data), the
1478     // device-mapper layering is different than if we had a partition.
1479     if (status.cow_partition_size() == 0) {
1480         return GetCowImageDeviceName(snapshot);
1481     }
1482     return GetCowName(snapshot);
1483 }
1484 
MergeSecondPhaseSnapshots(LockedFile * lock)1485 MergeFailureCode SnapshotManager::MergeSecondPhaseSnapshots(LockedFile* lock) {
1486     std::vector<std::string> snapshots;
1487     if (!ListSnapshots(lock, &snapshots)) {
1488         return MergeFailureCode::ListSnapshots;
1489     }
1490 
1491     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
1492     CHECK(update_status.state() == UpdateState::Merging ||
1493           update_status.state() == UpdateState::MergeFailed);
1494     CHECK(update_status.merge_phase() == MergePhase::FIRST_PHASE);
1495 
1496     update_status.set_state(UpdateState::Merging);
1497     update_status.set_merge_phase(MergePhase::SECOND_PHASE);
1498     if (!WriteSnapshotUpdateStatus(lock, update_status)) {
1499         return MergeFailureCode::WriteStatus;
1500     }
1501 
1502     auto current_slot_suffix = device_->GetSlotSuffix();
1503     MergeFailureCode result = MergeFailureCode::Ok;
1504     for (const auto& snapshot : snapshots) {
1505         if (!android::base::EndsWith(snapshot, current_slot_suffix)) {
1506             LOG(ERROR) << "Skipping invalid snapshot: " << snapshot
1507                        << " during MergeSecondPhaseSnapshots";
1508             continue;
1509         }
1510         SnapshotStatus snapshot_status;
1511         if (!ReadSnapshotStatus(lock, snapshot, &snapshot_status)) {
1512             return MergeFailureCode::ReadStatus;
1513         }
1514         if (DecideMergePhase(snapshot_status) != MergePhase::SECOND_PHASE) {
1515             continue;
1516         }
1517         auto code = SwitchSnapshotToMerge(lock, snapshot);
1518         if (code != MergeFailureCode::Ok) {
1519             LOG(ERROR) << "Failed to switch snapshot to a second-phase merge target: " << snapshot;
1520             if (result == MergeFailureCode::Ok) {
1521                 result = code;
1522             }
1523         }
1524     }
1525     return result;
1526 }
1527 
GetBootSnapshotsWithoutSlotSwitchPath()1528 std::string SnapshotManager::GetBootSnapshotsWithoutSlotSwitchPath() {
1529     return metadata_dir_ + "/" + android::base::Basename(kBootSnapshotsWithoutSlotSwitch);
1530 }
1531 
GetSnapshotBootIndicatorPath()1532 std::string SnapshotManager::GetSnapshotBootIndicatorPath() {
1533     return metadata_dir_ + "/" + android::base::Basename(kBootIndicatorPath);
1534 }
1535 
GetRollbackIndicatorPath()1536 std::string SnapshotManager::GetRollbackIndicatorPath() {
1537     return metadata_dir_ + "/" + android::base::Basename(kRollbackIndicatorPath);
1538 }
1539 
GetSnapuserdFromSystemPath()1540 std::string SnapshotManager::GetSnapuserdFromSystemPath() {
1541     return metadata_dir_ + "/" + android::base::Basename(kSnapuserdFromSystem);
1542 }
1543 
GetForwardMergeIndicatorPath()1544 std::string SnapshotManager::GetForwardMergeIndicatorPath() {
1545     return metadata_dir_ + "/allow-forward-merge";
1546 }
1547 
GetOldPartitionMetadataPath()1548 std::string SnapshotManager::GetOldPartitionMetadataPath() {
1549     return metadata_dir_ + "/old-partition-metadata";
1550 }
1551 
AcknowledgeMergeSuccess(LockedFile * lock)1552 void SnapshotManager::AcknowledgeMergeSuccess(LockedFile* lock) {
1553     // It's not possible to remove update state in recovery, so write an
1554     // indicator that cleanup is needed on reboot. If a factory data reset
1555     // was requested, it doesn't matter, everything will get wiped anyway.
1556     // To make testing easier we consider a /data wipe as cleaned up.
1557     if (device_->IsRecovery()) {
1558         WriteUpdateState(lock, UpdateState::MergeCompleted);
1559         return;
1560     }
1561 
1562     RemoveAllUpdateState(lock);
1563 
1564     if (UpdateUsesUserSnapshots(lock) && !device()->IsTestDevice()) {
1565         if (snapuserd_client_) {
1566             snapuserd_client_->DetachSnapuserd();
1567             snapuserd_client_->RemoveTransitionedDaemonIndicator();
1568             snapuserd_client_ = nullptr;
1569         }
1570     }
1571 }
1572 
AcknowledgeMergeFailure(MergeFailureCode failure_code)1573 void SnapshotManager::AcknowledgeMergeFailure(MergeFailureCode failure_code) {
1574     // Log first, so worst case, we always have a record of why the calls below
1575     // were being made.
1576     LOG(ERROR) << "Merge could not be completed and will be marked as failed.";
1577 
1578     auto lock = LockExclusive();
1579     if (!lock) return;
1580 
1581     // Since we released the lock in between WaitForMerge and here, it's
1582     // possible (1) the merge successfully completed or (2) was already
1583     // marked as a failure. So make sure to check the state again, and
1584     // only mark as a failure if appropriate.
1585     UpdateState state = ReadUpdateState(lock.get());
1586     if (state != UpdateState::Merging && state != UpdateState::MergeNeedsReboot) {
1587         return;
1588     }
1589 
1590     WriteUpdateState(lock.get(), UpdateState::MergeFailed, failure_code);
1591 }
1592 
OnSnapshotMergeComplete(LockedFile * lock,const std::string & name,const SnapshotStatus & status)1593 bool SnapshotManager::OnSnapshotMergeComplete(LockedFile* lock, const std::string& name,
1594                                               const SnapshotStatus& status) {
1595     if (!UpdateUsesUserSnapshots(lock)) {
1596         if (IsSnapshotDevice(name)) {
1597             // We are extra-cautious here, to avoid deleting the wrong table.
1598             std::string target_type;
1599             DmTargetSnapshot::Status dm_status;
1600             if (!QuerySnapshotStatus(name, &target_type, &dm_status)) {
1601                 return false;
1602             }
1603             if (target_type != "snapshot-merge") {
1604                 LOG(ERROR) << "Unexpected target type " << target_type
1605                            << " for snapshot device: " << name;
1606                 return false;
1607             }
1608             if (dm_status.sectors_allocated != dm_status.metadata_sectors) {
1609                 LOG(ERROR) << "Merge is unexpectedly incomplete for device " << name;
1610                 return false;
1611             }
1612             if (!CollapseSnapshotDevice(lock, name, status)) {
1613                 LOG(ERROR) << "Unable to collapse snapshot: " << name;
1614                 return false;
1615             }
1616         }
1617     } else {
1618         // Just collapse the device - no need to query again as we just did
1619         // prior to calling this function
1620         if (!CollapseSnapshotDevice(lock, name, status)) {
1621             LOG(ERROR) << "Unable to collapse snapshot: " << name;
1622             return false;
1623         }
1624     }
1625 
1626     // Note that collapsing is implicitly an Unmap, so we don't need to
1627     // unmap the snapshot.
1628 
1629     if (!DeleteSnapshot(lock, name)) {
1630         LOG(ERROR) << "Could not delete snapshot: " << name;
1631         return false;
1632     }
1633     return true;
1634 }
1635 
CollapseSnapshotDevice(LockedFile * lock,const std::string & name,const SnapshotStatus & status)1636 bool SnapshotManager::CollapseSnapshotDevice(LockedFile* lock, const std::string& name,
1637                                              const SnapshotStatus& status) {
1638     if (!UpdateUsesUserSnapshots(lock)) {
1639         // Verify we have a snapshot-merge device.
1640         DeviceMapper::TargetInfo target;
1641         if (!GetSingleTarget(name, TableQuery::Table, &target)) {
1642             return false;
1643         }
1644         if (DeviceMapper::GetTargetType(target.spec) != "snapshot-merge") {
1645             // This should be impossible, it was checked earlier.
1646             LOG(ERROR) << "Snapshot device has invalid target type: " << name;
1647             return false;
1648         }
1649 
1650         std::string base_device, cow_device;
1651         if (!DmTargetSnapshot::GetDevicesFromParams(target.data, &base_device, &cow_device)) {
1652             LOG(ERROR) << "Could not parse snapshot device " << name
1653                        << " parameters: " << target.data;
1654             return false;
1655         }
1656     }
1657 
1658     uint64_t snapshot_sectors = status.snapshot_size() / kSectorSize;
1659     if (snapshot_sectors * kSectorSize != status.snapshot_size()) {
1660         LOG(ERROR) << "Snapshot " << name
1661                    << " size is not sector aligned: " << status.snapshot_size();
1662         return false;
1663     }
1664 
1665     uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
1666     // Create a DmTable that is identical to the base device.
1667     CreateLogicalPartitionParams base_device_params{
1668             .block_device = device_->GetSuperDevice(slot),
1669             .metadata_slot = slot,
1670             .partition_name = name,
1671             .partition_opener = &device_->GetPartitionOpener(),
1672     };
1673     DmTable table;
1674     if (!CreateDmTable(base_device_params, &table)) {
1675         LOG(ERROR) << "Could not create a DmTable for partition: " << name;
1676         return false;
1677     }
1678 
1679     if (!dm_.LoadTableAndActivate(name, table)) {
1680         return false;
1681     }
1682 
1683     if (!UpdateUsesUserSnapshots(lock)) {
1684         // Attempt to delete the snapshot device if one still exists. Nothing
1685         // should be depending on the device, and device-mapper should have
1686         // flushed remaining I/O. We could in theory replace with dm-zero (or
1687         // re-use the table above), but for now it's better to know why this
1688         // would fail.
1689         //
1690         // Furthermore, we should not be trying to unmap for userspace snapshot
1691         // as unmap will fail since dm-user itself was a snapshot device prior
1692         // to switching of tables. Unmap will fail as the device will be mounted
1693         // by system partitions
1694         if (status.using_snapuserd()) {
1695             auto dm_user_name = GetDmUserCowName(name, GetSnapshotDriver(lock));
1696             UnmapDmUserDevice(dm_user_name);
1697         }
1698     }
1699 
1700     // We can't delete base device immediately as daemon holds a reference.
1701     // Make sure we wait for all the worker threads to terminate and release
1702     // the reference
1703     if (UpdateUsesUserSnapshots(lock) && EnsureSnapuserdConnected()) {
1704         if (!snapuserd_client_->WaitForDeviceDelete(name)) {
1705             LOG(ERROR) << "Failed to wait for " << name << " control device to delete";
1706         }
1707     }
1708 
1709     auto base_name = GetBaseDeviceName(name);
1710     if (!DeleteDeviceIfExists(base_name)) {
1711         LOG(ERROR) << "Unable to delete base device for snapshot: " << base_name;
1712     }
1713 
1714     if (!DeleteDeviceIfExists(GetSourceDeviceName(name), 4000ms)) {
1715         LOG(ERROR) << "Unable to delete source device for snapshot: " << GetSourceDeviceName(name);
1716     }
1717 
1718     return true;
1719 }
1720 
HandleCancelledUpdate(LockedFile * lock,const std::function<bool ()> & before_cancel)1721 bool SnapshotManager::HandleCancelledUpdate(LockedFile* lock,
1722                                             const std::function<bool()>& before_cancel) {
1723     auto slot = GetCurrentSlot();
1724     if (slot == Slot::Unknown) {
1725         return false;
1726     }
1727 
1728     // If all snapshots were reflashed, then cancel the entire update.
1729     if (AreAllSnapshotsCancelled(lock)) {
1730         LOG(WARNING) << "Detected re-flashing, cancelling unverified update.";
1731         return RemoveAllUpdateState(lock, before_cancel);
1732     }
1733 
1734     // If update has been rolled back, then cancel the entire update.
1735     // Client (update_engine) is responsible for doing additional cleanup work on its own states
1736     // when ProcessUpdateState() returns UpdateState::Cancelled.
1737     auto current_slot = GetCurrentSlot();
1738     if (current_slot != Slot::Source) {
1739         LOG(INFO) << "Update state is being processed while booting at " << current_slot
1740                   << " slot, taking no action.";
1741         return false;
1742     }
1743 
1744     // current_slot == Source. Attempt to detect rollbacks.
1745     if (access(GetRollbackIndicatorPath().c_str(), F_OK) != 0) {
1746         // This unverified update is not attempted. Take no action.
1747         PLOG(INFO) << "Rollback indicator not detected. "
1748                    << "Update state is being processed before reboot, taking no action.";
1749         return false;
1750     }
1751 
1752     LOG(WARNING) << "Detected rollback, cancelling unverified update.";
1753     return RemoveAllUpdateState(lock, before_cancel);
1754 }
1755 
PerformInitTransition(InitTransition transition,std::vector<std::string> * snapuserd_argv)1756 bool SnapshotManager::PerformInitTransition(InitTransition transition,
1757                                             std::vector<std::string>* snapuserd_argv) {
1758     LOG(INFO) << "Performing transition for snapuserd.";
1759 
1760     // Don't use EnsureSnapuserdConnected() because this is called from init,
1761     // and attempting to do so will deadlock.
1762     if (!snapuserd_client_ && transition != InitTransition::SELINUX_DETACH) {
1763         snapuserd_client_ = SnapuserdClient::Connect(kSnapuserdSocket, 10s);
1764         if (!snapuserd_client_) {
1765             LOG(ERROR) << "Unable to connect to snapuserd";
1766             return false;
1767         }
1768     }
1769 
1770     auto lock = LockExclusive();
1771     if (!lock) return false;
1772 
1773     std::vector<std::string> snapshots;
1774     if (!ListSnapshots(lock.get(), &snapshots)) {
1775         LOG(ERROR) << "Failed to list snapshots.";
1776         return false;
1777     }
1778 
1779     if (UpdateUsesUserSnapshots(lock.get()) && transition == InitTransition::SELINUX_DETACH) {
1780         snapuserd_argv->emplace_back("-user_snapshot");
1781         if (UpdateUsesIouring(lock.get())) {
1782             snapuserd_argv->emplace_back("-io_uring");
1783         }
1784         if (UpdateUsesODirect(lock.get())) {
1785             snapuserd_argv->emplace_back("-o_direct");
1786         }
1787         uint cow_op_merge_size = GetUpdateCowOpMergeSize(lock.get());
1788         if (cow_op_merge_size != 0) {
1789             snapuserd_argv->emplace_back("-cow_op_merge_size=" + std::to_string(cow_op_merge_size));
1790         }
1791         uint32_t worker_count = GetUpdateWorkerCount(lock.get());
1792         if (worker_count != 0) {
1793             snapuserd_argv->emplace_back("-worker_count=" + std::to_string(worker_count));
1794         }
1795         uint32_t verify_block_size = GetVerificationBlockSize(lock.get());
1796         if (verify_block_size != 0) {
1797             snapuserd_argv->emplace_back("-verify_block_size=" + std::to_string(verify_block_size));
1798         }
1799         uint32_t num_verify_threads = GetNumVerificationThreads(lock.get());
1800         if (num_verify_threads != 0) {
1801             snapuserd_argv->emplace_back("-num_verify_threads=" +
1802                                          std::to_string(num_verify_threads));
1803         }
1804     }
1805 
1806     size_t num_cows = 0;
1807     size_t ok_cows = 0;
1808     for (const auto& snapshot : snapshots) {
1809         std::string user_cow_name = GetDmUserCowName(snapshot, GetSnapshotDriver(lock.get()));
1810 
1811         if (dm_.GetState(user_cow_name) == DmDeviceState::INVALID) {
1812             continue;
1813         }
1814 
1815         DeviceMapper::TargetInfo target;
1816         if (!GetSingleTarget(user_cow_name, TableQuery::Table, &target)) {
1817             continue;
1818         }
1819 
1820         auto target_type = DeviceMapper::GetTargetType(target.spec);
1821         if (target_type != "user") {
1822             LOG(ERROR) << "Unexpected target type for " << user_cow_name << ": " << target_type;
1823             continue;
1824         }
1825 
1826         num_cows++;
1827 
1828         SnapshotStatus snapshot_status;
1829         if (!ReadSnapshotStatus(lock.get(), snapshot, &snapshot_status)) {
1830             LOG(ERROR) << "Unable to read snapshot status: " << snapshot;
1831             continue;
1832         }
1833 
1834         auto misc_name = user_cow_name;
1835 
1836         std::string source_device_name;
1837         if (snapshot_status.old_partition_size() > 0) {
1838             source_device_name = GetSourceDeviceName(snapshot);
1839         } else {
1840             source_device_name = GetBaseDeviceName(snapshot);
1841         }
1842 
1843         std::string source_device;
1844         if (!dm_.GetDmDevicePathByName(source_device_name, &source_device)) {
1845             LOG(ERROR) << "Could not get device path for " << GetSourceDeviceName(snapshot);
1846             continue;
1847         }
1848 
1849         std::string base_path_merge;
1850         if (!dm_.GetDmDevicePathByName(GetBaseDeviceName(snapshot), &base_path_merge)) {
1851             LOG(ERROR) << "Could not get device path for " << GetSourceDeviceName(snapshot);
1852             continue;
1853         }
1854 
1855         std::string cow_image_name = GetMappedCowDeviceName(snapshot, snapshot_status);
1856 
1857         std::string cow_image_device;
1858         if (!dm_.GetDmDevicePathByName(cow_image_name, &cow_image_device)) {
1859             LOG(ERROR) << "Could not get device path for " << cow_image_name;
1860             continue;
1861         }
1862 
1863         if (transition == InitTransition::SELINUX_DETACH) {
1864             if (!UpdateUsesUserSnapshots(lock.get())) {
1865                 auto message = misc_name + "," + cow_image_device + "," + source_device;
1866                 snapuserd_argv->emplace_back(std::move(message));
1867             } else {
1868                 auto message = misc_name + "," + cow_image_device + "," + source_device + "," +
1869                                base_path_merge;
1870                 snapuserd_argv->emplace_back(std::move(message));
1871             }
1872             SetReadAheadSize(cow_image_device, snapshot_status.read_ahead_size());
1873             SetReadAheadSize(source_device, snapshot_status.read_ahead_size());
1874 
1875             // Do not attempt to connect to the new snapuserd yet, it hasn't
1876             // been started. We do however want to wait for the misc device
1877             // to have been created.
1878             ok_cows++;
1879             continue;
1880         }
1881 
1882         DmTable table;
1883         table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
1884         if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
1885             LOG(ERROR) << "Unable to swap tables for " << misc_name;
1886             continue;
1887         }
1888 
1889         // Wait for ueventd to acknowledge and create the control device node.
1890         std::string control_device = "/dev/dm-user/" + misc_name;
1891         if (!WaitForDevice(control_device, 10s)) {
1892             LOG(ERROR) << "dm-user control device no found:  " << misc_name;
1893             continue;
1894         }
1895 
1896         uint64_t base_sectors;
1897         if (!UpdateUsesUserSnapshots(lock.get())) {
1898             base_sectors =
1899                     snapuserd_client_->InitDmUserCow(misc_name, cow_image_device, source_device);
1900         } else {
1901             base_sectors = snapuserd_client_->InitDmUserCow(misc_name, cow_image_device,
1902                                                             source_device, base_path_merge);
1903         }
1904 
1905         if (base_sectors == 0) {
1906             // Unrecoverable as metadata reads from cow device failed
1907             LOG(FATAL) << "Failed to retrieve base_sectors from Snapuserd";
1908             return false;
1909         }
1910 
1911         CHECK(base_sectors <= target.spec.length);
1912 
1913         if (!snapuserd_client_->AttachDmUser(misc_name)) {
1914             // This error is unrecoverable. We cannot proceed because reads to
1915             // the underlying device will fail.
1916             LOG(FATAL) << "Could not initialize snapuserd for " << user_cow_name;
1917             return false;
1918         }
1919 
1920         ok_cows++;
1921     }
1922 
1923     if (ok_cows != num_cows) {
1924         LOG(ERROR) << "Could not transition all snapuserd consumers.";
1925         return false;
1926     }
1927     return true;
1928 }
1929 
ReadCurrentMetadata()1930 std::unique_ptr<LpMetadata> SnapshotManager::ReadCurrentMetadata() {
1931     const auto& opener = device_->GetPartitionOpener();
1932     uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
1933     auto super_device = device_->GetSuperDevice(slot);
1934     auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
1935     if (!metadata) {
1936         LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
1937         return nullptr;
1938     }
1939     return metadata;
1940 }
1941 
GetMetadataPartitionState(const LpMetadata & metadata,const std::string & name)1942 SnapshotManager::MetadataPartitionState SnapshotManager::GetMetadataPartitionState(
1943         const LpMetadata& metadata, const std::string& name) {
1944     auto partition = android::fs_mgr::FindPartition(metadata, name);
1945     if (!partition) return MetadataPartitionState::None;
1946     if (partition->attributes & LP_PARTITION_ATTR_UPDATED) {
1947         return MetadataPartitionState::Updated;
1948     }
1949     return MetadataPartitionState::Flashed;
1950 }
1951 
AreAllSnapshotsCancelled(LockedFile * lock)1952 bool SnapshotManager::AreAllSnapshotsCancelled(LockedFile* lock) {
1953     std::vector<std::string> snapshots;
1954     if (!ListSnapshots(lock, &snapshots)) {
1955         LOG(WARNING) << "Failed to list snapshots to determine whether device has been flashed "
1956                      << "after applying an update. Assuming no snapshots.";
1957         // Let HandleCancelledUpdate resets UpdateState.
1958         return true;
1959     }
1960 
1961     std::map<std::string, bool> flashing_status;
1962 
1963     if (!GetSnapshotFlashingStatus(lock, snapshots, &flashing_status)) {
1964         LOG(WARNING) << "Failed to determine whether partitions have been flashed. Not"
1965                      << "removing update states.";
1966         return false;
1967     }
1968 
1969     bool all_snapshots_cancelled = std::all_of(flashing_status.begin(), flashing_status.end(),
1970                                                [](const auto& pair) { return pair.second; });
1971 
1972     if (all_snapshots_cancelled) {
1973         LOG(WARNING) << "All partitions are re-flashed after update, removing all update states.";
1974     }
1975     return all_snapshots_cancelled;
1976 }
1977 
GetSnapshotFlashingStatus(LockedFile * lock,const std::vector<std::string> & snapshots,std::map<std::string,bool> * out)1978 bool SnapshotManager::GetSnapshotFlashingStatus(LockedFile* lock,
1979                                                 const std::vector<std::string>& snapshots,
1980                                                 std::map<std::string, bool>* out) {
1981     CHECK(lock);
1982 
1983     auto source_slot_suffix = ReadUpdateSourceSlotSuffix();
1984     if (source_slot_suffix.empty()) {
1985         return false;
1986     }
1987     uint32_t source_slot = SlotNumberForSlotSuffix(source_slot_suffix);
1988     uint32_t target_slot = (source_slot == 0) ? 1 : 0;
1989 
1990     // Attempt to detect re-flashing on each partition.
1991     // - If all partitions are re-flashed, we can proceed to cancel the whole update.
1992     // - If only some of the partitions are re-flashed, snapshots for re-flashed partitions are
1993     //   deleted. Caller is responsible for merging the rest of the snapshots.
1994     // - If none of the partitions are re-flashed, caller is responsible for merging the snapshots.
1995     //
1996     // Note that we use target slot metadata, since if an OTA has been applied
1997     // to the target slot, we can detect the UPDATED flag. Any kind of flash
1998     // operation against dynamic partitions ensures that all copies of the
1999     // metadata are in sync, so flashing all partitions on the source slot will
2000     // remove the UPDATED flag on the target slot as well.
2001     const auto& opener = device_->GetPartitionOpener();
2002     auto super_device = device_->GetSuperDevice(target_slot);
2003     auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, target_slot);
2004     if (!metadata) {
2005         return false;
2006     }
2007 
2008     for (const auto& snapshot_name : snapshots) {
2009         if (GetMetadataPartitionState(*metadata, snapshot_name) ==
2010             MetadataPartitionState::Updated) {
2011             out->emplace(snapshot_name, false);
2012         } else {
2013             // Delete snapshots for partitions that are re-flashed after the update.
2014             LOG(WARNING) << "Detected re-flashing of partition " << snapshot_name << ".";
2015             out->emplace(snapshot_name, true);
2016         }
2017     }
2018     return true;
2019 }
2020 
RemoveInvalidSnapshots(LockedFile * lock)2021 void SnapshotManager::RemoveInvalidSnapshots(LockedFile* lock) {
2022     std::vector<std::string> snapshots;
2023 
2024     // Remove the stale snapshot metadata
2025     //
2026     // We make sure that all the three cases
2027     // are valid before removing the snapshot metadata:
2028     //
2029     // 1: dm state is active
2030     // 2: Root fs is not mounted off as a snapshot device
2031     // 3: Snapshot slot suffix should match current device slot
2032     if (!ListSnapshots(lock, &snapshots, device_->GetSlotSuffix()) || snapshots.empty()) {
2033         return;
2034     }
2035 
2036     // We indeed have some invalid snapshots
2037     for (const auto& name : snapshots) {
2038         if (dm_.GetState(name) == DmDeviceState::ACTIVE && !IsSnapshotDevice(name)) {
2039             if (!DeleteSnapshot(lock, name)) {
2040                 LOG(ERROR) << "Failed to delete invalid snapshot: " << name;
2041             } else {
2042                 LOG(INFO) << "Invalid snapshot: " << name << " deleted";
2043             }
2044         }
2045     }
2046 }
2047 
RemoveAllSnapshots(LockedFile * lock)2048 bool SnapshotManager::RemoveAllSnapshots(LockedFile* lock) {
2049     std::vector<std::string> snapshots;
2050     if (!ListSnapshots(lock, &snapshots)) {
2051         LOG(ERROR) << "Could not list snapshots";
2052         return false;
2053     }
2054 
2055     std::map<std::string, bool> flashing_status;
2056     if (!GetSnapshotFlashingStatus(lock, snapshots, &flashing_status)) {
2057         LOG(WARNING) << "Failed to get flashing status";
2058     }
2059 
2060     auto current_slot = GetCurrentSlot();
2061     bool ok = true;
2062     bool has_mapped_cow_images = false;
2063     for (const auto& name : snapshots) {
2064         // If booting off source slot, it is okay to unmap and delete all the snapshots.
2065         // If boot indicator is missing, update state is None or Initiated, so
2066         //   it is also okay to unmap and delete all the snapshots.
2067         // If booting off target slot,
2068         //  - should not unmap because:
2069         //    - In Android mode, snapshots are not mapped, but
2070         //      filesystems are mounting off dm-linear targets directly.
2071         //    - In recovery mode, assume nothing is mapped, so it is optional to unmap.
2072         //  - If partition is flashed or unknown, it is okay to delete snapshots.
2073         //    Otherwise (UPDATED flag), only delete snapshots if they are not mapped
2074         //    as dm-snapshot (for example, after merge completes).
2075         bool should_unmap = current_slot != Slot::Target;
2076         bool should_delete = ShouldDeleteSnapshot(flashing_status, current_slot, name);
2077         if (should_unmap && android::base::EndsWith(name, device_->GetSlotSuffix())) {
2078             // Something very unexpected has happened - we want to unmap this
2079             // snapshot, but it's on the wrong slot. We can't unmap an active
2080             // partition. If this is not really a snapshot, skip the unmap
2081             // step.
2082             if (dm_.GetState(name) == DmDeviceState::INVALID || !IsSnapshotDevice(name)) {
2083                 LOG(ERROR) << "Detected snapshot " << name << " on " << current_slot << " slot"
2084                            << " for source partition; removing without unmap.";
2085                 should_unmap = false;
2086             }
2087         }
2088 
2089         bool partition_ok = true;
2090         if (should_unmap && !UnmapPartitionWithSnapshot(lock, name)) {
2091             partition_ok = false;
2092         }
2093         if (partition_ok && should_delete && !DeleteSnapshot(lock, name)) {
2094             partition_ok = false;
2095         }
2096 
2097         if (!partition_ok) {
2098             // Remember whether or not we were able to unmap the cow image.
2099             auto cow_image_device = GetCowImageDeviceName(name);
2100             has_mapped_cow_images |=
2101                     (EnsureImageManager() && images_->IsImageMapped(cow_image_device));
2102 
2103             ok = false;
2104         }
2105     }
2106 
2107     if (ok || !has_mapped_cow_images) {
2108         if (!EnsureImageManager()) {
2109             return false;
2110         }
2111 
2112         if (device_->IsRecovery()) {
2113             // If a device is in recovery, we need to mark the snapshots for cleanup
2114             // upon next reboot, since we cannot delete them here.
2115             if (!images_->DisableAllImages()) {
2116                 LOG(ERROR) << "Could not remove all snapshot artifacts in recovery";
2117                 return false;
2118             }
2119         } else if (!images_->RemoveAllImages()) {
2120             // Delete any image artifacts as a precaution, in case an update is
2121             // being cancelled due to some corrupted state in an lp_metadata file.
2122             // Note that we do not do this if some cow images are still mapped,
2123             // since we must not remove backing storage if it's in use.
2124             LOG(ERROR) << "Could not remove all snapshot artifacts";
2125             return false;
2126         }
2127     }
2128     return ok;
2129 }
2130 
2131 // See comments in RemoveAllSnapshots().
ShouldDeleteSnapshot(const std::map<std::string,bool> & flashing_status,Slot current_slot,const std::string & name)2132 bool SnapshotManager::ShouldDeleteSnapshot(const std::map<std::string, bool>& flashing_status,
2133                                            Slot current_slot, const std::string& name) {
2134     if (current_slot != Slot::Target) {
2135         return true;
2136     }
2137     auto it = flashing_status.find(name);
2138     if (it == flashing_status.end()) {
2139         LOG(WARNING) << "Can't determine flashing status for " << name;
2140         return true;
2141     }
2142     if (it->second) {
2143         // partition flashed, okay to delete obsolete snapshots
2144         return true;
2145     }
2146     return !IsSnapshotDevice(name);
2147 }
2148 
GetUpdateState(double * progress)2149 UpdateState SnapshotManager::GetUpdateState(double* progress) {
2150     // If we've never started an update, the state file won't exist.
2151     auto state_file = GetStateFilePath();
2152     if (access(state_file.c_str(), F_OK) != 0 && errno == ENOENT) {
2153         return UpdateState::None;
2154     }
2155 
2156     auto lock = LockShared();
2157     if (!lock) {
2158         return UpdateState::None;
2159     }
2160 
2161     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get());
2162     auto state = update_status.state();
2163     if (progress == nullptr) {
2164         return state;
2165     }
2166 
2167     if (state == UpdateState::MergeCompleted) {
2168         *progress = 100.0;
2169         return state;
2170     }
2171 
2172     *progress = 0.0;
2173     if (state != UpdateState::Merging) {
2174         return state;
2175     }
2176 
2177     if (!UpdateUsesUserSnapshots(lock.get())) {
2178         // Sum all the snapshot states as if the system consists of a single huge
2179         // snapshots device, then compute the merge completion percentage of that
2180         // device.
2181         std::vector<std::string> snapshots;
2182         if (!ListSnapshots(lock.get(), &snapshots)) {
2183             LOG(ERROR) << "Could not list snapshots";
2184             return state;
2185         }
2186 
2187         DmTargetSnapshot::Status fake_snapshots_status = {};
2188         for (const auto& snapshot : snapshots) {
2189             DmTargetSnapshot::Status current_status;
2190 
2191             if (!IsSnapshotDevice(snapshot)) continue;
2192             if (!QuerySnapshotStatus(snapshot, nullptr, &current_status)) continue;
2193 
2194             fake_snapshots_status.sectors_allocated += current_status.sectors_allocated;
2195             fake_snapshots_status.total_sectors += current_status.total_sectors;
2196             fake_snapshots_status.metadata_sectors += current_status.metadata_sectors;
2197         }
2198 
2199         *progress = DmTargetSnapshot::MergePercent(fake_snapshots_status,
2200                                                    update_status.sectors_allocated());
2201     } else {
2202         if (EnsureSnapuserdConnected()) {
2203             *progress = snapuserd_client_->GetMergePercent();
2204         }
2205     }
2206 
2207     return state;
2208 }
2209 
IsSnapshotWithoutSlotSwitch()2210 bool SnapshotManager::IsSnapshotWithoutSlotSwitch() {
2211     return (access(GetBootSnapshotsWithoutSlotSwitchPath().c_str(), F_OK) == 0);
2212 }
2213 
UpdateUsesCompression()2214 bool SnapshotManager::UpdateUsesCompression() {
2215     auto lock = LockShared();
2216     if (!lock) return false;
2217     return UpdateUsesCompression(lock.get());
2218 }
2219 
UpdateUsesCompression(LockedFile * lock)2220 bool SnapshotManager::UpdateUsesCompression(LockedFile* lock) {
2221     // This returns true even if compression is "none", since update_engine is
2222     // really just trying to see if snapuserd is in use.
2223     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2224     return update_status.using_snapuserd();
2225 }
2226 
UpdateUsesIouring(LockedFile * lock)2227 bool SnapshotManager::UpdateUsesIouring(LockedFile* lock) {
2228     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2229     return update_status.io_uring_enabled();
2230 }
2231 
UpdateUsesODirect(LockedFile * lock)2232 bool SnapshotManager::UpdateUsesODirect(LockedFile* lock) {
2233     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2234     return update_status.o_direct();
2235 }
2236 
UpdateUsesSkipVerification(LockedFile * lock)2237 bool SnapshotManager::UpdateUsesSkipVerification(LockedFile* lock) {
2238     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2239     return update_status.skip_verification();
2240 }
2241 
GetUpdateCowOpMergeSize(LockedFile * lock)2242 uint32_t SnapshotManager::GetUpdateCowOpMergeSize(LockedFile* lock) {
2243     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2244     return update_status.cow_op_merge_size();
2245 }
2246 
GetUpdateWorkerCount(LockedFile * lock)2247 uint32_t SnapshotManager::GetUpdateWorkerCount(LockedFile* lock) {
2248     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2249     return update_status.num_worker_threads();
2250 }
2251 
GetVerificationBlockSize(LockedFile * lock)2252 uint32_t SnapshotManager::GetVerificationBlockSize(LockedFile* lock) {
2253     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2254     return update_status.verify_block_size();
2255 }
2256 
GetNumVerificationThreads(LockedFile * lock)2257 uint32_t SnapshotManager::GetNumVerificationThreads(LockedFile* lock) {
2258     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2259     return update_status.num_verification_threads();
2260 }
2261 
MarkSnapuserdFromSystem()2262 bool SnapshotManager::MarkSnapuserdFromSystem() {
2263     auto path = GetSnapuserdFromSystemPath();
2264 
2265     if (!android::base::WriteStringToFile("1", path)) {
2266         PLOG(ERROR) << "Unable to write to vendor update path: " << path;
2267         return false;
2268     }
2269 
2270     unique_fd fd(open(path.c_str(), O_PATH));
2271     if (fd < 0) {
2272         PLOG(ERROR) << "Failed to open file: " << path;
2273         return false;
2274     }
2275 
2276     /*
2277      * This function is invoked by first stage init and hence we need to
2278      * explicitly set the correct selinux label for this file as update_engine
2279      * will try to remove this file later on once the snapshot merge is
2280      * complete.
2281      */
2282     if (fsetxattr(fd.get(), XATTR_NAME_SELINUX, kOtaFileContext, strlen(kOtaFileContext) + 1, 0) <
2283         0) {
2284         PLOG(ERROR) << "fsetxattr for the path: " << path << " failed";
2285     }
2286 
2287     return true;
2288 }
2289 
2290 /*
2291  * Please see b/304829384 for more details.
2292  *
2293  * In Android S, we use dm-snapshot for mounting snapshots and snapshot-merge
2294  * process. If the vendor partition continues to be on Android S, then
2295  * "snapuserd" binary in first stage ramdisk will be from vendor partition.
2296  * Thus, we need to maintain backward compatibility.
2297  *
2298  * Now, We take a two step approach to maintain the backward compatibility:
2299  *
2300  * 1: During OTA installation, we will continue to use "user-space" snapshots
2301  * for OTA installation as both update-engine and snapuserd binary will be from system partition.
2302  * However, during installation, we mark "legacy_snapuserd" in
2303  * SnapshotUpdateStatus file to mark that this is a path to support backward compatibility.
2304  * Thus, this function will return "false" during OTA installation.
2305  *
2306  * 2: Post OTA reboot, there are two key steps:
2307  *    a: During first stage init, "init" and "snapuserd" could be from vendor
2308  *    partition. This could be from Android S. Thus, the snapshot mount path
2309  *    will be based off dm-snapshot.
2310  *
2311  *    b: Post selinux transition, "init" and "update-engine" will be "system"
2312  *    partition. Now, since the snapshots are mounted off dm-snapshot,
2313  *    update-engine interaction with "snapuserd" should work based off
2314  *    dm-snapshots.
2315  *
2316  *    TL;DR: update-engine will use the "system" snapuserd for installing new
2317  *    updates (this is safe as there is no "vendor" snapuserd running during
2318  *    installation). Post reboot, update-engine will use the legacy path when
2319  *    communicating with "vendor" snapuserd that was started in first-stage
2320  *    init. Hence, this function checks:
2321  *         i: Are we in post OTA reboot
2322  *         ii: Is the Vendor from Android 12
2323  *         iii: If both (i) and (ii) are true, then use the dm-snapshot based
2324  *         approach.
2325  *
2326  * 3: Post OTA reboot, if the vendor partition was updated from Android 12 to
2327  * any other release post Android 12, then snapuserd binary will be "system"
2328  * partition as post Android 12, init_boot will contain a copy of snapuserd
2329  * binary. Thus, during first stage init, if init is able to communicate to
2330  * daemon, that gives us a signal that the binary is from "system" copy. Hence,
2331  * there is no need to fallback to legacy dm-snapshot. Thus, init will use a
2332  * marker in /metadata to signal that the snapuserd binary from first stage init
2333  * can handle userspace snapshots.
2334  *
2335  */
IsLegacySnapuserdPostReboot()2336 bool SnapshotManager::IsLegacySnapuserdPostReboot() {
2337     auto slot = GetCurrentSlot();
2338     if (slot == Slot::Target) {
2339         /*
2340             If this marker is present, the daemon can handle userspace snapshots.
2341             During post-OTA reboot, this implies that the vendor partition is
2342             Android 13 or higher. If the snapshots were created on an
2343             Android 12 vendor, this means the vendor partition has been updated.
2344         */
2345         if (access(GetSnapuserdFromSystemPath().c_str(), F_OK) == 0) {
2346             is_snapshot_userspace_ = true;
2347             return false;
2348         }
2349         // If the marker isn't present and if the vendor is still in Android 12
2350         if (is_legacy_snapuserd_.has_value() && is_legacy_snapuserd_.value() == true) {
2351             return true;
2352         }
2353     }
2354 
2355     return false;
2356 }
2357 
UpdateUsesUserSnapshots()2358 bool SnapshotManager::UpdateUsesUserSnapshots() {
2359     // This and the following function is constantly
2360     // invoked during snapshot merge. We want to avoid
2361     // constantly reading from disk. Hence, store this
2362     // value in memory.
2363     //
2364     // Furthermore, this value in the disk is set
2365     // only when OTA is applied and doesn't change
2366     // during merge phase. Hence, once we know that
2367     // the value is read from disk the very first time,
2368     // it is safe to read successive checks from memory.
2369 
2370     if (is_snapshot_userspace_.has_value()) {
2371         // Check if legacy snapuserd is running post OTA reboot
2372         if (IsLegacySnapuserdPostReboot()) {
2373             return false;
2374         }
2375         return is_snapshot_userspace_.value();
2376     }
2377 
2378     auto lock = LockShared();
2379     if (!lock) return false;
2380 
2381     return UpdateUsesUserSnapshots(lock.get());
2382 }
2383 
UpdateUsesUserSnapshots(LockedFile * lock)2384 bool SnapshotManager::UpdateUsesUserSnapshots(LockedFile* lock) {
2385     if (!is_snapshot_userspace_.has_value()) {
2386         SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock);
2387         is_snapshot_userspace_ = update_status.userspace_snapshots();
2388         is_legacy_snapuserd_ = update_status.legacy_snapuserd();
2389     }
2390 
2391     if (IsLegacySnapuserdPostReboot()) {
2392         return false;
2393     }
2394 
2395     return is_snapshot_userspace_.value();
2396 }
2397 
ListSnapshots(LockedFile * lock,std::vector<std::string> * snapshots,const std::string & suffix)2398 bool SnapshotManager::ListSnapshots(LockedFile* lock, std::vector<std::string>* snapshots,
2399                                     const std::string& suffix) {
2400     CHECK(lock);
2401 
2402     auto dir_path = metadata_dir_ + "/snapshots"s;
2403     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(dir_path.c_str()), closedir);
2404     if (!dir) {
2405         PLOG(ERROR) << "opendir failed: " << dir_path;
2406         return false;
2407     }
2408 
2409     struct dirent* dp;
2410     while ((dp = readdir(dir.get())) != nullptr) {
2411         if (dp->d_type != DT_REG) continue;
2412 
2413         std::string name(dp->d_name);
2414         if (!suffix.empty() && !android::base::EndsWith(name, suffix)) {
2415             continue;
2416         }
2417 
2418         // Insert system and product partition at the beginning so that
2419         // during snapshot-merge, these partitions are merged first.
2420         if (name == "system_a" || name == "system_b" || name == "product_a" ||
2421             name == "product_b") {
2422             snapshots->insert(snapshots->begin(), std::move(name));
2423         } else {
2424             snapshots->emplace_back(std::move(name));
2425         }
2426     }
2427 
2428     return true;
2429 }
2430 
IsSnapshotManagerNeeded()2431 bool SnapshotManager::IsSnapshotManagerNeeded() {
2432     if (access(kBootIndicatorPath, F_OK) == 0) {
2433         return true;
2434     }
2435 
2436     if (IsScratchOtaMetadataOnSuper()) {
2437         return true;
2438     }
2439 
2440     return false;
2441 }
2442 
MapTempOtaMetadataPartitionIfNeeded(const std::function<bool (const std::string &)> & init)2443 bool SnapshotManager::MapTempOtaMetadataPartitionIfNeeded(
2444         const std::function<bool(const std::string&)>& init) {
2445     auto device = android::snapshot::GetScratchOtaMetadataPartition();
2446     if (!device.empty()) {
2447         init(device);
2448         if (android::snapshot::MapScratchOtaMetadataPartition(device).empty()) {
2449             return false;
2450         }
2451     }
2452     return true;
2453 }
2454 
GetGlobalRollbackIndicatorPath()2455 std::string SnapshotManager::GetGlobalRollbackIndicatorPath() {
2456     return kRollbackIndicatorPath;
2457 }
2458 
NeedSnapshotsInFirstStageMount()2459 bool SnapshotManager::NeedSnapshotsInFirstStageMount() {
2460     if (IsSnapshotWithoutSlotSwitch()) {
2461         if (GetCurrentSlot() != Slot::Source) {
2462             LOG(ERROR) << "Snapshots marked to boot without slot switch; but slot is wrong";
2463             return false;
2464         }
2465         return true;
2466     }
2467     // If we fail to read, we'll wind up using CreateLogicalPartitions, which
2468     // will create devices that look like the old slot, except with extra
2469     // content at the end of each device. This will confuse dm-verity, and
2470     // ultimately we'll fail to boot. Why not make it a fatal error and have
2471     // the reason be clearer? Because the indicator file still exists, and
2472     // if this was FATAL, reverting to the old slot would be broken.
2473     auto slot = GetCurrentSlot();
2474 
2475     if (slot != Slot::Target) {
2476         if (slot == Slot::Source) {
2477             // Device is rebooting into the original slot, so mark this as a
2478             // rollback.
2479             auto path = GetRollbackIndicatorPath();
2480             if (!android::base::WriteStringToFile("1", path)) {
2481                 PLOG(ERROR) << "Unable to write rollback indicator: " << path;
2482             } else {
2483                 LOG(INFO) << "Rollback detected, writing rollback indicator to " << path;
2484                 if (device_->IsTempMetadata()) {
2485                     CleanupScratchOtaMetadataIfPresent();
2486                 }
2487             }
2488         }
2489         LOG(INFO) << "Not booting from new slot. Will not mount snapshots.";
2490         return false;
2491     }
2492 
2493     // If we can't read the update state, it's unlikely anything else will
2494     // succeed, so this is a fatal error. We'll eventually exhaust boot
2495     // attempts and revert to the old slot.
2496     auto lock = LockShared();
2497     if (!lock) {
2498         LOG(FATAL) << "Could not read update state to determine snapshot status";
2499         return false;
2500     }
2501     switch (ReadUpdateState(lock.get())) {
2502         case UpdateState::Unverified:
2503         case UpdateState::Merging:
2504         case UpdateState::MergeFailed:
2505             return true;
2506         default:
2507             return false;
2508     }
2509 }
2510 
CreateLogicalAndSnapshotPartitions(const std::string & super_device,const std::chrono::milliseconds & timeout_ms)2511 bool SnapshotManager::CreateLogicalAndSnapshotPartitions(
2512         const std::string& super_device, const std::chrono::milliseconds& timeout_ms) {
2513     LOG(INFO) << "Creating logical partitions with snapshots as needed";
2514 
2515     auto lock = LockExclusive();
2516     if (!lock) return false;
2517 
2518     uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
2519     return MapAllPartitions(lock.get(), super_device, slot, timeout_ms);
2520 }
2521 
MapAllPartitions(LockedFile * lock,const std::string & super_device,uint32_t slot,const std::chrono::milliseconds & timeout_ms)2522 bool SnapshotManager::MapAllPartitions(LockedFile* lock, const std::string& super_device,
2523                                        uint32_t slot, const std::chrono::milliseconds& timeout_ms) {
2524     const auto& opener = device_->GetPartitionOpener();
2525     auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
2526     if (!metadata) {
2527         LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
2528         return false;
2529     }
2530 
2531     if (!EnsureImageManager()) {
2532         return false;
2533     }
2534 
2535     for (const auto& partition : metadata->partitions) {
2536         if (GetPartitionGroupName(metadata->groups[partition.group_index]) == kCowGroupName) {
2537             LOG(INFO) << "Skip mapping partition " << GetPartitionName(partition) << " in group "
2538                       << kCowGroupName;
2539             continue;
2540         }
2541 
2542         if (GetPartitionName(partition) ==
2543             android::base::Basename(android::snapshot::kOtaMetadataMount)) {
2544             LOG(INFO) << "Partition: " << GetPartitionName(partition) << " skipping";
2545             continue;
2546         }
2547 
2548         CreateLogicalPartitionParams params = {
2549                 .block_device = super_device,
2550                 .metadata = metadata.get(),
2551                 .partition = &partition,
2552                 .timeout_ms = timeout_ms,
2553                 .partition_opener = &opener,
2554         };
2555         if (!MapPartitionWithSnapshot(lock, std::move(params), SnapshotContext::Mount, nullptr)) {
2556             return false;
2557         }
2558     }
2559 
2560     LOG(INFO) << "Created logical partitions with snapshot.";
2561     return true;
2562 }
2563 
GetRemainingTime(const std::chrono::milliseconds & timeout,const std::chrono::time_point<std::chrono::steady_clock> & begin)2564 static std::chrono::milliseconds GetRemainingTime(
2565         const std::chrono::milliseconds& timeout,
2566         const std::chrono::time_point<std::chrono::steady_clock>& begin) {
2567     // If no timeout is specified, execute all commands without specifying any timeout.
2568     if (timeout.count() == 0) return std::chrono::milliseconds(0);
2569     auto passed_time = std::chrono::steady_clock::now() - begin;
2570     auto remaining_time = timeout - duration_cast<std::chrono::milliseconds>(passed_time);
2571     if (remaining_time.count() <= 0) {
2572         LOG(ERROR) << "MapPartitionWithSnapshot has reached timeout " << timeout.count() << "ms ("
2573                    << remaining_time.count() << "ms remaining)";
2574         // Return min() instead of remaining_time here because 0 is treated as a special value for
2575         // no timeout, where the rest of the commands will still be executed.
2576         return std::chrono::milliseconds::min();
2577     }
2578     return remaining_time;
2579 }
2580 
MapPartitionWithSnapshot(LockedFile * lock,CreateLogicalPartitionParams params,SnapshotContext context,SnapshotPaths * paths)2581 bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
2582                                                CreateLogicalPartitionParams params,
2583                                                SnapshotContext context, SnapshotPaths* paths) {
2584     auto begin = std::chrono::steady_clock::now();
2585 
2586     CHECK(lock);
2587 
2588     if (params.GetPartitionName() != params.GetDeviceName()) {
2589         LOG(ERROR) << "Mapping snapshot with a different name is unsupported: partition_name = "
2590                    << params.GetPartitionName() << ", device_name = " << params.GetDeviceName();
2591         return false;
2592     }
2593 
2594     // Fill out fields in CreateLogicalPartitionParams so that we have more information (e.g. by
2595     // reading super partition metadata).
2596     CreateLogicalPartitionParams::OwnedData params_owned_data;
2597     if (!params.InitDefaults(&params_owned_data)) {
2598         return false;
2599     }
2600 
2601     if (!params.partition->num_extents) {
2602         LOG(INFO) << "Skipping zero-length logical partition: " << params.GetPartitionName();
2603         return true;  // leave path empty to indicate that nothing is mapped.
2604     }
2605 
2606     // Determine if there is a live snapshot for the SnapshotStatus of the partition; i.e. if the
2607     // partition still has a snapshot that needs to be mapped.  If no live snapshot or merge
2608     // completed, live_snapshot_status is set to nullopt.
2609     std::optional<SnapshotStatus> live_snapshot_status;
2610     do {
2611         if (!IsSnapshotWithoutSlotSwitch() &&
2612             !(params.partition->attributes & LP_PARTITION_ATTR_UPDATED)) {
2613             LOG(INFO) << "Detected re-flashing of partition, will skip snapshot: "
2614                       << params.GetPartitionName();
2615             break;
2616         }
2617         auto file_path = GetSnapshotStatusFilePath(params.GetPartitionName());
2618         if (access(file_path.c_str(), F_OK) != 0) {
2619             if (errno != ENOENT) {
2620                 PLOG(INFO) << "Can't map snapshot for " << params.GetPartitionName()
2621                            << ": Can't access " << file_path;
2622                 return false;
2623             }
2624             break;
2625         }
2626         live_snapshot_status = std::make_optional<SnapshotStatus>();
2627         if (!ReadSnapshotStatus(lock, params.GetPartitionName(), &*live_snapshot_status)) {
2628             return false;
2629         }
2630         // No live snapshot if merge is completed.
2631         if (live_snapshot_status->state() == SnapshotState::MERGE_COMPLETED) {
2632             live_snapshot_status.reset();
2633         }
2634 
2635         if (live_snapshot_status->state() == SnapshotState::NONE ||
2636             live_snapshot_status->cow_partition_size() + live_snapshot_status->cow_file_size() ==
2637                     0) {
2638             LOG(WARNING) << "Snapshot status for " << params.GetPartitionName()
2639                          << " is invalid, ignoring: state = "
2640                          << SnapshotState_Name(live_snapshot_status->state())
2641                          << ", cow_partition_size = " << live_snapshot_status->cow_partition_size()
2642                          << ", cow_file_size = " << live_snapshot_status->cow_file_size();
2643             live_snapshot_status.reset();
2644         }
2645     } while (0);
2646 
2647     if (live_snapshot_status.has_value()) {
2648         // dm-snapshot requires the base device to be writable.
2649         params.force_writable = true;
2650         // Map the base device with a different name to avoid collision.
2651         params.device_name = GetBaseDeviceName(params.GetPartitionName());
2652     }
2653 
2654     AutoDeviceList created_devices;
2655 
2656     // Create the base device for the snapshot, or if there is no snapshot, the
2657     // device itself. This device consists of the real blocks in the super
2658     // partition that this logical partition occupies.
2659     std::string base_path;
2660     if (!CreateLogicalPartition(params, &base_path)) {
2661         LOG(ERROR) << "Could not create logical partition " << params.GetPartitionName()
2662                    << " as device " << params.GetDeviceName();
2663         return false;
2664     }
2665     created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, params.GetDeviceName());
2666 
2667     if (paths) {
2668         paths->target_device = base_path;
2669     }
2670 
2671     auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
2672     if (remaining_time.count() < 0) {
2673         return false;
2674     }
2675 
2676     // Wait for the base device to appear
2677     if (!WaitForDevice(base_path, remaining_time)) {
2678         return false;
2679     }
2680 
2681     if (!live_snapshot_status.has_value()) {
2682         created_devices.Release();
2683         return true;
2684     }
2685 
2686     // We don't have ueventd in first-stage init, so use device major:minor
2687     // strings instead.
2688     std::string base_device;
2689     if (!dm_.GetDeviceString(params.GetDeviceName(), &base_device)) {
2690         LOG(ERROR) << "Could not determine major/minor for: " << params.GetDeviceName();
2691         return false;
2692     }
2693 
2694     remaining_time = GetRemainingTime(params.timeout_ms, begin);
2695     if (remaining_time.count() < 0) return false;
2696 
2697     std::string cow_name;
2698     CreateLogicalPartitionParams cow_params = params;
2699     cow_params.timeout_ms = remaining_time;
2700     if (!MapCowDevices(lock, cow_params, *live_snapshot_status, &created_devices, &cow_name)) {
2701         return false;
2702     }
2703     std::string cow_device;
2704     if (!GetMappedImageDeviceStringOrPath(cow_name, &cow_device)) {
2705         LOG(ERROR) << "Could not determine major/minor for: " << cow_name;
2706         return false;
2707     }
2708     if (paths) {
2709         paths->cow_device_name = cow_name;
2710     }
2711 
2712     remaining_time = GetRemainingTime(params.timeout_ms, begin);
2713     if (remaining_time.count() < 0) return false;
2714 
2715     if (context == SnapshotContext::Update && live_snapshot_status->using_snapuserd()) {
2716         // Stop here, we can't run dm-user yet, the COW isn't built.
2717         created_devices.Release();
2718         return true;
2719     }
2720 
2721     if (live_snapshot_status->using_snapuserd()) {
2722         // Get the source device (eg the view of the partition from before it was resized).
2723         std::string source_device_path;
2724         if (live_snapshot_status->old_partition_size() > 0) {
2725             if (!MapSourceDevice(lock, params.GetPartitionName(), remaining_time,
2726                                  &source_device_path)) {
2727                 LOG(ERROR) << "Could not map source device for: " << cow_name;
2728                 return false;
2729             }
2730 
2731             auto source_device = GetSourceDeviceName(params.GetPartitionName());
2732             created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, source_device);
2733         } else {
2734             source_device_path = base_path;
2735         }
2736 
2737         if (!WaitForDevice(source_device_path, remaining_time)) {
2738             return false;
2739         }
2740 
2741         std::string cow_path;
2742         if (!GetMappedImageDevicePath(cow_name, &cow_path)) {
2743             LOG(ERROR) << "Could not determine path for: " << cow_name;
2744             return false;
2745         }
2746         if (!WaitForDevice(cow_path, remaining_time)) {
2747             return false;
2748         }
2749 
2750         auto name = GetDmUserCowName(params.GetPartitionName(), GetSnapshotDriver(lock));
2751 
2752         std::string new_cow_device;
2753         if (!MapDmUserCow(lock, name, cow_path, source_device_path, base_path, remaining_time,
2754                           &new_cow_device)) {
2755             LOG(ERROR) << "Could not map dm-user device for partition "
2756                        << params.GetPartitionName();
2757             return false;
2758         }
2759         created_devices.EmplaceBack<AutoUnmapDevice>(&dm_, name);
2760 
2761         cow_device = new_cow_device;
2762     }
2763 
2764     // For userspace snapshots, dm-user block device itself will act as a
2765     // snapshot device. There is one subtle difference - MapSnapshot will create
2766     // either snapshot target or snapshot-merge target based on the underlying
2767     // state of the snapshot device. If snapshot-merge target is created, merge
2768     // will immediately start in the kernel.
2769     //
2770     // This is no longer true with respect to userspace snapshots. When dm-user
2771     // block device is created, we just have the snapshots ready but daemon in
2772     // the user-space will not start the merge. We have to explicitly inform the
2773     // daemon to resume the merge. Check ProcessUpdateState() call stack.
2774     if (!UpdateUsesUserSnapshots(lock)) {
2775         remaining_time = GetRemainingTime(params.timeout_ms, begin);
2776         if (remaining_time.count() < 0) return false;
2777 
2778         std::string path;
2779         if (!MapSnapshot(lock, params.GetPartitionName(), base_device, cow_device, remaining_time,
2780                          &path)) {
2781             LOG(ERROR) << "Could not map snapshot for partition: " << params.GetPartitionName();
2782             return false;
2783         }
2784         // No need to add params.GetPartitionName() to created_devices since it is immediately
2785         // released.
2786 
2787         if (paths) {
2788             paths->snapshot_device = path;
2789         }
2790         LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << path;
2791     } else {
2792         LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at "
2793                   << cow_device;
2794     }
2795 
2796     created_devices.Release();
2797 
2798     return true;
2799 }
2800 
UnmapPartitionWithSnapshot(LockedFile * lock,const std::string & target_partition_name)2801 bool SnapshotManager::UnmapPartitionWithSnapshot(LockedFile* lock,
2802                                                  const std::string& target_partition_name) {
2803     CHECK(lock);
2804 
2805     if (!UnmapSnapshot(lock, target_partition_name)) {
2806         return false;
2807     }
2808 
2809     if (!UnmapCowDevices(lock, target_partition_name)) {
2810         return false;
2811     }
2812 
2813     auto base_name = GetBaseDeviceName(target_partition_name);
2814     if (!DeleteDeviceIfExists(base_name)) {
2815         LOG(ERROR) << "Cannot delete base device: " << base_name;
2816         return false;
2817     }
2818 
2819     auto source_name = GetSourceDeviceName(target_partition_name);
2820     if (!DeleteDeviceIfExists(source_name)) {
2821         LOG(ERROR) << "Cannot delete source device: " << source_name;
2822         return false;
2823     }
2824 
2825     LOG(INFO) << "Successfully unmapped snapshot " << target_partition_name;
2826 
2827     return true;
2828 }
2829 
MapCowDevices(LockedFile * lock,const CreateLogicalPartitionParams & params,const SnapshotStatus & snapshot_status,AutoDeviceList * created_devices,std::string * cow_name)2830 bool SnapshotManager::MapCowDevices(LockedFile* lock, const CreateLogicalPartitionParams& params,
2831                                     const SnapshotStatus& snapshot_status,
2832                                     AutoDeviceList* created_devices, std::string* cow_name) {
2833     CHECK(lock);
2834     CHECK(snapshot_status.cow_partition_size() + snapshot_status.cow_file_size() > 0);
2835     auto begin = std::chrono::steady_clock::now();
2836 
2837     std::string partition_name = params.GetPartitionName();
2838     std::string cow_image_name = GetCowImageDeviceName(partition_name);
2839     *cow_name = GetCowName(partition_name);
2840 
2841     // Map COW image if necessary.
2842     if (snapshot_status.cow_file_size() > 0) {
2843         if (!EnsureImageManager()) return false;
2844         auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
2845         if (remaining_time.count() < 0) return false;
2846 
2847         if (!MapCowImage(partition_name, remaining_time).has_value()) {
2848             LOG(ERROR) << "Could not map cow image for partition: " << partition_name;
2849             return false;
2850         }
2851         created_devices->EmplaceBack<AutoUnmapImage>(images_.get(), cow_image_name);
2852 
2853         // If no COW partition exists, just return the image alone.
2854         if (snapshot_status.cow_partition_size() == 0) {
2855             *cow_name = std::move(cow_image_name);
2856             LOG(INFO) << "Mapped COW image for " << partition_name << " at " << *cow_name;
2857             return true;
2858         }
2859     }
2860 
2861     auto remaining_time = GetRemainingTime(params.timeout_ms, begin);
2862     if (remaining_time.count() < 0) return false;
2863 
2864     CHECK(snapshot_status.cow_partition_size() > 0);
2865 
2866     // Create the DmTable for the COW device. It is the DmTable of the COW partition plus
2867     // COW image device as the last extent.
2868     CreateLogicalPartitionParams cow_partition_params = params;
2869     cow_partition_params.partition = nullptr;
2870     cow_partition_params.partition_name = *cow_name;
2871     cow_partition_params.device_name.clear();
2872     DmTable table;
2873     if (!CreateDmTable(cow_partition_params, &table)) {
2874         return false;
2875     }
2876     // If the COW image exists, append it as the last extent.
2877     if (snapshot_status.cow_file_size() > 0) {
2878         std::string cow_image_device;
2879         if (!GetMappedImageDeviceStringOrPath(cow_image_name, &cow_image_device)) {
2880             LOG(ERROR) << "Cannot determine major/minor for: " << cow_image_name;
2881             return false;
2882         }
2883         auto cow_partition_sectors = snapshot_status.cow_partition_size() / kSectorSize;
2884         auto cow_image_sectors = snapshot_status.cow_file_size() / kSectorSize;
2885         table.Emplace<DmTargetLinear>(cow_partition_sectors, cow_image_sectors, cow_image_device,
2886                                       0);
2887     }
2888 
2889     // We have created the DmTable now. Map it.
2890     std::string cow_path;
2891     if (!dm_.CreateDevice(*cow_name, table, &cow_path, remaining_time)) {
2892         LOG(ERROR) << "Could not create COW device: " << *cow_name;
2893         return false;
2894     }
2895     created_devices->EmplaceBack<AutoUnmapDevice>(&dm_, *cow_name);
2896     LOG(INFO) << "Mapped COW device for " << params.GetPartitionName() << " at " << cow_path;
2897     return true;
2898 }
2899 
UnmapCowDevices(LockedFile * lock,const std::string & name)2900 bool SnapshotManager::UnmapCowDevices(LockedFile* lock, const std::string& name) {
2901     CHECK(lock);
2902     if (!EnsureImageManager()) return false;
2903 
2904     if (UpdateUsesCompression(lock) && !UpdateUsesUserSnapshots(lock)) {
2905         auto dm_user_name = GetDmUserCowName(name, GetSnapshotDriver(lock));
2906         if (!UnmapDmUserDevice(dm_user_name)) {
2907             return false;
2908         }
2909     }
2910 
2911     if (!DeleteDeviceIfExists(GetCowName(name), 4000ms)) {
2912         LOG(ERROR) << "Cannot unmap: " << GetCowName(name);
2913         return false;
2914     }
2915 
2916     std::string cow_image_name = GetCowImageDeviceName(name);
2917     if (!images_->UnmapImageIfExists(cow_image_name)) {
2918         LOG(ERROR) << "Cannot unmap image " << cow_image_name;
2919         return false;
2920     }
2921     return true;
2922 }
2923 
UnmapDmUserDevice(const std::string & dm_user_name)2924 bool SnapshotManager::UnmapDmUserDevice(const std::string& dm_user_name) {
2925     if (dm_.GetState(dm_user_name) == DmDeviceState::INVALID) {
2926         return true;
2927     }
2928 
2929     if (!DeleteDeviceIfExists(dm_user_name)) {
2930         LOG(ERROR) << "Cannot unmap " << dm_user_name;
2931         return false;
2932     }
2933 
2934     if (EnsureSnapuserdConnected()) {
2935         if (!snapuserd_client_->WaitForDeviceDelete(dm_user_name)) {
2936             LOG(ERROR) << "Failed to wait for " << dm_user_name << " control device to delete";
2937             return false;
2938         }
2939     }
2940 
2941     // Ensure the control device is gone so we don't run into ABA problems.
2942     auto control_device = "/dev/dm-user/" + dm_user_name;
2943     if (!android::fs_mgr::WaitForFileDeleted(control_device, 10s)) {
2944         LOG(ERROR) << "Timed out waiting for " << control_device << " to unlink";
2945         return false;
2946     }
2947     return true;
2948 }
2949 
UnmapUserspaceSnapshotDevice(LockedFile * lock,const std::string & snapshot_name)2950 bool SnapshotManager::UnmapUserspaceSnapshotDevice(LockedFile* lock,
2951                                                    const std::string& snapshot_name) {
2952     auto dm_user_name = GetDmUserCowName(snapshot_name, GetSnapshotDriver(lock));
2953     if (dm_.GetState(dm_user_name) == DmDeviceState::INVALID) {
2954         return true;
2955     }
2956 
2957     CHECK(lock);
2958 
2959     SnapshotStatus snapshot_status;
2960 
2961     if (!ReadSnapshotStatus(lock, snapshot_name, &snapshot_status)) {
2962         return false;
2963     }
2964     // If the merge is complete, then we switch dm tables which is equivalent
2965     // to unmap; hence, we can't be deleting the device
2966     // as the table would be mounted off partitions and will fail.
2967     if (snapshot_status.state() != SnapshotState::MERGE_COMPLETED) {
2968         if (!DeleteDeviceIfExists(dm_user_name, 4000ms)) {
2969             LOG(ERROR) << "Cannot unmap " << dm_user_name;
2970             return false;
2971         }
2972     }
2973 
2974     if (EnsureSnapuserdConnected()) {
2975         if (!snapuserd_client_->WaitForDeviceDelete(dm_user_name)) {
2976             LOG(ERROR) << "Failed to wait for " << dm_user_name << " control device to delete";
2977             return false;
2978         }
2979     }
2980 
2981     // Ensure the control device is gone so we don't run into ABA problems.
2982     auto control_device = "/dev/dm-user/" + dm_user_name;
2983     if (!android::fs_mgr::WaitForFileDeleted(control_device, 10s)) {
2984         LOG(ERROR) << "Timed out waiting for " << control_device << " to unlink";
2985         return false;
2986     }
2987     return true;
2988 }
2989 
MapAllSnapshots(const std::chrono::milliseconds & timeout_ms)2990 bool SnapshotManager::MapAllSnapshots(const std::chrono::milliseconds& timeout_ms) {
2991     auto lock = LockExclusive();
2992     if (!lock) return false;
2993 
2994     auto state = ReadUpdateState(lock.get());
2995     if (state == UpdateState::Unverified) {
2996         if (GetCurrentSlot() == Slot::Target) {
2997             LOG(ERROR) << "Cannot call MapAllSnapshots when booting from the target slot.";
2998             return false;
2999         }
3000     } else if (state != UpdateState::Initiated) {
3001         LOG(ERROR) << "Cannot call MapAllSnapshots from update state: " << state;
3002         return false;
3003     }
3004 
3005     std::vector<std::string> snapshots;
3006     if (!ListSnapshots(lock.get(), &snapshots)) {
3007         return false;
3008     }
3009 
3010     const auto& opener = device_->GetPartitionOpener();
3011     auto slot_suffix = device_->GetOtherSlotSuffix();
3012     auto slot_number = SlotNumberForSlotSuffix(slot_suffix);
3013     auto super_device = device_->GetSuperDevice(slot_number);
3014     auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot_number);
3015     if (!metadata) {
3016         LOG(ERROR) << "MapAllSnapshots could not read dynamic partition metadata for device: "
3017                    << super_device;
3018         return false;
3019     }
3020 
3021     for (const auto& snapshot : snapshots) {
3022         if (!UnmapPartitionWithSnapshot(lock.get(), snapshot)) {
3023             LOG(ERROR) << "MapAllSnapshots could not unmap snapshot: " << snapshot;
3024             return false;
3025         }
3026 
3027         CreateLogicalPartitionParams params = {
3028                 .block_device = super_device,
3029                 .metadata = metadata.get(),
3030                 .partition_name = snapshot,
3031                 .timeout_ms = timeout_ms,
3032                 .partition_opener = &opener,
3033         };
3034         if (!MapPartitionWithSnapshot(lock.get(), std::move(params), SnapshotContext::Mount,
3035                                       nullptr)) {
3036             LOG(ERROR) << "MapAllSnapshots failed to map: " << snapshot;
3037             return false;
3038         }
3039     }
3040 
3041     LOG(INFO) << "MapAllSnapshots succeeded.";
3042     return true;
3043 }
3044 
UnmapAllSnapshots()3045 bool SnapshotManager::UnmapAllSnapshots() {
3046     auto lock = LockExclusive();
3047     if (!lock) return false;
3048 
3049     return UnmapAllSnapshots(lock.get());
3050 }
3051 
UnmapAllSnapshots(LockedFile * lock)3052 bool SnapshotManager::UnmapAllSnapshots(LockedFile* lock) {
3053     LOG(INFO) << "Lock acquired for " << __FUNCTION__;
3054     std::vector<std::string> snapshots;
3055     if (!ListSnapshots(lock, &snapshots)) {
3056         return false;
3057     }
3058     LOG(INFO) << "Found " << snapshots.size() << " partitions with snapshots";
3059 
3060     for (const auto& snapshot : snapshots) {
3061         if (!UnmapPartitionWithSnapshot(lock, snapshot)) {
3062             LOG(ERROR) << "Failed to unmap snapshot: " << snapshot;
3063             return false;
3064         }
3065     }
3066     LOG(INFO) << "Unmapped " << snapshots.size() << " partitions with snapshots";
3067 
3068     // Terminate the daemon and release the snapuserd_client_ object.
3069     // If we need to re-connect with the daemon, EnsureSnapuserdConnected()
3070     // will re-create the object and establish the socket connection.
3071     if (snapuserd_client_) {
3072         LOG(INFO) << "Shutdown snapuserd daemon";
3073         snapuserd_client_->DetachSnapuserd();
3074         snapuserd_client_ = nullptr;
3075     }
3076 
3077     return true;
3078 }
3079 
OpenFile(const std::string & file,int lock_flags)3080 auto SnapshotManager::OpenFile(const std::string& file,
3081                                int lock_flags) -> std::unique_ptr<LockedFile> {
3082     const auto start = std::chrono::system_clock::now();
3083     unique_fd fd(open(file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
3084     if (fd < 0) {
3085         PLOG(ERROR) << "Open failed: " << file;
3086         return nullptr;
3087     }
3088     if (lock_flags != 0 && TEMP_FAILURE_RETRY(flock(fd, lock_flags)) < 0) {
3089         PLOG(ERROR) << "Acquire flock failed: " << file;
3090         return nullptr;
3091     }
3092     // For simplicity, we want to CHECK that lock_mode == LOCK_EX, in some
3093     // calls, so strip extra flags.
3094     int lock_mode = lock_flags & (LOCK_EX | LOCK_SH);
3095     const auto end = std::chrono::system_clock::now();
3096     const auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
3097     if (duration_ms >= 1000ms) {
3098         LOG(INFO) << "Taking lock on " << file << " took " << duration_ms.count() << "ms";
3099     }
3100     return std::make_unique<LockedFile>(file, std::move(fd), lock_mode);
3101 }
3102 
~LockedFile()3103 SnapshotManager::LockedFile::~LockedFile() {
3104     if (TEMP_FAILURE_RETRY(flock(fd_, LOCK_UN)) < 0) {
3105         PLOG(ERROR) << "Failed to unlock file: " << path_;
3106     }
3107 }
3108 
GetStateFilePath() const3109 std::string SnapshotManager::GetStateFilePath() const {
3110     return metadata_dir_ + "/state"s;
3111 }
3112 
GetMergeStateFilePath() const3113 std::string SnapshotManager::GetMergeStateFilePath() const {
3114     return metadata_dir_ + "/merge_state"s;
3115 }
3116 
GetLockPath() const3117 std::string SnapshotManager::GetLockPath() const {
3118     return metadata_dir_;
3119 }
3120 
OpenLock(int lock_flags)3121 std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::OpenLock(int lock_flags) {
3122     auto lock_file = GetLockPath();
3123     return OpenFile(lock_file, lock_flags);
3124 }
3125 
LockShared()3126 std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::LockShared() {
3127     return OpenLock(LOCK_SH);
3128 }
3129 
LockExclusive()3130 std::unique_ptr<SnapshotManager::LockedFile> SnapshotManager::LockExclusive() {
3131     return OpenLock(LOCK_EX);
3132 }
3133 
UpdateStateFromString(const std::string & contents)3134 static UpdateState UpdateStateFromString(const std::string& contents) {
3135     if (contents.empty() || contents == "none") {
3136         return UpdateState::None;
3137     } else if (contents == "initiated") {
3138         return UpdateState::Initiated;
3139     } else if (contents == "unverified") {
3140         return UpdateState::Unverified;
3141     } else if (contents == "merging") {
3142         return UpdateState::Merging;
3143     } else if (contents == "merge-completed") {
3144         return UpdateState::MergeCompleted;
3145     } else if (contents == "merge-needs-reboot") {
3146         return UpdateState::MergeNeedsReboot;
3147     } else if (contents == "merge-failed") {
3148         return UpdateState::MergeFailed;
3149     } else if (contents == "cancelled") {
3150         return UpdateState::Cancelled;
3151     } else {
3152         LOG(ERROR) << "Unknown merge state in update state file: \"" << contents << "\"";
3153         return UpdateState::None;
3154     }
3155 }
3156 
operator <<(std::ostream & os,UpdateState state)3157 std::ostream& operator<<(std::ostream& os, UpdateState state) {
3158     switch (state) {
3159         case UpdateState::None:
3160             return os << "none";
3161         case UpdateState::Initiated:
3162             return os << "initiated";
3163         case UpdateState::Unverified:
3164             return os << "unverified";
3165         case UpdateState::Merging:
3166             return os << "merging";
3167         case UpdateState::MergeCompleted:
3168             return os << "merge-completed";
3169         case UpdateState::MergeNeedsReboot:
3170             return os << "merge-needs-reboot";
3171         case UpdateState::MergeFailed:
3172             return os << "merge-failed";
3173         case UpdateState::Cancelled:
3174             return os << "cancelled";
3175         default:
3176             LOG(ERROR) << "Unknown update state: " << static_cast<uint32_t>(state);
3177             return os;
3178     }
3179 }
3180 
operator <<(std::ostream & os,MergePhase phase)3181 std::ostream& operator<<(std::ostream& os, MergePhase phase) {
3182     switch (phase) {
3183         case MergePhase::NO_MERGE:
3184             return os << "none";
3185         case MergePhase::FIRST_PHASE:
3186             return os << "first";
3187         case MergePhase::SECOND_PHASE:
3188             return os << "second";
3189         default:
3190             LOG(ERROR) << "Unknown merge phase: " << static_cast<uint32_t>(phase);
3191             return os << "unknown(" << static_cast<uint32_t>(phase) << ")";
3192     }
3193 }
3194 
ReadUpdateState(LockedFile * lock)3195 UpdateState SnapshotManager::ReadUpdateState(LockedFile* lock) {
3196     SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock);
3197     return status.state();
3198 }
3199 
ReadSnapshotUpdateStatus(LockedFile * lock)3200 SnapshotUpdateStatus SnapshotManager::ReadSnapshotUpdateStatus(LockedFile* lock) {
3201     CHECK(lock);
3202 
3203     SnapshotUpdateStatus status = {};
3204     std::string contents;
3205     if (!android::base::ReadFileToString(GetStateFilePath(), &contents)) {
3206         PLOG(ERROR) << "Read state file failed";
3207         status.set_state(UpdateState::None);
3208         return status;
3209     }
3210 
3211     if (!status.ParseFromString(contents)) {
3212         LOG(WARNING) << "Unable to parse state file as SnapshotUpdateStatus, using the old format";
3213 
3214         // Try to rollback to legacy file to support devices that are
3215         // currently using the old file format.
3216         // TODO(b/147409432)
3217         status.set_state(UpdateStateFromString(contents));
3218     }
3219 
3220     return status;
3221 }
3222 
WriteUpdateState(LockedFile * lock,UpdateState state,MergeFailureCode failure_code)3223 bool SnapshotManager::WriteUpdateState(LockedFile* lock, UpdateState state,
3224                                        MergeFailureCode failure_code) {
3225     SnapshotUpdateStatus status;
3226     status.set_state(state);
3227 
3228     switch (state) {
3229         case UpdateState::MergeFailed:
3230             status.set_merge_failure_code(failure_code);
3231             break;
3232         case UpdateState::Initiated:
3233             status.set_source_build_fingerprint(
3234                     android::base::GetProperty("ro.build.fingerprint", ""));
3235             break;
3236         default:
3237             break;
3238     }
3239 
3240     // If we're transitioning between two valid states (eg, we're not beginning
3241     // or ending an OTA), then make sure to propagate the compression bit and
3242     // build fingerprint.
3243     if (!(state == UpdateState::Initiated || state == UpdateState::None)) {
3244         SnapshotUpdateStatus old_status = ReadSnapshotUpdateStatus(lock);
3245         status.set_using_snapuserd(old_status.using_snapuserd());
3246         status.set_source_build_fingerprint(old_status.source_build_fingerprint());
3247         status.set_merge_phase(old_status.merge_phase());
3248         status.set_userspace_snapshots(old_status.userspace_snapshots());
3249         status.set_io_uring_enabled(old_status.io_uring_enabled());
3250         status.set_legacy_snapuserd(old_status.legacy_snapuserd());
3251         status.set_o_direct(old_status.o_direct());
3252         status.set_skip_verification(old_status.skip_verification());
3253         status.set_cow_op_merge_size(old_status.cow_op_merge_size());
3254         status.set_num_worker_threads(old_status.num_worker_threads());
3255         status.set_verify_block_size(old_status.verify_block_size());
3256         status.set_num_verification_threads(old_status.num_verification_threads());
3257     }
3258     return WriteSnapshotUpdateStatus(lock, status);
3259 }
3260 
WriteSnapshotUpdateStatus(LockedFile * lock,const SnapshotUpdateStatus & status)3261 bool SnapshotManager::WriteSnapshotUpdateStatus(LockedFile* lock,
3262                                                 const SnapshotUpdateStatus& status) {
3263     CHECK(lock);
3264     CHECK(lock->lock_mode() == LOCK_EX);
3265 
3266     std::string contents;
3267     if (!status.SerializeToString(&contents)) {
3268         LOG(ERROR) << "Unable to serialize SnapshotUpdateStatus.";
3269         return false;
3270     }
3271 
3272 #ifdef LIBSNAPSHOT_USE_HAL
3273     auto merge_status = MergeStatus::UNKNOWN;
3274     switch (status.state()) {
3275         // The needs-reboot and completed cases imply that /data and /metadata
3276         // can be safely wiped, so we don't report a merge status.
3277         case UpdateState::None:
3278         case UpdateState::MergeNeedsReboot:
3279         case UpdateState::MergeCompleted:
3280         case UpdateState::Initiated:
3281             merge_status = MergeStatus::NONE;
3282             break;
3283         case UpdateState::Unverified:
3284             merge_status = MergeStatus::SNAPSHOTTED;
3285             break;
3286         case UpdateState::Merging:
3287         case UpdateState::MergeFailed:
3288             merge_status = MergeStatus::MERGING;
3289             break;
3290         default:
3291             // Note that Cancelled flows to here - it is never written, since
3292             // it only communicates a transient state to the caller.
3293             LOG(ERROR) << "Unexpected update status: " << status.state();
3294             break;
3295     }
3296 
3297     bool set_before_write =
3298             merge_status == MergeStatus::SNAPSHOTTED || merge_status == MergeStatus::MERGING;
3299     if (set_before_write && !device_->SetBootControlMergeStatus(merge_status)) {
3300         return false;
3301     }
3302 #endif
3303 
3304     if (!WriteStringToFileAtomic(contents, GetStateFilePath())) {
3305         PLOG(ERROR) << "Could not write to state file";
3306         return false;
3307     }
3308 
3309 #ifdef LIBSNAPSHOT_USE_HAL
3310     if (!set_before_write && !device_->SetBootControlMergeStatus(merge_status)) {
3311         return false;
3312     }
3313 #endif
3314     return true;
3315 }
3316 
GetSnapshotStatusFilePath(const std::string & name)3317 std::string SnapshotManager::GetSnapshotStatusFilePath(const std::string& name) {
3318     auto file = metadata_dir_ + "/snapshots/"s + name;
3319     return file;
3320 }
3321 
ReadSnapshotStatus(LockedFile * lock,const std::string & name,SnapshotStatus * status)3322 bool SnapshotManager::ReadSnapshotStatus(LockedFile* lock, const std::string& name,
3323                                          SnapshotStatus* status) {
3324     CHECK(lock);
3325     auto path = GetSnapshotStatusFilePath(name);
3326 
3327     unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
3328     if (fd < 0) {
3329         PLOG(ERROR) << "Open failed: " << path;
3330         return false;
3331     }
3332 
3333     if (!status->ParseFromFileDescriptor(fd.get())) {
3334         PLOG(ERROR) << "Unable to parse " << path << " as SnapshotStatus";
3335         return false;
3336     }
3337 
3338     if (status->name() != name) {
3339         LOG(WARNING) << "Found snapshot status named " << status->name() << " in " << path;
3340         status->set_name(name);
3341     }
3342 
3343     return true;
3344 }
3345 
WriteSnapshotStatus(LockedFile * lock,const SnapshotStatus & status)3346 bool SnapshotManager::WriteSnapshotStatus(LockedFile* lock, const SnapshotStatus& status) {
3347     // The caller must take an exclusive lock to modify snapshots.
3348     CHECK(lock);
3349     CHECK(lock->lock_mode() == LOCK_EX);
3350     CHECK(!status.name().empty());
3351 
3352     auto path = GetSnapshotStatusFilePath(status.name());
3353 
3354     std::string content;
3355     if (!status.SerializeToString(&content)) {
3356         LOG(ERROR) << "Unable to serialize SnapshotStatus for " << status.name();
3357         return false;
3358     }
3359 
3360     if (!WriteStringToFileAtomic(content, path)) {
3361         PLOG(ERROR) << "Unable to write SnapshotStatus to " << path;
3362         return false;
3363     }
3364 
3365     return true;
3366 }
3367 
EnsureImageManager()3368 bool SnapshotManager::EnsureImageManager() {
3369     if (images_) return true;
3370 
3371     images_ = device_->OpenImageManager();
3372     if (!images_) {
3373         LOG(ERROR) << "Could not open ImageManager";
3374         return false;
3375     }
3376     return true;
3377 }
3378 
EnsureSnapuserdConnected(std::chrono::milliseconds timeout_ms)3379 bool SnapshotManager::EnsureSnapuserdConnected(std::chrono::milliseconds timeout_ms) {
3380     if (snapuserd_client_) {
3381         return true;
3382     }
3383 
3384     if (!use_first_stage_snapuserd_ && !EnsureSnapuserdStarted()) {
3385         return false;
3386     }
3387 
3388     snapuserd_client_ = SnapuserdClient::Connect(kSnapuserdSocket, timeout_ms);
3389     if (!snapuserd_client_) {
3390         LOG(ERROR) << "Unable to connect to snapuserd";
3391         return false;
3392     }
3393     return true;
3394 }
3395 
UnmapAndDeleteCowPartition(MetadataBuilder * current_metadata)3396 void SnapshotManager::UnmapAndDeleteCowPartition(MetadataBuilder* current_metadata) {
3397     std::vector<std::string> to_delete;
3398     for (auto* existing_cow_partition : current_metadata->ListPartitionsInGroup(kCowGroupName)) {
3399         if (!DeleteDeviceIfExists(existing_cow_partition->name())) {
3400             LOG(WARNING) << existing_cow_partition->name()
3401                          << " cannot be unmapped and its space cannot be reclaimed";
3402             continue;
3403         }
3404         to_delete.push_back(existing_cow_partition->name());
3405     }
3406     for (const auto& name : to_delete) {
3407         current_metadata->RemovePartition(name);
3408     }
3409 }
3410 
AddRequiredSpace(Return orig,const std::map<std::string,SnapshotStatus> & all_snapshot_status)3411 static Return AddRequiredSpace(Return orig,
3412                                const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
3413     if (orig.error_code() != Return::ErrorCode::NO_SPACE) {
3414         return orig;
3415     }
3416     uint64_t sum = 0;
3417     for (auto&& [name, status] : all_snapshot_status) {
3418         sum += status.cow_file_size();
3419     }
3420     LOG(INFO) << "Calculated needed COW space: " << sum << " bytes";
3421     return Return::NoSpace(sum);
3422 }
3423 
CreateUpdateSnapshots(const DeltaArchiveManifest & manifest)3424 Return SnapshotManager::CreateUpdateSnapshots(const DeltaArchiveManifest& manifest) {
3425     auto lock = LockExclusive();
3426     if (!lock) return Return::Error();
3427 
3428     auto update_state = ReadUpdateState(lock.get());
3429     if (update_state != UpdateState::Initiated) {
3430         LOG(ERROR) << "Cannot create update snapshots in state " << update_state;
3431         return Return::Error();
3432     }
3433 
3434     // TODO(b/134949511): remove this check. Right now, with overlayfs mounted, the scratch
3435     // partition takes up a big chunk of space in super, causing COW images to be created on
3436     // retrofit Virtual A/B devices.
3437     if (device_->IsOverlayfsSetup()) {
3438         LOG(ERROR) << "Cannot create update snapshots with overlayfs setup. Run `adb enable-verity`"
3439                    << ", reboot, then try again.";
3440         return Return::Error();
3441     }
3442 
3443     const auto& opener = device_->GetPartitionOpener();
3444     auto current_suffix = device_->GetSlotSuffix();
3445     uint32_t current_slot = SlotNumberForSlotSuffix(current_suffix);
3446     auto target_suffix = device_->GetOtherSlotSuffix();
3447     uint32_t target_slot = SlotNumberForSlotSuffix(target_suffix);
3448     auto current_super = device_->GetSuperDevice(current_slot);
3449 
3450     auto current_metadata = MetadataBuilder::New(opener, current_super, current_slot);
3451     if (current_metadata == nullptr) {
3452         LOG(ERROR) << "Cannot create metadata builder.";
3453         return Return::Error();
3454     }
3455 
3456     auto target_metadata =
3457             MetadataBuilder::NewForUpdate(opener, current_super, current_slot, target_slot);
3458     if (target_metadata == nullptr) {
3459         LOG(ERROR) << "Cannot create target metadata builder.";
3460         return Return::Error();
3461     }
3462 
3463     // Delete partitions with target suffix in |current_metadata|. Otherwise,
3464     // partition_cow_creator recognizes these left-over partitions as used space.
3465     for (const auto& group_name : current_metadata->ListGroups()) {
3466         if (android::base::EndsWith(group_name, target_suffix)) {
3467             current_metadata->RemoveGroupAndPartitions(group_name);
3468         }
3469     }
3470 
3471     SnapshotMetadataUpdater metadata_updater(target_metadata.get(), target_slot, manifest);
3472     if (!metadata_updater.Update()) {
3473         LOG(ERROR) << "Cannot calculate new metadata.";
3474         return Return::Error();
3475     }
3476 
3477     // Delete previous COW partitions in current_metadata so that PartitionCowCreator marks those as
3478     // free regions.
3479     UnmapAndDeleteCowPartition(current_metadata.get());
3480 
3481     // Check that all these metadata is not retrofit dynamic partitions. Snapshots on
3482     // devices with retrofit dynamic partitions does not make sense.
3483     // This ensures that current_metadata->GetFreeRegions() uses the same device
3484     // indices as target_metadata (i.e. 0 -> "super").
3485     // This is also assumed in MapCowDevices() call below.
3486     CHECK(current_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME &&
3487           target_metadata->GetBlockDevicePartitionName(0) == LP_METADATA_DEFAULT_PARTITION_NAME);
3488 
3489     const auto& dap_metadata = manifest.dynamic_partition_metadata();
3490 
3491     std::string vabc_disable_reason;
3492     if (!dap_metadata.vabc_enabled()) {
3493         vabc_disable_reason = "not enabled metadata";
3494     } else if (device_->IsRecovery()) {
3495         vabc_disable_reason = "recovery";
3496     } else if (!KernelSupportsCompressedSnapshots()) {
3497         vabc_disable_reason = "kernel missing userspace block device support";
3498     }
3499 
3500     // Deduce supported features.
3501     bool userspace_snapshots = CanUseUserspaceSnapshots();
3502     bool legacy_compression = GetLegacyCompressionEnabledProperty();
3503     bool is_legacy_snapuserd = IsVendorFromAndroid12();
3504 
3505     if (!vabc_disable_reason.empty()) {
3506         if (userspace_snapshots) {
3507             LOG(INFO) << "Userspace snapshots disabled: " << vabc_disable_reason;
3508         }
3509         if (legacy_compression) {
3510             LOG(INFO) << "Compression disabled: " << vabc_disable_reason;
3511         }
3512         userspace_snapshots = false;
3513         legacy_compression = false;
3514         is_legacy_snapuserd = false;
3515     }
3516 
3517     if (legacy_compression || userspace_snapshots) {
3518         if (dap_metadata.cow_version() < kMinCowVersion ||
3519             dap_metadata.cow_version() > kMaxCowVersion) {
3520             LOG(ERROR) << "Manifest cow version is out of bounds (got: "
3521                        << dap_metadata.cow_version() << ", min: " << kMinCowVersion
3522                        << ", max: " << kMaxCowVersion << ")";
3523             return Return::Error();
3524         }
3525     }
3526 
3527     if (!userspace_snapshots && is_legacy_snapuserd && legacy_compression) {
3528         userspace_snapshots = true;
3529         LOG(INFO) << "Vendor from Android 12. Enabling userspace snapshot for OTA install";
3530     }
3531 
3532     const bool using_snapuserd = userspace_snapshots || legacy_compression;
3533     if (!using_snapuserd) {
3534         LOG(INFO) << "Using legacy Virtual A/B (dm-snapshot)";
3535     }
3536 
3537     std::string compression_algorithm;
3538     uint64_t compression_factor{};
3539     if (using_snapuserd) {
3540         compression_algorithm = dap_metadata.vabc_compression_param();
3541         compression_factor = dap_metadata.compression_factor();
3542         if (compression_algorithm.empty()) {
3543             // Older OTAs don't set an explicit compression type, so default to gz.
3544             compression_algorithm = "gz";
3545         }
3546         LOG(INFO) << "using compression algorithm: " << compression_algorithm
3547                   << ", max compressible block size: " << compression_factor;
3548     }
3549     auto read_ahead_size =
3550             android::base::GetUintProperty<uint>("ro.virtual_ab.read_ahead_size", kReadAheadSizeKb);
3551     PartitionCowCreator cow_creator{
3552             .target_metadata = target_metadata.get(),
3553             .target_suffix = target_suffix,
3554             .target_partition = nullptr,
3555             .current_metadata = current_metadata.get(),
3556             .current_suffix = current_suffix,
3557             .update = nullptr,
3558             .extra_extents = {},
3559             .using_snapuserd = using_snapuserd,
3560             .compression_algorithm = compression_algorithm,
3561             .compression_factor = compression_factor,
3562             .read_ahead_size = read_ahead_size,
3563     };
3564 
3565     if (dap_metadata.vabc_feature_set().has_threaded()) {
3566         cow_creator.enable_threading = dap_metadata.vabc_feature_set().threaded();
3567     }
3568     if (dap_metadata.vabc_feature_set().has_batch_writes()) {
3569         cow_creator.batched_writes = dap_metadata.vabc_feature_set().batch_writes();
3570     }
3571 
3572     // In case of error, automatically delete devices that are created along the way.
3573     // Note that "lock" is destroyed after "created_devices", so it is safe to use |lock| for
3574     // these devices.
3575     AutoDeviceList created_devices;
3576     std::map<std::string, SnapshotStatus> all_snapshot_status;
3577     auto ret = CreateUpdateSnapshotsInternal(lock.get(), manifest, &cow_creator, &created_devices,
3578                                              &all_snapshot_status);
3579     if (!ret.is_ok()) {
3580         LOG(ERROR) << "CreateUpdateSnapshotsInternal failed: " << ret.string();
3581         return ret;
3582     }
3583 
3584     auto exported_target_metadata = target_metadata->Export();
3585     if (exported_target_metadata == nullptr) {
3586         LOG(ERROR) << "Cannot export target metadata";
3587         return Return::Error();
3588     }
3589 
3590     ret = InitializeUpdateSnapshots(lock.get(), dap_metadata.cow_version(), target_metadata.get(),
3591                                     exported_target_metadata.get(), target_suffix,
3592                                     all_snapshot_status);
3593     if (!ret.is_ok()) return ret;
3594 
3595     if (!UpdatePartitionTable(opener, device_->GetSuperDevice(target_slot),
3596                               *exported_target_metadata, target_slot)) {
3597         LOG(ERROR) << "Cannot write target metadata";
3598         return Return::Error();
3599     }
3600 
3601     // If snapuserd is enabled, we need to retain a copy of the old metadata
3602     // so we can access original blocks in case they are moved around. We do
3603     // not want to rely on the old super metadata slot because we don't
3604     // guarantee its validity after the slot switch is successful.
3605     if (using_snapuserd) {
3606         auto metadata = current_metadata->Export();
3607         if (!metadata) {
3608             LOG(ERROR) << "Could not export current metadata";
3609             return Return::Error();
3610         }
3611 
3612         auto path = GetOldPartitionMetadataPath();
3613         if (!android::fs_mgr::WriteToImageFile(path, *metadata.get())) {
3614             LOG(ERROR) << "Cannot write old metadata to " << path;
3615             return Return::Error();
3616         }
3617     }
3618 
3619     SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get());
3620     status.set_state(update_state);
3621     status.set_using_snapuserd(using_snapuserd);
3622 
3623     if (userspace_snapshots) {
3624         status.set_userspace_snapshots(true);
3625         LOG(INFO) << "Virtual A/B using userspace snapshots";
3626 
3627         if (GetIouringEnabledProperty()) {
3628             status.set_io_uring_enabled(true);
3629             LOG(INFO) << "io_uring for snapshots enabled";
3630         }
3631         if (GetODirectEnabledProperty()) {
3632             status.set_o_direct(true);
3633             LOG(INFO) << "o_direct for source image enabled";
3634         }
3635         if (GetSkipVerificationProperty()) {
3636             status.set_skip_verification(true);
3637             LOG(INFO) << "skipping verification of images";
3638         }
3639         if (is_legacy_snapuserd) {
3640             status.set_legacy_snapuserd(true);
3641             LOG(INFO) << "Setting legacy_snapuserd to true";
3642         }
3643         status.set_cow_op_merge_size(
3644                 android::base::GetUintProperty<uint32_t>("ro.virtual_ab.cow_op_merge_size", 0));
3645         status.set_num_worker_threads(
3646                 android::base::GetUintProperty<uint32_t>("ro.virtual_ab.num_worker_threads", 0));
3647         status.set_verify_block_size(
3648                 android::base::GetUintProperty<uint32_t>("ro.virtual_ab.verify_block_size", 0));
3649         status.set_num_verification_threads(
3650                 android::base::GetUintProperty<uint32_t>("ro.virtual_ab.num_verify_threads", 0));
3651     } else if (legacy_compression) {
3652         LOG(INFO) << "Virtual A/B using legacy snapuserd";
3653     } else {
3654         LOG(INFO) << "Virtual A/B using dm-snapshot";
3655     }
3656 
3657     is_snapshot_userspace_.emplace(userspace_snapshots);
3658     is_legacy_snapuserd_.emplace(is_legacy_snapuserd);
3659 
3660     if (!device()->IsTestDevice() && using_snapuserd) {
3661         // Terminate stale daemon if any
3662         std::unique_ptr<SnapuserdClient> snapuserd_client = std::move(snapuserd_client_);
3663         if (!snapuserd_client) {
3664             snapuserd_client = SnapuserdClient::TryConnect(kSnapuserdSocket, 5s);
3665         }
3666         if (snapuserd_client) {
3667             snapuserd_client->DetachSnapuserd();
3668             snapuserd_client = nullptr;
3669         }
3670     }
3671 
3672     if (!WriteSnapshotUpdateStatus(lock.get(), status)) {
3673         LOG(ERROR) << "Unable to write new update state";
3674         return Return::Error();
3675     }
3676 
3677     created_devices.Release();
3678     LOG(INFO) << "Successfully created all snapshots for target slot " << target_suffix;
3679 
3680     return Return::Ok();
3681 }
3682 
CreateUpdateSnapshotsInternal(LockedFile * lock,const DeltaArchiveManifest & manifest,PartitionCowCreator * cow_creator,AutoDeviceList * created_devices,std::map<std::string,SnapshotStatus> * all_snapshot_status)3683 Return SnapshotManager::CreateUpdateSnapshotsInternal(
3684         LockedFile* lock, const DeltaArchiveManifest& manifest, PartitionCowCreator* cow_creator,
3685         AutoDeviceList* created_devices,
3686         std::map<std::string, SnapshotStatus>* all_snapshot_status) {
3687     CHECK(lock);
3688 
3689     auto* target_metadata = cow_creator->target_metadata;
3690     const auto& target_suffix = cow_creator->target_suffix;
3691 
3692     if (!target_metadata->AddGroup(kCowGroupName, 0)) {
3693         LOG(ERROR) << "Cannot add group " << kCowGroupName;
3694         return Return::Error();
3695     }
3696 
3697     std::map<std::string, const PartitionUpdate*> partition_map;
3698     std::map<std::string, std::vector<Extent>> extra_extents_map;
3699     for (const auto& partition_update : manifest.partitions()) {
3700         auto suffixed_name = partition_update.partition_name() + target_suffix;
3701         auto&& [it, inserted] = partition_map.emplace(suffixed_name, &partition_update);
3702         if (!inserted) {
3703             LOG(ERROR) << "Duplicated partition " << partition_update.partition_name()
3704                        << " in update manifest.";
3705             return Return::Error();
3706         }
3707 
3708         auto& extra_extents = extra_extents_map[suffixed_name];
3709         if (partition_update.has_hash_tree_extent()) {
3710             extra_extents.push_back(partition_update.hash_tree_extent());
3711         }
3712         if (partition_update.has_fec_extent()) {
3713             extra_extents.push_back(partition_update.fec_extent());
3714         }
3715     }
3716 
3717     for (auto* target_partition : ListPartitionsWithSuffix(target_metadata, target_suffix)) {
3718         cow_creator->target_partition = target_partition;
3719         cow_creator->update = nullptr;
3720         auto iter = partition_map.find(target_partition->name());
3721         if (iter != partition_map.end()) {
3722             cow_creator->update = iter->second;
3723         } else {
3724             LOG(INFO) << target_partition->name()
3725                       << " isn't included in the payload, skipping the cow creation.";
3726             continue;
3727         }
3728 
3729         cow_creator->extra_extents.clear();
3730         auto extra_extents_it = extra_extents_map.find(target_partition->name());
3731         if (extra_extents_it != extra_extents_map.end()) {
3732             cow_creator->extra_extents = std::move(extra_extents_it->second);
3733         }
3734 
3735         // Compute the device sizes for the partition.
3736         auto cow_creator_ret = cow_creator->Run();
3737         if (!cow_creator_ret.has_value()) {
3738             LOG(ERROR) << "PartitionCowCreator returned no value for " << target_partition->name();
3739             return Return::Error();
3740         }
3741 
3742         LOG(INFO) << "For partition " << target_partition->name()
3743                   << ", device size = " << cow_creator_ret->snapshot_status.device_size()
3744                   << ", snapshot size = " << cow_creator_ret->snapshot_status.snapshot_size()
3745                   << ", cow partition size = "
3746                   << cow_creator_ret->snapshot_status.cow_partition_size()
3747                   << ", cow file size = " << cow_creator_ret->snapshot_status.cow_file_size();
3748 
3749         // Delete any existing snapshot before re-creating one.
3750         if (!DeleteSnapshot(lock, target_partition->name())) {
3751             LOG(ERROR) << "Cannot delete existing snapshot before creating a new one for partition "
3752                        << target_partition->name();
3753             return Return::Error();
3754         }
3755 
3756         // It is possible that the whole partition uses free space in super, and snapshot / COW
3757         // would not be needed. In this case, skip the partition.
3758         bool needs_snapshot = cow_creator_ret->snapshot_status.snapshot_size() > 0;
3759         bool needs_cow = (cow_creator_ret->snapshot_status.cow_partition_size() +
3760                           cow_creator_ret->snapshot_status.cow_file_size()) > 0;
3761         CHECK(needs_snapshot == needs_cow);
3762 
3763         if (!needs_snapshot) {
3764             LOG(INFO) << "Skip creating snapshot for partition " << target_partition->name()
3765                       << "because nothing needs to be snapshotted.";
3766             continue;
3767         }
3768 
3769         // Find the original partition size.
3770         auto name = target_partition->name();
3771         auto old_partition_name =
3772                 name.substr(0, name.size() - target_suffix.size()) + cow_creator->current_suffix;
3773         auto old_partition = cow_creator->current_metadata->FindPartition(old_partition_name);
3774         if (old_partition) {
3775             cow_creator_ret->snapshot_status.set_old_partition_size(old_partition->size());
3776         }
3777 
3778         // Store these device sizes to snapshot status file.
3779         if (!CreateSnapshot(lock, cow_creator, &cow_creator_ret->snapshot_status)) {
3780             return Return::Error();
3781         }
3782         created_devices->EmplaceBack<AutoDeleteSnapshot>(this, lock, target_partition->name());
3783 
3784         // Create the COW partition. That is, use any remaining free space in super partition before
3785         // creating the COW images.
3786         if (cow_creator_ret->snapshot_status.cow_partition_size() > 0) {
3787             CHECK(cow_creator_ret->snapshot_status.cow_partition_size() % kSectorSize == 0)
3788                     << "cow_partition_size == "
3789                     << cow_creator_ret->snapshot_status.cow_partition_size()
3790                     << " is not a multiple of sector size " << kSectorSize;
3791             auto cow_partition = target_metadata->AddPartition(GetCowName(target_partition->name()),
3792                                                                kCowGroupName, 0 /* flags */);
3793             if (cow_partition == nullptr) {
3794                 return Return::Error();
3795             }
3796 
3797             if (!target_metadata->ResizePartition(
3798                         cow_partition, cow_creator_ret->snapshot_status.cow_partition_size(),
3799                         cow_creator_ret->cow_partition_usable_regions)) {
3800                 LOG(ERROR) << "Cannot create COW partition on metadata with size "
3801                            << cow_creator_ret->snapshot_status.cow_partition_size();
3802                 return Return::Error();
3803             }
3804             // Only the in-memory target_metadata is modified; nothing to clean up if there is an
3805             // error in the future.
3806         }
3807 
3808         all_snapshot_status->emplace(target_partition->name(),
3809                                      std::move(cow_creator_ret->snapshot_status));
3810 
3811         LOG(INFO) << "Successfully created snapshot partition for " << target_partition->name();
3812     }
3813 
3814     LOG(INFO) << "Allocating CoW images.";
3815 
3816     for (auto&& [name, snapshot_status] : *all_snapshot_status) {
3817         // Create the backing COW image if necessary.
3818         if (snapshot_status.cow_file_size() > 0) {
3819             auto ret = CreateCowImage(lock, name);
3820             if (!ret.is_ok()) {
3821                 LOG(ERROR) << "CreateCowImage failed: " << ret.string();
3822                 return AddRequiredSpace(ret, *all_snapshot_status);
3823             }
3824         }
3825 
3826         LOG(INFO) << "Successfully created snapshot for " << name;
3827     }
3828 
3829     return Return::Ok();
3830 }
3831 
InitializeUpdateSnapshots(LockedFile * lock,uint32_t cow_version,MetadataBuilder * target_metadata,const LpMetadata * exported_target_metadata,const std::string & target_suffix,const std::map<std::string,SnapshotStatus> & all_snapshot_status)3832 Return SnapshotManager::InitializeUpdateSnapshots(
3833         LockedFile* lock, uint32_t cow_version, MetadataBuilder* target_metadata,
3834         const LpMetadata* exported_target_metadata, const std::string& target_suffix,
3835         const std::map<std::string, SnapshotStatus>& all_snapshot_status) {
3836     CHECK(lock);
3837 
3838     CreateLogicalPartitionParams cow_params{
3839             .block_device = LP_METADATA_DEFAULT_PARTITION_NAME,
3840             .metadata = exported_target_metadata,
3841             .timeout_ms = std::chrono::milliseconds::max(),
3842             .partition_opener = &device_->GetPartitionOpener(),
3843     };
3844     for (auto* target_partition : ListPartitionsWithSuffix(target_metadata, target_suffix)) {
3845         AutoDeviceList created_devices_for_cow;
3846 
3847         if (!UnmapPartitionWithSnapshot(lock, target_partition->name())) {
3848             LOG(ERROR) << "Cannot unmap existing COW devices before re-mapping them for zero-fill: "
3849                        << target_partition->name();
3850             return Return::Error();
3851         }
3852 
3853         auto it = all_snapshot_status.find(target_partition->name());
3854         if (it == all_snapshot_status.end()) continue;
3855         cow_params.partition_name = target_partition->name();
3856         std::string cow_name;
3857         if (!MapCowDevices(lock, cow_params, it->second, &created_devices_for_cow, &cow_name)) {
3858             return Return::Error();
3859         }
3860 
3861         std::string cow_path;
3862         if (!images_->GetMappedImageDevice(cow_name, &cow_path)) {
3863             LOG(ERROR) << "Cannot determine path for " << cow_name;
3864             return Return::Error();
3865         }
3866 
3867         if (!android::fs_mgr::WaitForFile(cow_path, 6s)) {
3868             LOG(ERROR) << "Timed out waiting for device to appear: " << cow_path;
3869             return Return::Error();
3870         }
3871 
3872         if (it->second.using_snapuserd()) {
3873             unique_fd fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC));
3874             if (fd < 0) {
3875                 PLOG(ERROR) << "open " << cow_path << " failed for snapshot "
3876                             << cow_params.partition_name;
3877                 return Return::Error();
3878             }
3879 
3880             CowOptions options;
3881             if (device()->IsTestDevice()) {
3882                 options.scratch_space = false;
3883             }
3884             options.compression = it->second.compression_algorithm();
3885             if (cow_version >= 3) {
3886                 options.op_count_max = it->second.estimated_ops_buffer_size();
3887                 options.max_blocks = {it->second.device_size() / options.block_size};
3888             }
3889 
3890             auto writer = CreateCowWriter(cow_version, options, std::move(fd));
3891             if (!writer->Finalize()) {
3892                 LOG(ERROR) << "Could not initialize COW device for " << target_partition->name();
3893                 return Return::Error();
3894             }
3895         } else {
3896             auto ret = InitializeKernelCow(cow_path);
3897             if (!ret.is_ok()) {
3898                 LOG(ERROR) << "Can't zero-fill COW device for " << target_partition->name() << ": "
3899                            << cow_path;
3900                 return AddRequiredSpace(ret, all_snapshot_status);
3901             }
3902         }
3903         // Let destructor of created_devices_for_cow to unmap the COW devices.
3904     };
3905     return Return::Ok();
3906 }
3907 
MapUpdateSnapshot(const CreateLogicalPartitionParams & params,std::string * snapshot_path)3908 bool SnapshotManager::MapUpdateSnapshot(const CreateLogicalPartitionParams& params,
3909                                         std::string* snapshot_path) {
3910     auto lock = LockShared();
3911     if (!lock) return false;
3912     if (!UnmapPartitionWithSnapshot(lock.get(), params.GetPartitionName())) {
3913         LOG(ERROR) << "Cannot unmap existing snapshot before re-mapping it: "
3914                    << params.GetPartitionName();
3915         return false;
3916     }
3917 
3918     SnapshotStatus status;
3919     if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) {
3920         return false;
3921     }
3922     if (status.using_snapuserd()) {
3923         LOG(ERROR) << "Cannot use MapUpdateSnapshot with snapuserd";
3924         return false;
3925     }
3926 
3927     SnapshotPaths paths;
3928     if (!MapPartitionWithSnapshot(lock.get(), params, SnapshotContext::Update, &paths)) {
3929         return false;
3930     }
3931 
3932     if (!paths.snapshot_device.empty()) {
3933         *snapshot_path = paths.snapshot_device;
3934     } else {
3935         *snapshot_path = paths.target_device;
3936     }
3937     DCHECK(!snapshot_path->empty());
3938     return true;
3939 }
3940 
OpenSnapshotWriter(const android::fs_mgr::CreateLogicalPartitionParams & params,std::optional<uint64_t> label)3941 std::unique_ptr<ICowWriter> SnapshotManager::OpenSnapshotWriter(
3942         const android::fs_mgr::CreateLogicalPartitionParams& params,
3943         std::optional<uint64_t> label) {
3944 #if defined(LIBSNAPSHOT_NO_COW_WRITE)
3945     (void)params;
3946     (void)label;
3947 
3948     LOG(ERROR) << "Snapshots cannot be written in first-stage init or recovery";
3949     return nullptr;
3950 #else
3951     // First unmap any existing mapping.
3952     auto lock = LockShared();
3953     if (!lock) return nullptr;
3954     if (!UnmapPartitionWithSnapshot(lock.get(), params.GetPartitionName())) {
3955         LOG(ERROR) << "Cannot unmap existing snapshot before re-mapping it: "
3956                    << params.GetPartitionName();
3957         return nullptr;
3958     }
3959 
3960     SnapshotPaths paths;
3961     if (!MapPartitionWithSnapshot(lock.get(), params, SnapshotContext::Update, &paths)) {
3962         return nullptr;
3963     }
3964 
3965     SnapshotStatus status;
3966     if (!paths.cow_device_name.empty()) {
3967         if (!ReadSnapshotStatus(lock.get(), params.GetPartitionName(), &status)) {
3968             return nullptr;
3969         }
3970     } else {
3971         // Currently, partition_cow_creator always creates snapshots. The
3972         // reason is that if partition X shrinks while partition Y grows, we
3973         // cannot bindly write to the newly freed extents in X. This would
3974         // make the old slot unusable. So, the entire size of the target
3975         // partition is currently considered snapshottable.
3976         LOG(ERROR) << "No snapshot available for partition " << params.GetPartitionName();
3977         return nullptr;
3978     }
3979 
3980     if (!status.using_snapuserd()) {
3981         LOG(ERROR) << "Can only create snapshot writers with userspace or compressed snapshots";
3982         return nullptr;
3983     }
3984 
3985     return OpenCompressedSnapshotWriter(lock.get(), status, paths, label);
3986 #endif
3987 }
3988 
3989 #if !defined(LIBSNAPSHOT_NO_COW_WRITE)
OpenCompressedSnapshotWriter(LockedFile * lock,const SnapshotStatus & status,const SnapshotPaths & paths,std::optional<uint64_t> label)3990 std::unique_ptr<ICowWriter> SnapshotManager::OpenCompressedSnapshotWriter(
3991         LockedFile* lock, const SnapshotStatus& status, const SnapshotPaths& paths,
3992         std::optional<uint64_t> label) {
3993     CHECK(lock);
3994 
3995     CowOptions cow_options;
3996     cow_options.compression = status.compression_algorithm();
3997     cow_options.max_blocks = {status.device_size() / cow_options.block_size};
3998     cow_options.batch_write = status.batched_writes();
3999     cow_options.num_compress_threads = status.enable_threading() ? 2 : 1;
4000     cow_options.op_count_max = status.estimated_ops_buffer_size();
4001     cow_options.compression_factor = status.compression_factor();
4002     // Disable scratch space for vts tests
4003     if (device()->IsTestDevice()) {
4004         cow_options.scratch_space = false;
4005     }
4006 
4007     // Currently we don't support partial snapshots, since partition_cow_creator
4008     // never creates this scenario.
4009     CHECK(status.snapshot_size() == status.device_size());
4010 
4011     std::string cow_path;
4012     if (!GetMappedImageDevicePath(paths.cow_device_name, &cow_path)) {
4013         LOG(ERROR) << "Could not determine path for " << paths.cow_device_name;
4014         return nullptr;
4015     }
4016 
4017     unique_fd cow_fd(open(cow_path.c_str(), O_RDWR | O_CLOEXEC));
4018     if (cow_fd < 0) {
4019         PLOG(ERROR) << "OpenCompressedSnapshotWriter: open " << cow_path;
4020         return nullptr;
4021     }
4022 
4023     CowHeaderV3 header;
4024     if (!ReadCowHeader(cow_fd, &header)) {
4025         LOG(ERROR) << "OpenCompressedSnapshotWriter: read header failed";
4026         return nullptr;
4027     }
4028 
4029     return CreateCowWriter(header.prefix.major_version, cow_options, std::move(cow_fd), label);
4030 }
4031 #endif  // !defined(LIBSNAPSHOT_NO_COW_WRITE)
4032 
UnmapUpdateSnapshot(const std::string & target_partition_name)4033 bool SnapshotManager::UnmapUpdateSnapshot(const std::string& target_partition_name) {
4034     auto lock = LockShared();
4035     if (!lock) return false;
4036     return UnmapPartitionWithSnapshot(lock.get(), target_partition_name);
4037 }
4038 
UnmapAllPartitionsInRecovery()4039 bool SnapshotManager::UnmapAllPartitionsInRecovery() {
4040     auto lock = LockExclusive();
4041     if (!lock) return false;
4042 
4043     const auto& opener = device_->GetPartitionOpener();
4044     uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
4045     auto super_device = device_->GetSuperDevice(slot);
4046     auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
4047     if (!metadata) {
4048         LOG(ERROR) << "Could not read dynamic partition metadata for device: " << super_device;
4049         return false;
4050     }
4051 
4052     bool ok = true;
4053     for (const auto& partition : metadata->partitions) {
4054         auto partition_name = GetPartitionName(partition);
4055         ok &= UnmapPartitionWithSnapshot(lock.get(), partition_name);
4056     }
4057     return ok;
4058 }
4059 
operator <<(std::ostream & os,SnapshotManager::Slot slot)4060 std::ostream& operator<<(std::ostream& os, SnapshotManager::Slot slot) {
4061     switch (slot) {
4062         case SnapshotManager::Slot::Unknown:
4063             return os << "unknown";
4064         case SnapshotManager::Slot::Source:
4065             return os << "source";
4066         case SnapshotManager::Slot::Target:
4067             return os << "target";
4068     }
4069 }
4070 
Dump(std::ostream & os)4071 bool SnapshotManager::Dump(std::ostream& os) {
4072     // Don't actually lock. Dump() is for debugging purposes only, so it is okay
4073     // if it is racy.
4074     auto file = OpenLock(0 /* lock flag */);
4075     if (!file) return false;
4076 
4077     std::stringstream ss;
4078 
4079     auto update_status = ReadSnapshotUpdateStatus(file.get());
4080 
4081     ss << "Update state: " << update_status.state() << std::endl;
4082     ss << "Using snapuserd: " << update_status.using_snapuserd() << std::endl;
4083     ss << "Using userspace snapshots: " << update_status.userspace_snapshots() << std::endl;
4084     ss << "Using io_uring: " << update_status.io_uring_enabled() << std::endl;
4085     ss << "Using o_direct: " << update_status.o_direct() << std::endl;
4086     ss << "Using skip_verification: " << update_status.skip_verification() << std::endl;
4087     ss << "Cow op merge size (0 for uncapped): " << update_status.cow_op_merge_size() << std::endl;
4088     ss << "Worker thread count: " << update_status.num_worker_threads() << std::endl;
4089     ss << "Num verification threads: " << update_status.num_verification_threads() << std::endl;
4090     ss << "Verify block size: " << update_status.verify_block_size() << std::endl;
4091     ss << "Using XOR compression: " << GetXorCompressionEnabledProperty() << std::endl;
4092     ss << "Current slot: " << device_->GetSlotSuffix() << std::endl;
4093     ss << "Boot indicator: booting from " << GetCurrentSlot() << " slot" << std::endl;
4094     ss << "Rollback indicator: "
4095        << (access(GetRollbackIndicatorPath().c_str(), F_OK) == 0 ? "exists" : strerror(errno))
4096        << std::endl;
4097     ss << "Forward merge indicator: "
4098        << (access(GetForwardMergeIndicatorPath().c_str(), F_OK) == 0 ? "exists" : strerror(errno))
4099        << std::endl;
4100     ss << "Source build fingerprint: " << update_status.source_build_fingerprint() << std::endl;
4101 
4102     if (update_status.state() == UpdateState::Merging) {
4103         ss << "Merge completion: ";
4104         if (!EnsureSnapuserdConnected()) {
4105             ss << "N/A";
4106         } else {
4107             ss << snapuserd_client_->GetMergePercent() << "%";
4108         }
4109         ss << std::endl;
4110         ss << "Merge phase: " << update_status.merge_phase() << std::endl;
4111     }
4112 
4113     bool ok = true;
4114     std::vector<std::string> snapshots;
4115     if (!ListSnapshots(file.get(), &snapshots)) {
4116         LOG(ERROR) << "Could not list snapshots";
4117         snapshots.clear();
4118         ok = false;
4119     }
4120     for (const auto& name : snapshots) {
4121         ss << "Snapshot: " << name << std::endl;
4122         SnapshotStatus status;
4123         if (!ReadSnapshotStatus(file.get(), name, &status)) {
4124             ok = false;
4125             continue;
4126         }
4127         ss << "    state: " << SnapshotState_Name(status.state()) << std::endl;
4128         ss << "    device size (bytes): " << status.device_size() << std::endl;
4129         ss << "    snapshot size (bytes): " << status.snapshot_size() << std::endl;
4130         ss << "    cow partition size (bytes): " << status.cow_partition_size() << std::endl;
4131         ss << "    cow file size (bytes): " << status.cow_file_size() << std::endl;
4132         ss << "    allocated sectors: " << status.sectors_allocated() << std::endl;
4133         ss << "    metadata sectors: " << status.metadata_sectors() << std::endl;
4134         ss << "    compression: " << status.compression_algorithm() << std::endl;
4135         ss << "    compression factor: " << status.compression_factor() << std::endl;
4136         ss << "    merge phase: " << DecideMergePhase(status) << std::endl;
4137     }
4138     os << ss.rdbuf();
4139     return ok;
4140 }
4141 
EnsureMetadataMounted()4142 std::unique_ptr<AutoDevice> SnapshotManager::EnsureMetadataMounted() {
4143     if (!device_->IsRecovery()) {
4144         // No need to mount anything in recovery.
4145         LOG(INFO) << "EnsureMetadataMounted does nothing in Android mode.";
4146         return std::unique_ptr<AutoUnmountDevice>(new AutoUnmountDevice());
4147     }
4148     auto ret = AutoUnmountDevice::New(device_->GetMetadataDir());
4149     if (ret == nullptr) return nullptr;
4150 
4151     // In rescue mode, it is possible to erase and format metadata, but /metadata/ota is not
4152     // created to execute snapshot updates. Hence, subsequent calls is likely to fail because
4153     // Lock*() fails. By failing early and returning nullptr here, update_engine_sideload can
4154     // treat this case as if /metadata is not mounted.
4155     if (!LockShared()) {
4156         LOG(WARNING) << "/metadata is mounted, but errors occur when acquiring a shared lock. "
4157                         "Subsequent calls to SnapshotManager will fail. Unmounting /metadata now.";
4158         return nullptr;
4159     }
4160     return ret;
4161 }
4162 
HandleImminentDataWipe(const std::function<void ()> & callback)4163 bool SnapshotManager::HandleImminentDataWipe(const std::function<void()>& callback) {
4164     if (!device_->IsRecovery()) {
4165         LOG(ERROR) << "Data wipes are only allowed in recovery.";
4166         return false;
4167     }
4168 
4169     auto mount = EnsureMetadataMounted();
4170     if (!mount || !mount->HasDevice()) {
4171         // We allow the wipe to continue, because if we can't mount /metadata,
4172         // it is unlikely the device would have booted anyway. If there is no
4173         // metadata partition, then the device predates Virtual A/B.
4174         LOG(INFO) << "/metadata not found; allowing wipe.";
4175         return true;
4176     }
4177 
4178     // This could happen if /metadata mounted but there is no filesystem
4179     // structure. Weird, but we have to assume there's no OTA pending, and
4180     // thus we let the wipe proceed.
4181     UpdateState state;
4182     {
4183         auto lock = LockExclusive();
4184         if (!lock) {
4185             LOG(ERROR) << "Unable to determine update state; allowing wipe.";
4186             return true;
4187         }
4188 
4189         state = ReadUpdateState(lock.get());
4190         LOG(INFO) << "Update state before wipe: " << state << "; slot: " << GetCurrentSlot()
4191                   << "; suffix: " << device_->GetSlotSuffix();
4192     }
4193 
4194     bool try_merge = false;
4195     switch (state) {
4196         case UpdateState::None:
4197         case UpdateState::Initiated:
4198             LOG(INFO) << "Wipe is not impacted by update state; allowing wipe.";
4199             break;
4200         case UpdateState::Unverified:
4201             if (GetCurrentSlot() != Slot::Target) {
4202                 LOG(INFO) << "Wipe is not impacted by rolled back update; allowing wipe";
4203                 break;
4204             }
4205             if (!HasForwardMergeIndicator()) {
4206                 auto slot_number = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
4207                 auto other_slot_number = SlotNumberForSlotSuffix(device_->GetOtherSlotSuffix());
4208 
4209                 // We're not allowed to forward merge, so forcefully rollback the
4210                 // slot switch.
4211                 LOG(INFO) << "Allowing wipe due to lack of forward merge indicator; reverting to "
4212                              "old slot since update will be deleted.";
4213                 device_->SetSlotAsUnbootable(slot_number);
4214                 device_->SetActiveBootSlot(other_slot_number);
4215                 break;
4216             }
4217 
4218             // Forward merge indicator means we have to mount snapshots and try to merge.
4219             LOG(INFO) << "Forward merge indicator is present.";
4220             try_merge = true;
4221             break;
4222         case UpdateState::Merging:
4223         case UpdateState::MergeFailed:
4224             try_merge = true;
4225             break;
4226         case UpdateState::MergeNeedsReboot:
4227         case UpdateState::Cancelled:
4228             LOG(INFO) << "Unexpected update state in recovery; allowing wipe.";
4229             break;
4230         default:
4231             break;
4232     }
4233 
4234     if (try_merge) {
4235         auto slot_number = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
4236         auto super_path = device_->GetSuperDevice(slot_number);
4237         if (!CreateLogicalAndSnapshotPartitions(super_path, 20s)) {
4238             LOG(ERROR) << "Unable to map partitions to complete merge.";
4239             return false;
4240         }
4241 
4242         auto process_callback = [&]() -> bool {
4243             if (callback) {
4244                 callback();
4245             }
4246             return true;
4247         };
4248 
4249         state = ProcessUpdateStateOnDataWipe(process_callback);
4250         if (state == UpdateState::MergeFailed) {
4251             return false;
4252         }
4253 
4254         // Nothing should be depending on partitions now, so unmap them all.
4255         if (!UnmapAllPartitionsInRecovery()) {
4256             LOG(ERROR) << "Unable to unmap all partitions; fastboot may fail to flash.";
4257         }
4258     }
4259 
4260     if (state != UpdateState::None) {
4261         auto lock = LockExclusive();
4262         if (!lock) return false;
4263 
4264         // Zap the update state so the bootloader doesn't think we're still
4265         // merging. It's okay if this fails, it's informative only at this
4266         // point.
4267         WriteUpdateState(lock.get(), UpdateState::None);
4268     }
4269     return true;
4270 }
4271 
FinishMergeInRecovery()4272 bool SnapshotManager::FinishMergeInRecovery() {
4273     if (!device_->IsRecovery()) {
4274         LOG(ERROR) << "Data wipes are only allowed in recovery.";
4275         return false;
4276     }
4277 
4278     auto mount = EnsureMetadataMounted();
4279     if (!mount || !mount->HasDevice()) {
4280         return false;
4281     }
4282 
4283     auto slot_number = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
4284     auto super_path = device_->GetSuperDevice(slot_number);
4285     if (!CreateLogicalAndSnapshotPartitions(super_path, 20s)) {
4286         LOG(ERROR) << "Unable to map partitions to complete merge.";
4287         return false;
4288     }
4289 
4290     UpdateState state = ProcessUpdateState();
4291     if (state != UpdateState::MergeCompleted) {
4292         LOG(ERROR) << "Merge returned unexpected status: " << state;
4293         return false;
4294     }
4295 
4296     // Nothing should be depending on partitions now, so unmap them all.
4297     if (!UnmapAllPartitionsInRecovery()) {
4298         LOG(ERROR) << "Unable to unmap all partitions; fastboot may fail to flash.";
4299     }
4300     return true;
4301 }
4302 
ProcessUpdateStateOnDataWipe(const std::function<bool ()> & callback)4303 UpdateState SnapshotManager::ProcessUpdateStateOnDataWipe(const std::function<bool()>& callback) {
4304     while (true) {
4305         UpdateState state = ProcessUpdateState(callback);
4306         LOG(INFO) << "Processed updated state in recovery: " << state;
4307         switch (state) {
4308             case UpdateState::MergeFailed:
4309                 LOG(ERROR) << "Unrecoverable merge failure detected.";
4310                 return state;
4311             case UpdateState::Unverified: {
4312                 // Unverified was already handled earlier, in HandleImminentDataWipe,
4313                 // but it will fall through here if a forward merge is required.
4314                 //
4315                 // If InitiateMerge fails, we early return. If it succeeds, then we
4316                 // are guaranteed that the next call to ProcessUpdateState will not
4317                 // return Unverified.
4318                 if (!InitiateMerge()) {
4319                     LOG(ERROR) << "Failed to initiate merge on data wipe.";
4320                     return UpdateState::MergeFailed;
4321                 }
4322                 continue;
4323             }
4324             case UpdateState::MergeNeedsReboot:
4325                 // We shouldn't get here, because nothing is depending on
4326                 // logical partitions.
4327                 LOG(ERROR) << "Unexpected merge-needs-reboot state in recovery.";
4328                 return state;
4329             default:
4330                 return state;
4331         }
4332     }
4333 }
4334 
HasForwardMergeIndicator()4335 bool SnapshotManager::HasForwardMergeIndicator() {
4336     return access(GetForwardMergeIndicatorPath().c_str(), F_OK) == 0;
4337 }
4338 
EnsureNoOverflowSnapshot(LockedFile * lock)4339 bool SnapshotManager::EnsureNoOverflowSnapshot(LockedFile* lock) {
4340     CHECK(lock);
4341 
4342     std::vector<std::string> snapshots;
4343     if (!ListSnapshots(lock, &snapshots)) {
4344         LOG(ERROR) << "Could not list snapshots.";
4345         return false;
4346     }
4347 
4348     for (const auto& snapshot : snapshots) {
4349         SnapshotStatus status;
4350         if (!ReadSnapshotStatus(lock, snapshot, &status)) {
4351             return false;
4352         }
4353         if (status.using_snapuserd()) {
4354             continue;
4355         }
4356 
4357         std::vector<DeviceMapper::TargetInfo> targets;
4358         if (!dm_.GetTableStatus(snapshot, &targets)) {
4359             LOG(ERROR) << "Could not read snapshot device table: " << snapshot;
4360             return false;
4361         }
4362         if (targets.size() != 1) {
4363             LOG(ERROR) << "Unexpected device-mapper table for snapshot: " << snapshot
4364                        << ", size = " << targets.size();
4365             return false;
4366         }
4367         if (targets[0].IsOverflowSnapshot()) {
4368             LOG(ERROR) << "Detected overflow in snapshot " << snapshot
4369                        << ", CoW device size computation is wrong!";
4370             return false;
4371         }
4372     }
4373 
4374     return true;
4375 }
4376 
RecoveryCreateSnapshotDevices()4377 CreateResult SnapshotManager::RecoveryCreateSnapshotDevices() {
4378     if (!device_->IsRecovery()) {
4379         LOG(ERROR) << __func__ << " is only allowed in recovery.";
4380         return CreateResult::NOT_CREATED;
4381     }
4382 
4383     auto mount = EnsureMetadataMounted();
4384     if (!mount || !mount->HasDevice()) {
4385         LOG(ERROR) << "Couldn't mount Metadata.";
4386         return CreateResult::NOT_CREATED;
4387     }
4388     return RecoveryCreateSnapshotDevices(mount);
4389 }
4390 
RecoveryCreateSnapshotDevices(const std::unique_ptr<AutoDevice> & metadata_device)4391 CreateResult SnapshotManager::RecoveryCreateSnapshotDevices(
4392         const std::unique_ptr<AutoDevice>& metadata_device) {
4393     if (!device_->IsRecovery()) {
4394         LOG(ERROR) << __func__ << " is only allowed in recovery.";
4395         return CreateResult::NOT_CREATED;
4396     }
4397 
4398     if (metadata_device == nullptr || !metadata_device->HasDevice()) {
4399         LOG(ERROR) << "Metadata not mounted.";
4400         return CreateResult::NOT_CREATED;
4401     }
4402 
4403     auto state_file = GetStateFilePath();
4404     if (access(state_file.c_str(), F_OK) != 0 && errno == ENOENT) {
4405         LOG(ERROR) << "Couldn't access state file.";
4406         return CreateResult::NOT_CREATED;
4407     }
4408 
4409     if (!NeedSnapshotsInFirstStageMount()) {
4410         return CreateResult::NOT_CREATED;
4411     }
4412 
4413     auto slot_suffix = device_->GetOtherSlotSuffix();
4414     auto slot_number = SlotNumberForSlotSuffix(slot_suffix);
4415     auto super_path = device_->GetSuperDevice(slot_number);
4416     if (!CreateLogicalAndSnapshotPartitions(super_path, 20s)) {
4417         LOG(ERROR) << "Unable to map partitions.";
4418         return CreateResult::ERROR;
4419     }
4420     return CreateResult::CREATED;
4421 }
4422 
UpdateForwardMergeIndicator(bool wipe)4423 bool SnapshotManager::UpdateForwardMergeIndicator(bool wipe) {
4424     auto path = GetForwardMergeIndicatorPath();
4425 
4426     if (!wipe) {
4427         LOG(INFO) << "Wipe is not scheduled. Deleting forward merge indicator.";
4428         return RemoveFileIfExists(path);
4429     }
4430 
4431     // TODO(b/152094219): Don't forward merge if no CoW file is allocated.
4432 
4433     LOG(INFO) << "Wipe will be scheduled. Allowing forward merge of snapshots.";
4434     if (!android::base::WriteStringToFile("1", path)) {
4435         PLOG(ERROR) << "Unable to write forward merge indicator: " << path;
4436         return false;
4437     }
4438 
4439     return true;
4440 }
4441 
GetSnapshotMergeStatsInstance()4442 ISnapshotMergeStats* SnapshotManager::GetSnapshotMergeStatsInstance() {
4443     return SnapshotMergeStats::GetInstance(*this);
4444 }
4445 
4446 // This is only to be used in recovery or normal Android (not first-stage init).
4447 // We don't guarantee dm paths are available in first-stage init, because ueventd
4448 // isn't running yet.
GetMappedImageDevicePath(const std::string & device_name,std::string * device_path)4449 bool SnapshotManager::GetMappedImageDevicePath(const std::string& device_name,
4450                                                std::string* device_path) {
4451     // Try getting the device string if it is a device mapper device.
4452     if (dm_.GetState(device_name) != DmDeviceState::INVALID) {
4453         return dm_.GetDmDevicePathByName(device_name, device_path);
4454     }
4455 
4456     // Otherwise, get path from IImageManager.
4457     return images_->GetMappedImageDevice(device_name, device_path);
4458 }
4459 
GetMappedImageDeviceStringOrPath(const std::string & device_name,std::string * device_string_or_mapped_path)4460 bool SnapshotManager::GetMappedImageDeviceStringOrPath(const std::string& device_name,
4461                                                        std::string* device_string_or_mapped_path) {
4462     // Try getting the device string if it is a device mapper device.
4463     if (dm_.GetState(device_name) != DmDeviceState::INVALID) {
4464         return dm_.GetDeviceString(device_name, device_string_or_mapped_path);
4465     }
4466 
4467     // Otherwise, get path from IImageManager.
4468     if (!images_->GetMappedImageDevice(device_name, device_string_or_mapped_path)) {
4469         return false;
4470     }
4471 
4472     LOG(WARNING) << "Calling GetMappedImageDevice with local image manager; device "
4473                  << (device_string_or_mapped_path ? *device_string_or_mapped_path : "(nullptr)")
4474                  << "may not be available in first stage init! ";
4475     return true;
4476 }
4477 
WaitForDevice(const std::string & device,std::chrono::milliseconds timeout_ms)4478 bool SnapshotManager::WaitForDevice(const std::string& device,
4479                                     std::chrono::milliseconds timeout_ms) {
4480     if (!android::base::StartsWith(device, "/")) {
4481         return true;
4482     }
4483 
4484     // In first-stage init, we rely on init setting a callback which can
4485     // regenerate uevents and populate /dev for us.
4486     if (uevent_regen_callback_) {
4487         if (!uevent_regen_callback_(device)) {
4488             LOG(ERROR) << "Failed to find device after regenerating uevents: " << device;
4489             return false;
4490         }
4491         return true;
4492     }
4493 
4494     // Otherwise, the only kind of device we need to wait for is a dm-user
4495     // misc device. Normal calls to DeviceMapper::CreateDevice() guarantee
4496     // the path has been created.
4497     if (!android::base::StartsWith(device, "/dev/dm-user/")) {
4498         return true;
4499     }
4500 
4501     if (timeout_ms.count() == 0) {
4502         LOG(ERROR) << "No timeout was specified to wait for device: " << device;
4503         return false;
4504     }
4505     if (!android::fs_mgr::WaitForFile(device, timeout_ms)) {
4506         LOG(ERROR) << "Timed out waiting for device to appear: " << device;
4507         return false;
4508     }
4509     return true;
4510 }
4511 
IsSnapuserdRequired()4512 bool SnapshotManager::IsSnapuserdRequired() {
4513     auto lock = LockExclusive();
4514     if (!lock) return false;
4515 
4516     auto status = ReadSnapshotUpdateStatus(lock.get());
4517     return status.state() != UpdateState::None && status.using_snapuserd();
4518 }
4519 
PrepareSnapuserdArgsForSelinux(std::vector<std::string> * snapuserd_argv)4520 bool SnapshotManager::PrepareSnapuserdArgsForSelinux(std::vector<std::string>* snapuserd_argv) {
4521     return PerformInitTransition(InitTransition::SELINUX_DETACH, snapuserd_argv);
4522 }
4523 
DetachFirstStageSnapuserdForSelinux()4524 bool SnapshotManager::DetachFirstStageSnapuserdForSelinux() {
4525     LOG(INFO) << "Detaching first stage snapuserd";
4526 
4527     auto lock = LockExclusive();
4528     if (!lock) return false;
4529 
4530     std::vector<std::string> snapshots;
4531     if (!ListSnapshots(lock.get(), &snapshots)) {
4532         LOG(ERROR) << "Failed to list snapshots.";
4533         return false;
4534     }
4535 
4536     size_t num_cows = 0;
4537     size_t ok_cows = 0;
4538     for (const auto& snapshot : snapshots) {
4539         std::string user_cow_name = GetDmUserCowName(snapshot, GetSnapshotDriver(lock.get()));
4540 
4541         if (dm_.GetState(user_cow_name) == DmDeviceState::INVALID) {
4542             continue;
4543         }
4544 
4545         DeviceMapper::TargetInfo target;
4546         if (!GetSingleTarget(user_cow_name, TableQuery::Table, &target)) {
4547             continue;
4548         }
4549 
4550         auto target_type = DeviceMapper::GetTargetType(target.spec);
4551         if (target_type != "user") {
4552             LOG(ERROR) << "Unexpected target type for " << user_cow_name << ": " << target_type;
4553             continue;
4554         }
4555 
4556         num_cows++;
4557         auto misc_name = user_cow_name;
4558 
4559         DmTable table;
4560         table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
4561         if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
4562             LOG(ERROR) << "Unable to swap tables for " << misc_name;
4563             continue;
4564         }
4565 
4566         // Wait for ueventd to acknowledge and create the control device node.
4567         std::string control_device = "/dev/dm-user/" + misc_name;
4568         if (!WaitForDevice(control_device, 10s)) {
4569             LOG(ERROR) << "dm-user control device no found:  " << misc_name;
4570             continue;
4571         }
4572 
4573         ok_cows++;
4574         LOG(INFO) << "control device is ready: " << control_device;
4575     }
4576 
4577     if (ok_cows != num_cows) {
4578         LOG(ERROR) << "Could not transition all snapuserd consumers.";
4579         return false;
4580     }
4581 
4582     return true;
4583 }
4584 
PerformSecondStageInitTransition()4585 bool SnapshotManager::PerformSecondStageInitTransition() {
4586     return PerformInitTransition(InitTransition::SECOND_STAGE);
4587 }
4588 
ReadOldPartitionMetadata(LockedFile * lock)4589 const LpMetadata* SnapshotManager::ReadOldPartitionMetadata(LockedFile* lock) {
4590     CHECK(lock);
4591 
4592     if (!old_partition_metadata_) {
4593         auto path = GetOldPartitionMetadataPath();
4594         old_partition_metadata_ = android::fs_mgr::ReadFromImageFile(path);
4595         if (!old_partition_metadata_) {
4596             LOG(ERROR) << "Could not read old partition metadata from " << path;
4597             return nullptr;
4598         }
4599     }
4600     return old_partition_metadata_.get();
4601 }
4602 
DecideMergePhase(const SnapshotStatus & status)4603 MergePhase SnapshotManager::DecideMergePhase(const SnapshotStatus& status) {
4604     if (status.using_snapuserd() && status.device_size() < status.old_partition_size()) {
4605         return MergePhase::FIRST_PHASE;
4606     }
4607     return MergePhase::SECOND_PHASE;
4608 }
4609 
UpdateCowStats(ISnapshotMergeStats * stats)4610 void SnapshotManager::UpdateCowStats(ISnapshotMergeStats* stats) {
4611     auto lock = LockExclusive();
4612     if (!lock) return;
4613 
4614     std::vector<std::string> snapshots;
4615     if (!ListSnapshots(lock.get(), &snapshots, GetSnapshotSlotSuffix())) {
4616         LOG(ERROR) << "Could not list snapshots";
4617         return;
4618     }
4619 
4620     uint64_t cow_file_size = 0;
4621     uint64_t total_cow_size = 0;
4622     uint64_t estimated_cow_size = 0;
4623     for (const auto& snapshot : snapshots) {
4624         SnapshotStatus status;
4625         if (!ReadSnapshotStatus(lock.get(), snapshot, &status)) {
4626             return;
4627         }
4628 
4629         cow_file_size += status.cow_file_size();
4630         total_cow_size += status.cow_file_size() + status.cow_partition_size();
4631         estimated_cow_size += status.estimated_cow_size();
4632     }
4633 
4634     stats->report()->set_cow_file_size(cow_file_size);
4635     stats->report()->set_total_cow_size_bytes(total_cow_size);
4636     stats->report()->set_estimated_cow_size_bytes(estimated_cow_size);
4637 }
4638 
SetMergeStatsFeatures(ISnapshotMergeStats * stats)4639 void SnapshotManager::SetMergeStatsFeatures(ISnapshotMergeStats* stats) {
4640     auto lock = LockExclusive();
4641     if (!lock) return;
4642 
4643     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get());
4644     stats->report()->set_iouring_used(update_status.io_uring_enabled());
4645     stats->report()->set_userspace_snapshots_used(update_status.userspace_snapshots());
4646     stats->report()->set_xor_compression_used(GetXorCompressionEnabledProperty());
4647 }
4648 
DeleteDeviceIfExists(const std::string & name,const std::chrono::milliseconds & timeout_ms)4649 bool SnapshotManager::DeleteDeviceIfExists(const std::string& name,
4650                                            const std::chrono::milliseconds& timeout_ms) {
4651     auto start = std::chrono::steady_clock::now();
4652     while (true) {
4653         if (dm_.DeleteDeviceIfExists(name)) {
4654             return true;
4655         }
4656         auto now = std::chrono::steady_clock::now();
4657         auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
4658         if (elapsed >= timeout_ms) {
4659             break;
4660         }
4661         std::this_thread::sleep_for(400ms);
4662     }
4663 
4664     // Try to diagnose why this failed. First get the actual device path.
4665     std::string full_path;
4666     if (!dm_.GetDmDevicePathByName(name, &full_path)) {
4667         LOG(ERROR) << "Unable to diagnose DM_DEV_REMOVE failure.";
4668         return false;
4669     }
4670 
4671     // Check for child dm-devices.
4672     std::string block_name = android::base::Basename(full_path);
4673     std::string sysfs_holders = "/sys/class/block/" + block_name + "/holders";
4674 
4675     std::error_code ec;
4676     std::filesystem::directory_iterator dir_iter(sysfs_holders, ec);
4677     if (auto begin = std::filesystem::begin(dir_iter); begin != std::filesystem::end(dir_iter)) {
4678         LOG(ERROR) << "Child device-mapper device still mapped: " << begin->path();
4679         return false;
4680     }
4681 
4682     // Check for mounted partitions.
4683     android::fs_mgr::Fstab fstab;
4684     android::fs_mgr::ReadFstabFromFile("/proc/mounts", &fstab);
4685     for (const auto& entry : fstab) {
4686         if (android::base::Basename(entry.blk_device) == block_name) {
4687             LOG(ERROR) << "Partition still mounted: " << entry.mount_point;
4688             return false;
4689         }
4690     }
4691 
4692     // Check for detached mounted partitions.
4693     for (const auto& fs : std::filesystem::directory_iterator("/sys/fs", ec)) {
4694         std::string fs_type = android::base::Basename(fs.path().c_str());
4695         if (!(fs_type == "ext4" || fs_type == "f2fs")) {
4696             continue;
4697         }
4698 
4699         std::string path = fs.path().c_str() + "/"s + block_name;
4700         if (access(path.c_str(), F_OK) == 0) {
4701             LOG(ERROR) << "Block device was lazily unmounted and is still in-use: " << full_path
4702                        << "; possibly open file descriptor or attached loop device.";
4703             return false;
4704         }
4705     }
4706 
4707     LOG(ERROR) << "Device-mapper device " << name << "(" << full_path << ")" << " still in use."
4708                << "  Probably a file descriptor was leaked or held open, or a loop device is"
4709                << " attached.";
4710     return false;
4711 }
4712 
ReadMergeFailureCode()4713 MergeFailureCode SnapshotManager::ReadMergeFailureCode() {
4714     auto lock = LockExclusive();
4715     if (!lock) return MergeFailureCode::AcquireLock;
4716 
4717     SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get());
4718     if (status.state() != UpdateState::MergeFailed) {
4719         return MergeFailureCode::Ok;
4720     }
4721     return status.merge_failure_code();
4722 }
4723 
ReadSourceBuildFingerprint()4724 std::string SnapshotManager::ReadSourceBuildFingerprint() {
4725     auto lock = LockExclusive();
4726     if (!lock) return {};
4727 
4728     SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get());
4729     return status.source_build_fingerprint();
4730 }
4731 
PauseSnapshotMerge()4732 bool SnapshotManager::PauseSnapshotMerge() {
4733     auto snapuserd_client = SnapuserdClient::TryConnect(kSnapuserdSocket, 5s);
4734     if (snapuserd_client) {
4735         // Pause the snapshot-merge
4736         return snapuserd_client->PauseMerge();
4737     }
4738     return false;
4739 }
4740 
ResumeSnapshotMerge()4741 bool SnapshotManager::ResumeSnapshotMerge() {
4742     auto snapuserd_client = SnapuserdClient::TryConnect(kSnapuserdSocket, 5s);
4743     if (snapuserd_client) {
4744         // Resume the snapshot-merge
4745         return snapuserd_client->ResumeMerge();
4746     }
4747     return false;
4748 }
4749 
IsUserspaceSnapshotUpdateInProgress(std::vector<std::string> & dynamic_partitions)4750 bool SnapshotManager::IsUserspaceSnapshotUpdateInProgress(
4751         std::vector<std::string>& dynamic_partitions) {
4752     // We cannot grab /metadata/ota lock here as this
4753     // is in reboot path. See b/308900853
4754     //
4755     // Check if any of the partitions are mounted
4756     // off dm-user block device. If so, then we are certain
4757     // that OTA update in progress.
4758     auto current_suffix = device_->GetSlotSuffix();
4759     auto& dm = DeviceMapper::Instance();
4760     auto dm_block_devices = dm.FindDmPartitions();
4761     if (dm_block_devices.empty()) {
4762         LOG(ERROR) << "No dm-enabled block device is found.";
4763         return false;
4764     }
4765 
4766     bool is_ota_in_progress = false;
4767     for (auto& partition : dm_block_devices) {
4768         std::string partition_name = partition.first + current_suffix;
4769         DeviceMapper::TargetInfo snap_target;
4770         if (!GetSingleTarget(partition_name, TableQuery::Status, &snap_target)) {
4771             continue;
4772         }
4773         auto type = DeviceMapper::GetTargetType(snap_target.spec);
4774         // Partition is mounted off snapshots
4775         if (type == "user") {
4776             dynamic_partitions.emplace_back("/" + partition.first);
4777             is_ota_in_progress = true;
4778         }
4779     }
4780     return is_ota_in_progress;
4781 }
4782 
BootFromSnapshotsWithoutSlotSwitch()4783 bool SnapshotManager::BootFromSnapshotsWithoutSlotSwitch() {
4784     auto lock = LockExclusive();
4785     if (!lock) return false;
4786 
4787     auto contents = device_->GetSlotSuffix();
4788     // This is the indicator which tells first-stage init
4789     // to boot from snapshots even though there was no slot-switch
4790     auto boot_file = GetBootSnapshotsWithoutSlotSwitchPath();
4791     if (!WriteStringToFileAtomic(contents, boot_file)) {
4792         PLOG(ERROR) << "write failed: " << boot_file;
4793         return false;
4794     }
4795 
4796     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get());
4797     update_status.set_state(UpdateState::Initiated);
4798     update_status.set_userspace_snapshots(true);
4799     update_status.set_using_snapuserd(true);
4800     if (!WriteSnapshotUpdateStatus(lock.get(), update_status)) {
4801         return false;
4802     }
4803     return true;
4804 }
4805 
PrepareDeviceToBootWithoutSnapshot()4806 bool SnapshotManager::PrepareDeviceToBootWithoutSnapshot() {
4807     auto lock = LockExclusive();
4808     if (!lock) return false;
4809 
4810     android::base::RemoveFileIfExists(GetSnapshotBootIndicatorPath());
4811     android::base::RemoveFileIfExists(GetBootSnapshotsWithoutSlotSwitchPath());
4812 
4813     SnapshotUpdateStatus update_status = ReadSnapshotUpdateStatus(lock.get());
4814     update_status.set_state(UpdateState::Cancelled);
4815     if (!WriteSnapshotUpdateStatus(lock.get(), update_status)) {
4816         return false;
4817     }
4818     return true;
4819 }
4820 
SetReadAheadSize(const std::string & entry_block_device,off64_t size_kb)4821 void SnapshotManager::SetReadAheadSize(const std::string& entry_block_device, off64_t size_kb) {
4822     std::string block_device;
4823     if (!Realpath(entry_block_device, &block_device)) {
4824         PLOG(ERROR) << "Failed to realpath " << entry_block_device;
4825         return;
4826     }
4827 
4828     static constexpr std::string_view kDevBlockPrefix("/dev/block/");
4829     if (!android::base::StartsWith(block_device, kDevBlockPrefix)) {
4830         LOG(ERROR) << block_device << " is not a block device";
4831         return;
4832     }
4833 
4834     std::string block_name = block_device.substr(kDevBlockPrefix.length());
4835     std::string sys_partition =
4836             android::base::StringPrintf("/sys/class/block/%s/partition", block_name.c_str());
4837     struct stat info;
4838     if (lstat(sys_partition.c_str(), &info) == 0) {
4839         block_name += "/..";
4840     }
4841     std::string sys_ra = android::base::StringPrintf("/sys/class/block/%s/queue/read_ahead_kb",
4842                                                      block_name.c_str());
4843     std::string size = std::to_string(size_kb);
4844     android::base::WriteStringToFile(size, sys_ra.c_str());
4845 }
4846 
4847 }  // namespace snapshot
4848 }  // namespace android
4849