aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTao Bao2017-07-21 17:15:31 -0500
committerTao Bao2017-07-21 19:17:03 -0500
commit5a1dee01df3af346729b5791606b72d59b8e9815 (patch)
tree323b3f45522f35b5a75ccc5a922456baa1f13f6c /update_verifier
parent9187f1cc51cc04155754d0ed34a5fc875acb9af4 (diff)
downloadplatform-bootable-recovery-5a1dee01df3af346729b5791606b72d59b8e9815.tar.gz
platform-bootable-recovery-5a1dee01df3af346729b5791606b72d59b8e9815.tar.xz
platform-bootable-recovery-5a1dee01df3af346729b5791606b72d59b8e9815.zip
update_verifier: Handle legacy care_map.txt gracefully.
update_verifier should be backward compatible to not reject legacy care_map.txt from old releases, which could otherwise fail to boot into the new release. For example, we've changed the care_map format between N and O. An O update_verifier would fail to work with an N care_map.txt - a) we have switched update_verifier to read from device mapper in O; b) the last few blocks that contain metadata can't be read via device mapper. This could be a result of sideloading an O OTA while the device having a pending N update. Bug: 63544345 Test: As follows on sailfish: 1. Flash the device with this CL; 2. Put a copy of N care_map.txt at /data/ota_package/. Restore the permissions properly ('cache' group); 3. `adb reboot bootloader`; 4. `fastboot set_active <current_slot>` 5. Device boots up into home screen, with a warning in logcat that says it has skipped legacy care_map.txt. Change-Id: I6acc88c9e655a9245e6531f176fef7953953935f
Diffstat (limited to 'update_verifier')
-rw-r--r--update_verifier/update_verifier.cpp71
1 files changed, 42 insertions, 29 deletions
diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp
index d3a5185b..b49011a1 100644
--- a/update_verifier/update_verifier.cpp
+++ b/update_verifier/update_verifier.cpp
@@ -175,40 +175,53 @@ static bool read_blocks(const std::string& partition, const std::string& range_s
175 return true; 175 return true;
176} 176}
177 177
178// Returns true to indicate a passing verification (or the error should be ignored); Otherwise
179// returns false on fatal errors, where we should reject the current boot and trigger a fallback.
180// Note that update_verifier should be backward compatible to not reject care_map.txt from old
181// releases, which could otherwise fail to boot into the new release. For example, we've changed
182// the care_map format between N and O. An O update_verifier would fail to work with N
183// care_map.txt. This could be a result of sideloading an O OTA while the device having a pending N
184// update.
178bool verify_image(const std::string& care_map_name) { 185bool verify_image(const std::string& care_map_name) {
179 android::base::unique_fd care_map_fd(TEMP_FAILURE_RETRY(open(care_map_name.c_str(), O_RDONLY))); 186 android::base::unique_fd care_map_fd(TEMP_FAILURE_RETRY(open(care_map_name.c_str(), O_RDONLY)));
180 // If the device is flashed before the current boot, it may not have care_map.txt 187 // If the device is flashed before the current boot, it may not have care_map.txt
181 // in /data/ota_package. To allow the device to continue booting in this situation, 188 // in /data/ota_package. To allow the device to continue booting in this situation,
182 // we should print a warning and skip the block verification. 189 // we should print a warning and skip the block verification.
183 if (care_map_fd.get() == -1) { 190 if (care_map_fd.get() == -1) {
184 PLOG(WARNING) << "Failed to open " << care_map_name; 191 PLOG(WARNING) << "Failed to open " << care_map_name;
185 return true; 192 return true;
186 } 193 }
187 // Care map file has four lines (two lines if vendor partition is not present): 194 // Care map file has four lines (two lines if vendor partition is not present):
188 // First line has the block partition name (system/vendor). 195 // First line has the block partition name (system/vendor).
189 // Second line holds all ranges of blocks to verify. 196 // Second line holds all ranges of blocks to verify.
190 // The next two lines have the same format but for vendor partition. 197 // The next two lines have the same format but for vendor partition.
191 std::string file_content; 198 std::string file_content;
192 if (!android::base::ReadFdToString(care_map_fd.get(), &file_content)) { 199 if (!android::base::ReadFdToString(care_map_fd.get(), &file_content)) {
193 LOG(ERROR) << "Error reading care map contents to string."; 200 LOG(ERROR) << "Error reading care map contents to string.";
194 return false; 201 return false;
195 } 202 }
196 203
197 std::vector<std::string> lines; 204 std::vector<std::string> lines;
198 lines = android::base::Split(android::base::Trim(file_content), "\n"); 205 lines = android::base::Split(android::base::Trim(file_content), "\n");
199 if (lines.size() != 2 && lines.size() != 4) { 206 if (lines.size() != 2 && lines.size() != 4) {
200 LOG(ERROR) << "Invalid lines in care_map: found " << lines.size() 207 LOG(ERROR) << "Invalid lines in care_map: found " << lines.size()
201 << " lines, expecting 2 or 4 lines."; 208 << " lines, expecting 2 or 4 lines.";
202 return false; 209 return false;
203 } 210 }
204 211
205 for (size_t i = 0; i < lines.size(); i += 2) { 212 for (size_t i = 0; i < lines.size(); i += 2) {
206 if (!read_blocks(lines[i], lines[i+1])) { 213 // We're seeing an N care_map.txt. Skip the verification since it's not compatible with O
207 return false; 214 // update_verifier (the last few metadata blocks can't be read via device mapper).
208 } 215 if (android::base::StartsWith(lines[i], "/dev/block/")) {
216 LOG(WARNING) << "Found legacy care_map.txt; skipped.";
217 return true;
218 }
219 if (!read_blocks(lines[i], lines[i+1])) {
220 return false;
209 } 221 }
222 }
210 223
211 return true; 224 return true;
212} 225}
213 226
214static int reboot_device() { 227static int reboot_device() {