aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Bao2017-07-21 14:13:15 -0500
committerTao Bao2017-07-21 15:40:56 -0500
commitec57903a7ec0bfe3c2f39dd6ee9cfc3de4ed20e6 (patch)
treea29bc14ef762d21383473758a8341d60d22de4ca /recovery.cpp
parentf7c00ddaf62a6a09ae257d193cadf286af750700 (diff)
downloadplatform-bootable-recovery-ec57903a7ec0bfe3c2f39dd6ee9cfc3de4ed20e6.tar.gz
platform-bootable-recovery-ec57903a7ec0bfe3c2f39dd6ee9cfc3de4ed20e6.tar.xz
platform-bootable-recovery-ec57903a7ec0bfe3c2f39dd6ee9cfc3de4ed20e6.zip
Avoid crashing recovery with unwritable /cache.
When /cache is unwritable, recovery hits a crash loop. Because it passes nullptr to fileno(3) when writing back the locale file. This prevents user from recovering a device - it cannot boot far enough to recovery menu which allows wiping /cache. Bug: 63927337 Test: Corrupt /cache and boot into recovery on bullhead: 1. m -j recoveryimage 2. fastboot erase cache 3. fastboot boot $OUT/recovery.img 4. recovery menu shows up. Change-Id: I1407743f802049eb48add56a36298b665cb86139
Diffstat (limited to 'recovery.cpp')
-rw-r--r--recovery.cpp48
1 files changed, 23 insertions, 25 deletions
diff --git a/recovery.cpp b/recovery.cpp
index e2d993e2..55b12d5d 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -477,40 +477,38 @@ static void copy_logs() {
477 sync(); 477 sync();
478} 478}
479 479
480// clear the recovery command and prepare to boot a (hopefully working) system, 480// Clear the recovery command and prepare to boot a (hopefully working) system,
481// copy our log file to cache as well (for the system to read). This function is 481// copy our log file to cache as well (for the system to read). This function is
482// idempotent: call it as many times as you like. 482// idempotent: call it as many times as you like.
483static void finish_recovery() { 483static void finish_recovery() {
484 // Save the locale to cache, so if recovery is next started up 484 // Save the locale to cache, so if recovery is next started up without a '--locale' argument
485 // without a --locale argument (eg, directly from the bootloader) 485 // (e.g., directly from the bootloader) it will use the last-known locale.
486 // it will use the last-known locale. 486 if (!locale.empty() && has_cache) {
487 if (!locale.empty() && has_cache) { 487 LOG(INFO) << "Saving locale \"" << locale << "\"";
488 LOG(INFO) << "Saving locale \"" << locale << "\""; 488 if (ensure_path_mounted(LOCALE_FILE) != 0) {
489 489 LOG(ERROR) << "Failed to mount " << LOCALE_FILE;
490 FILE* fp = fopen_path(LOCALE_FILE, "we"); 490 } else if (!android::base::WriteStringToFile(locale, LOCALE_FILE)) {
491 if (!android::base::WriteStringToFd(locale, fileno(fp))) { 491 PLOG(ERROR) << "Failed to save locale to " << LOCALE_FILE;
492 PLOG(ERROR) << "Failed to save locale to " << LOCALE_FILE;
493 }
494 check_and_fclose(fp, LOCALE_FILE);
495 } 492 }
493 }
496 494
497 copy_logs(); 495 copy_logs();
498 496
499 // Reset to normal system boot so recovery won't cycle indefinitely. 497 // Reset to normal system boot so recovery won't cycle indefinitely.
500 std::string err; 498 std::string err;
501 if (!clear_bootloader_message(&err)) { 499 if (!clear_bootloader_message(&err)) {
502 LOG(ERROR) << "Failed to clear BCB message: " << err; 500 LOG(ERROR) << "Failed to clear BCB message: " << err;
503 } 501 }
504 502
505 // Remove the command file, so recovery won't repeat indefinitely. 503 // Remove the command file, so recovery won't repeat indefinitely.
506 if (has_cache) { 504 if (has_cache) {
507 if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) { 505 if (ensure_path_mounted(COMMAND_FILE) != 0 || (unlink(COMMAND_FILE) && errno != ENOENT)) {
508 LOG(WARNING) << "Can't unlink " << COMMAND_FILE; 506 LOG(WARNING) << "Can't unlink " << COMMAND_FILE;
509 }
510 ensure_path_unmounted(CACHE_ROOT);
511 } 507 }
508 ensure_path_unmounted(CACHE_ROOT);
509 }
512 510
513 sync(); // For good measure. 511 sync(); // For good measure.
514} 512}
515 513
516struct saved_log_file { 514struct saved_log_file {