1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "Checkpoint"
18 #include "Checkpoint.h"
19 #include "FsCrypt.h"
20 #include "KeyStorage.h"
21 #include "VoldUtil.h"
22 #include "VolumeManager.h"
23
24 #include <fstream>
25 #include <list>
26 #include <memory>
27 #include <string>
28 #include <thread>
29 #include <vector>
30
31 #include <BootControlClient.h>
32 #include <android-base/file.h>
33 #include <android-base/logging.h>
34 #include <android-base/parseint.h>
35 #include <android-base/properties.h>
36 #include <android-base/unique_fd.h>
37 #include <cutils/android_reboot.h>
38 #include <fcntl.h>
39 #include <fs_mgr.h>
40 #include <linux/fs.h>
41 #include <mntent.h>
42 #include <sys/mount.h>
43 #include <sys/stat.h>
44 #include <sys/statvfs.h>
45 #include <unistd.h>
46
47 using android::base::GetBoolProperty;
48 using android::base::GetUintProperty;
49 using android::base::SetProperty;
50 using android::binder::Status;
51 using android::fs_mgr::Fstab;
52 using android::fs_mgr::ReadFstabFromFile;
53 using android::hal::BootControlClient;
54
55 namespace android {
56 namespace vold {
57
58 namespace {
59 const std::string kMetadataCPFile = "/metadata/vold/checkpoint";
60
error(const std::string & msg)61 binder::Status error(const std::string& msg) {
62 PLOG(ERROR) << msg;
63 return binder::Status::fromServiceSpecificError(errno, String8(msg.c_str()));
64 }
65
error(int error,const std::string & msg)66 binder::Status error(int error, const std::string& msg) {
67 LOG(ERROR) << msg;
68 return binder::Status::fromServiceSpecificError(error, String8(msg.c_str()));
69 }
70
setBowState(std::string const & block_device,std::string const & state)71 bool setBowState(std::string const& block_device, std::string const& state) {
72 std::string bow_device = fs_mgr_find_bow_device(block_device);
73 if (bow_device.empty()) return false;
74
75 if (!android::base::WriteStringToFile(state, bow_device + "/bow/state")) {
76 PLOG(ERROR) << "Failed to write to file " << bow_device + "/bow/state";
77 return false;
78 }
79
80 return true;
81 }
82
83 // Do any work that was deferred until the userdata filesystem checkpoint was
84 // committed. This work involves the deletion of resources that aren't covered
85 // by the userdata filesystem checkpoint, e.g. Keystore keys.
DoCheckpointCommittedWork()86 void DoCheckpointCommittedWork() {
87 // Take the crypt lock to provide synchronization with the Binder calls that
88 // operate on key directories.
89 std::lock_guard<std::mutex> lock(VolumeManager::Instance()->getCryptLock());
90
91 DeferredCommitKeystoreKeys();
92 fscrypt_deferred_fixate_ce_keys();
93 }
94
95 } // namespace
96
cp_supportsCheckpoint(bool & result)97 Status cp_supportsCheckpoint(bool& result) {
98 result = false;
99
100 for (const auto& entry : fstab_default) {
101 if (entry.fs_mgr_flags.checkpoint_blk || entry.fs_mgr_flags.checkpoint_fs) {
102 result = true;
103 return Status::ok();
104 }
105 }
106 return Status::ok();
107 }
108
cp_supportsBlockCheckpoint(bool & result)109 Status cp_supportsBlockCheckpoint(bool& result) {
110 result = false;
111
112 for (const auto& entry : fstab_default) {
113 if (entry.fs_mgr_flags.checkpoint_blk) {
114 result = true;
115 return Status::ok();
116 }
117 }
118 return Status::ok();
119 }
120
cp_supportsFileCheckpoint(bool & result)121 Status cp_supportsFileCheckpoint(bool& result) {
122 result = false;
123
124 for (const auto& entry : fstab_default) {
125 if (entry.fs_mgr_flags.checkpoint_fs) {
126 result = true;
127 return Status::ok();
128 }
129 }
130 return Status::ok();
131 }
132
cp_startCheckpoint(int retry)133 Status cp_startCheckpoint(int retry) {
134 bool result;
135 if (!cp_supportsCheckpoint(result).isOk() || !result)
136 return error(ENOTSUP, "Checkpoints not supported");
137
138 if (retry < -1) return error(EINVAL, "Retry count must be more than -1");
139 std::string content;
140 if (retry == -1) {
141 content = std::to_string(-1);
142 auto module = BootControlClient::WaitForService();
143 if (module) {
144 std::string suffix = module->GetSuffix(module->GetCurrentSlot());
145 if (!suffix.empty()) content += " " + suffix;
146 }
147 } else {
148 content = std::to_string(retry + 1);
149 }
150 if (!android::base::WriteStringToFile(content, kMetadataCPFile))
151 return error("Failed to write checkpoint file");
152 return Status::ok();
153 }
154
155 namespace {
156
157 volatile bool isCheckpointing = false;
158 volatile bool isBow = true;
159
160 volatile bool needsCheckpointWasCalled = false;
161
162 // Protects isCheckpointing, needsCheckpointWasCalled and code that makes decisions based on status
163 // of isCheckpointing
164 std::mutex isCheckpointingLock;
165
166 std::mutex listenersLock;
167 std::vector<android::sp<android::system::vold::IVoldCheckpointListener>> listeners;
168 } // namespace
169
notifyCheckpointListeners()170 void notifyCheckpointListeners() {
171 std::lock_guard<std::mutex> lock(listenersLock);
172
173 for (auto& listener : listeners) {
174 listener->onCheckpointingComplete();
175 listener = nullptr;
176 }
177
178 // Reclaim vector memory; we likely won't need it again.
179 listeners = std::vector<android::sp<android::system::vold::IVoldCheckpointListener>>();
180 }
181
cp_commitChanges()182 Status cp_commitChanges() {
183 std::lock_guard<std::mutex> lock(isCheckpointingLock);
184
185 if (!isCheckpointing) {
186 return Status::ok();
187 }
188 if (android::base::GetProperty("persist.vold.dont_commit_checkpoint", "0") == "1") {
189 LOG(WARNING)
190 << "NOT COMMITTING CHECKPOINT BECAUSE persist.vold.dont_commit_checkpoint IS 1";
191 return Status::ok();
192 }
193 auto module = BootControlClient::WaitForService();
194 if (module) {
195 auto cr = module->MarkBootSuccessful();
196 if (!cr.success)
197 return error(EINVAL, "Error marking booted successfully: " + std::string(cr.errMsg));
198 LOG(INFO) << "Marked slot as booted successfully.";
199 // Clears the warm reset flag for next reboot.
200 if (!SetProperty("ota.warm_reset", "0")) {
201 LOG(WARNING) << "Failed to reset the warm reset flag";
202 }
203 } else {
204 LOG(ERROR) << "Failed to get BootControl HAL, not marking slot as successful.";
205 }
206 // Must take action for list of mounted checkpointed things here
207 // To do this, we walk the list of mounted file systems.
208 // But we also need to get the matching fstab entries to see
209 // the original flags
210 std::string err_str;
211
212 Fstab mounts;
213 if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
214 return error(EINVAL, "Failed to get /proc/mounts");
215 }
216
217 // Walk mounted file systems
218 for (const auto& mount_rec : mounts) {
219 const auto fstab_rec =
220 GetEntryForMountPoint(&fstab_default, mount_rec.mount_point, mount_rec.fs_type);
221 if (!fstab_rec) continue;
222
223 if (fstab_rec->fs_mgr_flags.checkpoint_fs) {
224 if (fstab_rec->fs_type == "f2fs") {
225 std::string options = mount_rec.fs_options + ",checkpoint=enable";
226 if (mount(mount_rec.blk_device.c_str(), mount_rec.mount_point.c_str(), "none",
227 MS_REMOUNT | fstab_rec->flags, options.c_str())) {
228 return error(EINVAL, "Failed to remount");
229 }
230 }
231 } else if (fstab_rec->fs_mgr_flags.checkpoint_blk && isBow) {
232 if (!setBowState(mount_rec.blk_device, "2"))
233 return error(EINVAL, "Failed to set bow state");
234 }
235 }
236 SetProperty("vold.checkpoint_committed", "1");
237 LOG(INFO) << "Checkpoint has been committed.";
238 isCheckpointing = false;
239 if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
240 return error(err_str.c_str());
241
242 notifyCheckpointListeners();
243
244 std::thread(DoCheckpointCommittedWork).detach();
245 return Status::ok();
246 }
247
248 namespace {
abort_metadata_file()249 void abort_metadata_file() {
250 std::string oldContent, newContent;
251 int retry = 0;
252 struct stat st;
253 int result = stat(kMetadataCPFile.c_str(), &st);
254
255 // If the file doesn't exist, we aren't managing a checkpoint retry counter
256 if (result != 0) return;
257 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent)) {
258 PLOG(ERROR) << "Failed to read checkpoint file";
259 return;
260 }
261 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
262
263 if (!android::base::ParseInt(retryContent, &retry)) {
264 PLOG(ERROR) << "Could not parse retry count";
265 return;
266 }
267 if (retry > 0) {
268 newContent = "0";
269 if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
270 PLOG(ERROR) << "Could not write checkpoint file";
271 }
272 }
273 } // namespace
274
cp_abortChanges(const std::string & message,bool retry)275 void cp_abortChanges(const std::string& message, bool retry) {
276 if (!cp_needsCheckpoint()) return;
277 if (!retry) abort_metadata_file();
278 android_reboot(ANDROID_RB_RESTART2, 0, message.c_str());
279 }
280
cp_needsRollback()281 bool cp_needsRollback() {
282 std::string content;
283 bool ret;
284
285 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
286 if (ret) {
287 if (content == "0") return true;
288 if (content.substr(0, 3) == "-1 ") {
289 std::string oldSuffix = content.substr(3);
290 auto module = BootControlClient::WaitForService();
291 std::string newSuffix;
292
293 if (module) {
294 newSuffix = module->GetSuffix(module->GetCurrentSlot());
295 if (oldSuffix == newSuffix) return true;
296 }
297 }
298 }
299 return false;
300 }
301
cp_needsCheckpoint()302 bool cp_needsCheckpoint() {
303 std::lock_guard<std::mutex> lock(isCheckpointingLock);
304
305 // Make sure we only return true during boot. See b/138952436 for discussion
306 if (needsCheckpointWasCalled) return isCheckpointing;
307 needsCheckpointWasCalled = true;
308
309 bool ret;
310 std::string content;
311 auto module = BootControlClient::WaitForService();
312
313 if (isCheckpointing) return true;
314
315 // In case of INVALID slot or other failures, we do not perform checkpoint.
316 if (module && !module->IsSlotMarkedSuccessful(module->GetCurrentSlot()).value_or(true)) {
317 isCheckpointing = true;
318 return true;
319 }
320 ret = android::base::ReadFileToString(kMetadataCPFile, &content);
321 if (ret && content != "0") {
322 isCheckpointing = true;
323 return true;
324 }
325
326 // Leave isCheckpointing false and notify listeners now that we know we don't need one
327 notifyCheckpointListeners();
328 return false;
329 }
330
cp_isCheckpointing()331 bool cp_isCheckpointing() {
332 return isCheckpointing;
333 }
334
335 namespace {
336 const std::string kSleepTimeProp = "ro.sys.cp_msleeptime";
337 const uint32_t msleeptime_default = 1000; // 1 s
338 const uint32_t max_msleeptime = 3600000; // 1 h
339
340 const std::string kMinFreeBytesProp = "ro.sys.cp_min_free_bytes";
341 const uint64_t min_free_bytes_default = 100 * (1 << 20); // 100 MiB
342
343 const std::string kCommitOnFullProp = "ro.sys.cp_commit_on_full";
344 const bool commit_on_full_default = true;
345
cp_healthDaemon(std::string mnt_pnt,std::string blk_device,bool is_fs_cp)346 static void cp_healthDaemon(std::string mnt_pnt, std::string blk_device, bool is_fs_cp) {
347 struct statvfs data;
348 uint32_t msleeptime = GetUintProperty(kSleepTimeProp, msleeptime_default, max_msleeptime);
349 uint64_t min_free_bytes =
350 GetUintProperty(kMinFreeBytesProp, min_free_bytes_default, (uint64_t)-1);
351 bool commit_on_full = GetBoolProperty(kCommitOnFullProp, commit_on_full_default);
352
353 struct timespec req;
354 req.tv_sec = msleeptime / 1000;
355 msleeptime %= 1000;
356 req.tv_nsec = msleeptime * 1000000;
357 while (isCheckpointing) {
358 uint64_t free_bytes = 0;
359 if (is_fs_cp) {
360 statvfs(mnt_pnt.c_str(), &data);
361 free_bytes = ((uint64_t) data.f_bavail) * data.f_frsize;
362 } else {
363 std::string bow_device = fs_mgr_find_bow_device(blk_device);
364 if (!bow_device.empty()) {
365 std::string content;
366 if (android::base::ReadFileToString(bow_device + "/bow/free", &content)) {
367 free_bytes = std::strtoull(content.c_str(), NULL, 10);
368 }
369 }
370 }
371 if (free_bytes < min_free_bytes) {
372 if (commit_on_full) {
373 LOG(INFO) << "Low space for checkpointing. Commiting changes";
374 cp_commitChanges();
375 break;
376 } else {
377 LOG(INFO) << "Low space for checkpointing. Rebooting";
378 cp_abortChanges("checkpoint,low_space", false);
379 break;
380 }
381 }
382 nanosleep(&req, NULL);
383 }
384 }
385
386 } // namespace
387
cp_prepareCheckpoint()388 Status cp_prepareCheckpoint() {
389 // Log to notify CTS - see b/137924328 for context
390 LOG(INFO) << "cp_prepareCheckpoint called";
391 std::lock_guard<std::mutex> lock(isCheckpointingLock);
392 if (!isCheckpointing) {
393 return Status::ok();
394 }
395
396 Fstab mounts;
397 if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
398 return error(EINVAL, "Failed to get /proc/mounts");
399 }
400
401 for (const auto& mount_rec : mounts) {
402 const auto fstab_rec = GetEntryForMountPoint(&fstab_default, mount_rec.mount_point);
403 if (!fstab_rec) continue;
404
405 if (fstab_rec->fs_mgr_flags.checkpoint_blk) {
406 android::base::unique_fd fd(
407 TEMP_FAILURE_RETRY(open(mount_rec.mount_point.c_str(), O_RDONLY | O_CLOEXEC)));
408 if (fd == -1) {
409 PLOG(ERROR) << "Failed to open mount point" << mount_rec.mount_point;
410 continue;
411 }
412
413 struct fstrim_range range = {};
414 range.len = ULLONG_MAX;
415 nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
416 if (ioctl(fd, FITRIM, &range)) {
417 PLOG(ERROR) << "Failed to trim " << mount_rec.mount_point;
418 continue;
419 }
420 nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start;
421 LOG(INFO) << "Trimmed " << range.len << " bytes on " << mount_rec.mount_point << " in "
422 << nanoseconds_to_milliseconds(time) << "ms for checkpoint";
423
424 isBow &= setBowState(mount_rec.blk_device, "1");
425 }
426 if (fstab_rec->fs_mgr_flags.checkpoint_blk || fstab_rec->fs_mgr_flags.checkpoint_fs) {
427 std::thread(cp_healthDaemon, std::string(mount_rec.mount_point),
428 std::string(mount_rec.blk_device),
429 fstab_rec->fs_mgr_flags.checkpoint_fs == 1)
430 .detach();
431 }
432 }
433 return Status::ok();
434 }
435
436 namespace {
437 const int kSectorSize = 512;
438
439 typedef uint64_t sector_t;
440
441 struct log_entry {
442 sector_t source; // in sectors of size kSectorSize
443 sector_t dest; // in sectors of size kSectorSize
444 uint32_t size; // in bytes
445 uint32_t checksum;
446 } __attribute__((packed));
447
448 struct log_sector_v1_0 {
449 uint32_t magic;
450 uint16_t header_version;
451 uint16_t header_size;
452 uint32_t block_size;
453 uint32_t count;
454 uint32_t sequence;
455 uint64_t sector0;
456 } __attribute__((packed));
457
458 // MAGIC is BOW in ascii
459 const int kMagic = 0x00574f42;
460 // Partially restored MAGIC is WOB in ascii
461 const int kPartialRestoreMagic = 0x00424f57;
462
crc32(const void * data,size_t n_bytes,uint32_t * crc)463 void crc32(const void* data, size_t n_bytes, uint32_t* crc) {
464 static uint32_t table[0x100] = {
465 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
466 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
467 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
468 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
469 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
470 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
471 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
472 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
473 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
474 0xB6662D3D,
475
476 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5,
477 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
478 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED,
479 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
480 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074,
481 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC,
482 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C,
483 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
484 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B,
485 0xC0BA6CAD,
486
487 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615,
488 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
489 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D,
490 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
491 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4,
492 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C,
493 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C,
494 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
495 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B,
496 0x5BDEAE1D,
497
498 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785,
499 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
500 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD,
501 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
502 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354,
503 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
504 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C,
505 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
506 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B,
507 0x2D02EF8D};
508
509 for (size_t i = 0; i < n_bytes; ++i) {
510 *crc ^= ((uint8_t*)data)[i];
511 *crc = table[(uint8_t)*crc] ^ *crc >> 8;
512 }
513 }
514
515 // A map of relocations.
516 // The map must be initialized so that relocations[0] = 0
517 // During restore, we replay the log records in reverse, copying from dest to
518 // source
519 // To validate, we must be able to read the 'dest' sectors as though they had
520 // been copied but without actually copying. This map represents how the sectors
521 // would have been moved. To read a sector s, find the index <= s and read
522 // relocations[index] + s - index
523 typedef std::map<sector_t, sector_t> Relocations;
524
relocate(Relocations & relocations,sector_t dest,sector_t source,int count)525 void relocate(Relocations& relocations, sector_t dest, sector_t source, int count) {
526 // Find first one we're equal to or greater than
527 auto s = --relocations.upper_bound(source);
528
529 // Take slice
530 Relocations slice;
531 slice[dest] = source - s->first + s->second;
532 ++s;
533
534 // Add rest of elements
535 for (; s != relocations.end() && s->first < source + count; ++s)
536 slice[dest - source + s->first] = s->second;
537
538 // Split range at end of dest
539 auto dest_end = --relocations.upper_bound(dest + count);
540 relocations[dest + count] = dest + count - dest_end->first + dest_end->second;
541
542 // Remove all elements in [dest, dest + count)
543 relocations.erase(relocations.lower_bound(dest), relocations.lower_bound(dest + count));
544
545 // Add new elements
546 relocations.insert(slice.begin(), slice.end());
547 }
548
549 // A map of sectors that have been written to.
550 // The final entry must always be False.
551 // When we restart the restore after an interruption, we must take care that
552 // when we copy from dest to source, that the block we copy to was not
553 // previously copied from.
554 // i e. A->B C->A; If we replay this sequence, we end up copying C->B
555 // We must save our partial result whenever we finish a page, or when we copy
556 // to a location that was copied from earlier (our source is an earlier dest)
557 typedef std::map<sector_t, bool> Used_Sectors;
558
checkCollision(Used_Sectors & used_sectors,sector_t start,sector_t end)559 bool checkCollision(Used_Sectors& used_sectors, sector_t start, sector_t end) {
560 auto second_overlap = used_sectors.upper_bound(start);
561 auto first_overlap = --second_overlap;
562
563 if (first_overlap->second) {
564 return true;
565 } else if (second_overlap != used_sectors.end() && second_overlap->first < end) {
566 return true;
567 }
568 return false;
569 }
570
markUsed(Used_Sectors & used_sectors,sector_t start,sector_t end)571 void markUsed(Used_Sectors& used_sectors, sector_t start, sector_t end) {
572 auto start_pos = used_sectors.insert_or_assign(start, true).first;
573 auto end_pos = used_sectors.insert_or_assign(end, false).first;
574
575 if (start_pos == used_sectors.begin() || !std::prev(start_pos)->second) {
576 start_pos++;
577 }
578 if (std::next(end_pos) != used_sectors.end() && !std::next(end_pos)->second) {
579 end_pos++;
580 }
581 if (start_pos->first < end_pos->first) {
582 used_sectors.erase(start_pos, end_pos);
583 }
584 }
585
586 // Restores the given log_entry's data from dest -> source
587 // If that entry is a log sector, set the magic to kPartialRestoreMagic and flush.
restoreSector(int device_fd,Used_Sectors & used_sectors,std::vector<char> & ls_buffer,log_entry * le,std::vector<char> & buffer)588 void restoreSector(int device_fd, Used_Sectors& used_sectors, std::vector<char>& ls_buffer,
589 log_entry* le, std::vector<char>& buffer) {
590 log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);
591 uint32_t index = le - ((log_entry*)&ls_buffer[ls.header_size]);
592 int count = (le->size - 1) / kSectorSize + 1;
593
594 if (checkCollision(used_sectors, le->source, le->source + count)) {
595 fsync(device_fd);
596 lseek64(device_fd, 0, SEEK_SET);
597 ls.count = index + 1;
598 ls.magic = kPartialRestoreMagic;
599 write(device_fd, &ls_buffer[0], ls.block_size);
600 fsync(device_fd);
601 used_sectors.clear();
602 used_sectors[0] = false;
603 }
604
605 markUsed(used_sectors, le->dest, le->dest + count);
606
607 if (index == 0 && ls.sequence != 0) {
608 log_sector_v1_0* next = reinterpret_cast<log_sector_v1_0*>(&buffer[0]);
609 if (next->magic == kMagic) {
610 next->magic = kPartialRestoreMagic;
611 }
612 }
613
614 lseek64(device_fd, le->source * kSectorSize, SEEK_SET);
615 write(device_fd, &buffer[0], le->size);
616
617 if (index == 0) {
618 fsync(device_fd);
619 }
620 }
621
622 // Read from the device
623 // If we are validating, the read occurs as though the relocations had happened
624 // returns the amount asked for or an empty buffer on error. Partial reads are considered a failure
relocatedRead(int device_fd,Relocations const & relocations,bool validating,sector_t sector,uint32_t size,uint32_t block_size)625 std::vector<char> relocatedRead(int device_fd, Relocations const& relocations, bool validating,
626 sector_t sector, uint32_t size, uint32_t block_size) {
627 if (!validating) {
628 std::vector<char> buffer(size);
629 off64_t offset = sector * kSectorSize;
630 if (lseek64(device_fd, offset, SEEK_SET) != offset) {
631 return std::vector<char>();
632 }
633 if (read(device_fd, &buffer[0], size) != static_cast<ssize_t>(size)) {
634 return std::vector<char>();
635 }
636 return buffer;
637 }
638
639 std::vector<char> buffer(size);
640 for (uint32_t i = 0; i < size; i += block_size, sector += block_size / kSectorSize) {
641 auto relocation = --relocations.upper_bound(sector);
642 off64_t offset = (sector + relocation->second - relocation->first) * kSectorSize;
643 if (lseek64(device_fd, offset, SEEK_SET) != offset) {
644 return std::vector<char>();
645 }
646 if (read(device_fd, &buffer[i], block_size) != static_cast<ssize_t>(block_size)) {
647 return std::vector<char>();
648 }
649 }
650
651 return buffer;
652 }
653
654 } // namespace
655
cp_restoreCheckpoint(const std::string & blockDevice,int restore_limit)656 Status cp_restoreCheckpoint(const std::string& blockDevice, int restore_limit) {
657 bool validating = true;
658 std::string action = "Validating";
659 int restore_count = 0;
660
661 for (;;) {
662 Relocations relocations;
663 relocations[0] = 0;
664 Status status = Status::ok();
665
666 LOG(INFO) << action << " checkpoint on " << blockDevice;
667 base::unique_fd device_fd(open(blockDevice.c_str(), O_RDWR | O_CLOEXEC));
668 if (device_fd < 0) return error("Cannot open " + blockDevice);
669
670 log_sector_v1_0 original_ls;
671 if (read(device_fd, reinterpret_cast<char*>(&original_ls), sizeof(original_ls)) !=
672 sizeof(original_ls)) {
673 return error(EINVAL, "Cannot read sector");
674 }
675 if (original_ls.magic == kPartialRestoreMagic) {
676 validating = false;
677 action = "Restoring";
678 } else if (original_ls.magic != kMagic) {
679 return error(EINVAL, "No magic");
680 }
681
682 if (original_ls.block_size < sizeof(log_sector_v1_0)) {
683 return error(EINVAL, "Block size is invalid");
684 }
685
686 LOG(INFO) << action << " " << original_ls.sequence << " log sectors";
687
688 for (int sequence = original_ls.sequence; sequence >= 0 && status.isOk(); sequence--) {
689 auto ls_buffer = relocatedRead(device_fd, relocations, validating, 0,
690 original_ls.block_size, original_ls.block_size);
691 if (ls_buffer.size() != original_ls.block_size) {
692 status = error(EINVAL, "Failed to read log sector");
693 break;
694 }
695 log_sector_v1_0& ls = *reinterpret_cast<log_sector_v1_0*>(&ls_buffer[0]);
696
697 Used_Sectors used_sectors;
698 used_sectors[0] = false;
699
700 if (ls.magic != kMagic && (ls.magic != kPartialRestoreMagic || validating)) {
701 status = error(EINVAL, "No magic");
702 break;
703 }
704
705 if (ls.block_size != original_ls.block_size) {
706 status = error(EINVAL, "Block size mismatch");
707 break;
708 }
709
710 if ((int)ls.sequence != sequence) {
711 status = error(EINVAL, "Expecting log sector " + std::to_string(sequence) +
712 " but got " + std::to_string(ls.sequence));
713 break;
714 }
715
716 if (ls.header_size < sizeof(log_sector_v1_0) || ls.header_size > ls.block_size) {
717 status = error(EINVAL, "Log sector header size is invalid");
718 break;
719 }
720 if (ls.count < 1 || ls.count > (ls.block_size - ls.header_size) / sizeof(log_entry)) {
721 status = error(EINVAL, "Log sector count is invalid");
722 break;
723 }
724 LOG(INFO) << action << " from log sector " << ls.sequence;
725 for (log_entry* le =
726 reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]) + ls.count - 1;
727 le >= reinterpret_cast<log_entry*>(&ls_buffer[ls.header_size]); --le) {
728 // This is very noisy - limit to DEBUG only
729 LOG(VERBOSE) << action << " " << le->size << " bytes from sector " << le->dest
730 << " to " << le->source << " with checksum " << std::hex
731 << le->checksum;
732
733 if (ls.block_size > UINT_MAX - le->size || le->size < ls.block_size) {
734 status = error(EINVAL, "log entry is invalid");
735 break;
736 }
737 auto buffer = relocatedRead(device_fd, relocations, validating, le->dest, le->size,
738 ls.block_size);
739 if (buffer.size() != le->size) {
740 status = error(EINVAL, "Failed to read sector");
741 break;
742 }
743 uint32_t checksum = le->source / (ls.block_size / kSectorSize);
744 for (size_t i = 0; i < le->size; i += ls.block_size) {
745 crc32(&buffer[i], ls.block_size, &checksum);
746 }
747
748 if (le->checksum && checksum != le->checksum) {
749 status = error(EINVAL, "Checksums don't match");
750 break;
751 }
752
753 if (validating) {
754 relocate(relocations, le->source, le->dest, (le->size - 1) / kSectorSize + 1);
755 } else {
756 restoreSector(device_fd, used_sectors, ls_buffer, le, buffer);
757 restore_count++;
758 if (restore_limit && restore_count >= restore_limit) {
759 status = error(EAGAIN, "Hit the test limit");
760 break;
761 }
762 }
763 }
764 }
765
766 if (!status.isOk()) {
767 if (!validating) {
768 LOG(ERROR) << "Checkpoint restore failed even though checkpoint validation passed";
769 return status;
770 }
771
772 LOG(WARNING) << "Checkpoint validation failed - attempting to roll forward";
773 auto buffer = relocatedRead(device_fd, relocations, false, original_ls.sector0,
774 original_ls.block_size, original_ls.block_size);
775 if (buffer.size() != original_ls.block_size) {
776 return error(EINVAL, "Failed to read original sector");
777 }
778
779 if (lseek64(device_fd, 0, SEEK_SET) != 0) {
780 return error(EINVAL, "Failed to seek to sector 0");
781 }
782 if (write(device_fd, &buffer[0], original_ls.block_size) !=
783 static_cast<ssize_t>(original_ls.block_size)) {
784 return error(EINVAL, "Failed to write original sector");
785 }
786 return Status::ok();
787 }
788
789 if (!validating) break;
790
791 validating = false;
792 action = "Restoring";
793 }
794
795 return Status::ok();
796 }
797
cp_markBootAttempt()798 Status cp_markBootAttempt() {
799 std::string oldContent, newContent;
800 int retry = 0;
801 struct stat st;
802 int result = stat(kMetadataCPFile.c_str(), &st);
803
804 // If the file doesn't exist, we aren't managing a checkpoint retry counter
805 if (result != 0) return Status::ok();
806 if (!android::base::ReadFileToString(kMetadataCPFile, &oldContent))
807 return error("Failed to read checkpoint file");
808 std::string retryContent = oldContent.substr(0, oldContent.find_first_of(" "));
809
810 if (!android::base::ParseInt(retryContent, &retry))
811 return error(EINVAL, "Could not parse retry count");
812 if (retry > 0) {
813 retry--;
814
815 newContent = std::to_string(retry);
816 if (!android::base::WriteStringToFile(newContent, kMetadataCPFile))
817 return error("Could not write checkpoint file");
818 }
819 return Status::ok();
820 }
821
cp_resetCheckpoint()822 void cp_resetCheckpoint() {
823 std::lock_guard<std::mutex> lock(isCheckpointingLock);
824 needsCheckpointWasCalled = false;
825 }
826
cp_registerCheckpointListener(android::sp<android::system::vold::IVoldCheckpointListener> listener)827 bool cp_registerCheckpointListener(
828 android::sp<android::system::vold::IVoldCheckpointListener> listener) {
829 std::lock_guard<std::mutex> checkpointGuard(isCheckpointingLock);
830 if (needsCheckpointWasCalled && !isCheckpointing) {
831 // Either checkpoint already committed or we didn't need one
832 return false;
833 }
834
835 // Either we don't know whether we need a checkpoint or we're already checkpointing,
836 // so we need to save this listener to notify later.
837 std::lock_guard<std::mutex> listenersGuard(listenersLock);
838 listeners.push_back(std::move(listener));
839 return true;
840 }
841
842 } // namespace vold
843 } // namespace android
844