• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <ctype.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <inttypes.h>
21 #include <limits.h>
22 #include <string.h>
23 #include <sys/stat.h>
24 #include <sys/wait.h>
25 #include <unistd.h>
26 
27 #include <chrono>
28 #include <limits>
29 #include <map>
30 #include <string>
31 #include <vector>
32 
33 #include <android-base/parseint.h>
34 #include <android-base/stringprintf.h>
35 #include <android-base/strings.h>
36 #include <cutils/properties.h>
37 
38 #include "common.h"
39 #include "error_code.h"
40 #include "install.h"
41 #include "minui/minui.h"
42 #include "minzip/SysUtil.h"
43 #include "minzip/Zip.h"
44 #include "mtdutils/mounts.h"
45 #include "mtdutils/mtdutils.h"
46 #include "roots.h"
47 #include "ui.h"
48 #include "verifier.h"
49 
50 extern RecoveryUI* ui;
51 
52 #define ASSUMED_UPDATE_BINARY_NAME  "META-INF/com/google/android/update-binary"
53 static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt";
54 static constexpr const char* AB_OTA_PAYLOAD = "payload.bin";
55 #define PUBLIC_KEYS_FILE "/res/keys"
56 static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
57 
58 // Default allocation of progress bar segments to operations
59 static const int VERIFICATION_PROGRESS_TIME = 60;
60 static const float VERIFICATION_PROGRESS_FRACTION = 0.25;
61 static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4;
62 static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
63 
64 // This function parses and returns the build.version.incremental
parse_build_number(std::string str)65 static int parse_build_number(std::string str) {
66     size_t pos = str.find("=");
67     if (pos != std::string::npos) {
68         std::string num_string = android::base::Trim(str.substr(pos+1));
69         int build_number;
70         if (android::base::ParseInt(num_string.c_str(), &build_number, 0)) {
71             return build_number;
72         }
73     }
74 
75     LOGE("Failed to parse build number in %s.\n", str.c_str());
76     return -1;
77 }
78 
read_metadata_from_package(ZipArchive * zip,std::string * meta_data)79 bool read_metadata_from_package(ZipArchive* zip, std::string* meta_data) {
80     const ZipEntry* meta_entry = mzFindZipEntry(zip, METADATA_PATH);
81     if (meta_entry == nullptr) {
82         LOGE("Failed to find %s in update package.\n", METADATA_PATH);
83         return false;
84     }
85 
86     meta_data->resize(meta_entry->uncompLen, '\0');
87     if (!mzReadZipEntry(zip, meta_entry, &(*meta_data)[0], meta_entry->uncompLen)) {
88         LOGE("Failed to read metadata in update package.\n");
89         return false;
90     }
91     return true;
92 }
93 
94 // Read the build.version.incremental of src/tgt from the metadata and log it to last_install.
read_source_target_build(ZipArchive * zip,std::vector<std::string> & log_buffer)95 static void read_source_target_build(ZipArchive* zip, std::vector<std::string>& log_buffer) {
96     std::string meta_data;
97     if (!read_metadata_from_package(zip, &meta_data)) {
98         return;
99     }
100     // Examples of the pre-build and post-build strings in metadata:
101     // pre-build-incremental=2943039
102     // post-build-incremental=2951741
103     std::vector<std::string> lines = android::base::Split(meta_data, "\n");
104     for (const std::string& line : lines) {
105         std::string str = android::base::Trim(line);
106         if (android::base::StartsWith(str, "pre-build-incremental")){
107             int source_build = parse_build_number(str);
108             if (source_build != -1) {
109                 log_buffer.push_back(android::base::StringPrintf("source_build: %d",
110                         source_build));
111             }
112         } else if (android::base::StartsWith(str, "post-build-incremental")) {
113             int target_build = parse_build_number(str);
114             if (target_build != -1) {
115                 log_buffer.push_back(android::base::StringPrintf("target_build: %d",
116                         target_build));
117             }
118         }
119     }
120 }
121 
122 // Extract the update binary from the open zip archive |zip| located at |path|
123 // and store into |cmd| the command line that should be called. The |status_fd|
124 // is the file descriptor the child process should use to report back the
125 // progress of the update.
126 static int
127 update_binary_command(const char* path, ZipArchive* zip, int retry_count,
128                       int status_fd, std::vector<std::string>* cmd);
129 
130 #ifdef AB_OTA_UPDATER
131 
132 // Parses the metadata of the OTA package in |zip| and checks whether we are
133 // allowed to accept this A/B package. Downgrading is not allowed unless
134 // explicitly enabled in the package and only for incremental packages.
check_newer_ab_build(ZipArchive * zip)135 static int check_newer_ab_build(ZipArchive* zip)
136 {
137     std::string metadata_str;
138     if (!read_metadata_from_package(zip, &metadata_str)) {
139         return INSTALL_CORRUPT;
140     }
141     std::map<std::string, std::string> metadata;
142     for (const std::string& line : android::base::Split(metadata_str, "\n")) {
143         size_t eq = line.find('=');
144         if (eq != std::string::npos) {
145             metadata[line.substr(0, eq)] = line.substr(eq + 1);
146         }
147     }
148     char value[PROPERTY_VALUE_MAX];
149 
150     property_get("ro.product.device", value, "");
151     const std::string& pkg_device = metadata["pre-device"];
152     if (pkg_device != value || pkg_device.empty()) {
153         LOGE("Package is for product %s but expected %s\n",
154              pkg_device.c_str(), value);
155         return INSTALL_ERROR;
156     }
157 
158     // We allow the package to not have any serialno, but if it has a non-empty
159     // value it should match.
160     property_get("ro.serialno", value, "");
161     const std::string& pkg_serial_no = metadata["serialno"];
162     if (!pkg_serial_no.empty() && pkg_serial_no != value) {
163         LOGE("Package is for serial %s\n", pkg_serial_no.c_str());
164         return INSTALL_ERROR;
165     }
166 
167     if (metadata["ota-type"] != "AB") {
168         LOGE("Package is not A/B\n");
169         return INSTALL_ERROR;
170     }
171 
172     // Incremental updates should match the current build.
173     property_get("ro.build.version.incremental", value, "");
174     const std::string& pkg_pre_build = metadata["pre-build-incremental"];
175     if (!pkg_pre_build.empty() && pkg_pre_build != value) {
176         LOGE("Package is for source build %s but expected %s\n",
177              pkg_pre_build.c_str(), value);
178         return INSTALL_ERROR;
179     }
180     property_get("ro.build.fingerprint", value, "");
181     const std::string& pkg_pre_build_fingerprint = metadata["pre-build"];
182     if (!pkg_pre_build_fingerprint.empty() &&
183         pkg_pre_build_fingerprint != value) {
184         LOGE("Package is for source build %s but expected %s\n",
185              pkg_pre_build_fingerprint.c_str(), value);
186         return INSTALL_ERROR;
187     }
188 
189     // Check for downgrade version.
190     int64_t build_timestampt = property_get_int64(
191             "ro.build.date.utc", std::numeric_limits<int64_t>::max());
192     int64_t pkg_post_timespampt = 0;
193     // We allow to full update to the same version we are running, in case there
194     // is a problem with the current copy of that version.
195     if (metadata["post-timestamp"].empty() ||
196         !android::base::ParseInt(metadata["post-timestamp"].c_str(),
197                                  &pkg_post_timespampt) ||
198         pkg_post_timespampt < build_timestampt) {
199         if (metadata["ota-downgrade"] != "yes") {
200             LOGE("Update package is older than the current build, expected a "
201                  "build newer than timestamp %" PRIu64 " but package has "
202                  "timestamp %" PRIu64 " and downgrade not allowed.\n",
203                  build_timestampt, pkg_post_timespampt);
204             return INSTALL_ERROR;
205         }
206         if (pkg_pre_build_fingerprint.empty()) {
207             LOGE("Downgrade package must have a pre-build version set, not "
208                  "allowed.\n");
209             return INSTALL_ERROR;
210         }
211     }
212 
213     return 0;
214 }
215 
216 static int
update_binary_command(const char * path,ZipArchive * zip,int retry_count,int status_fd,std::vector<std::string> * cmd)217 update_binary_command(const char* path, ZipArchive* zip, int retry_count,
218                       int status_fd, std::vector<std::string>* cmd)
219 {
220     int ret = check_newer_ab_build(zip);
221     if (ret) {
222         return ret;
223     }
224 
225     // For A/B updates we extract the payload properties to a buffer and obtain
226     // the RAW payload offset in the zip file.
227     const ZipEntry* properties_entry =
228             mzFindZipEntry(zip, AB_OTA_PAYLOAD_PROPERTIES);
229     if (!properties_entry) {
230         LOGE("Can't find %s\n", AB_OTA_PAYLOAD_PROPERTIES);
231         return INSTALL_CORRUPT;
232     }
233     std::vector<unsigned char> payload_properties(
234             mzGetZipEntryUncompLen(properties_entry));
235     if (!mzExtractZipEntryToBuffer(zip, properties_entry,
236                                    payload_properties.data())) {
237         LOGE("Can't extract %s\n", AB_OTA_PAYLOAD_PROPERTIES);
238         return INSTALL_CORRUPT;
239     }
240 
241     const ZipEntry* payload_entry = mzFindZipEntry(zip, AB_OTA_PAYLOAD);
242     if (!payload_entry) {
243         LOGE("Can't find %s\n", AB_OTA_PAYLOAD);
244         return INSTALL_CORRUPT;
245     }
246     long payload_offset = mzGetZipEntryOffset(payload_entry);
247     *cmd = {
248         "/sbin/update_engine_sideload",
249         android::base::StringPrintf("--payload=file://%s", path),
250         android::base::StringPrintf("--offset=%ld", payload_offset),
251         "--headers=" + std::string(payload_properties.begin(),
252                                    payload_properties.end()),
253         android::base::StringPrintf("--status_fd=%d", status_fd),
254     };
255     return 0;
256 }
257 
258 #else  // !AB_OTA_UPDATER
259 
260 static int
update_binary_command(const char * path,ZipArchive * zip,int retry_count,int status_fd,std::vector<std::string> * cmd)261 update_binary_command(const char* path, ZipArchive* zip, int retry_count,
262                       int status_fd, std::vector<std::string>* cmd)
263 {
264     // On traditional updates we extract the update binary from the package.
265     const ZipEntry* binary_entry =
266             mzFindZipEntry(zip, ASSUMED_UPDATE_BINARY_NAME);
267     if (binary_entry == NULL) {
268         return INSTALL_CORRUPT;
269     }
270 
271     const char* binary = "/tmp/update_binary";
272     unlink(binary);
273     int fd = creat(binary, 0755);
274     if (fd < 0) {
275         LOGE("Can't make %s\n", binary);
276         return INSTALL_ERROR;
277     }
278     bool ok = mzExtractZipEntryToFile(zip, binary_entry, fd);
279     close(fd);
280 
281     if (!ok) {
282         LOGE("Can't copy %s\n", ASSUMED_UPDATE_BINARY_NAME);
283         return INSTALL_ERROR;
284     }
285 
286     *cmd = {
287         binary,
288         EXPAND(RECOVERY_API_VERSION),   // defined in Android.mk
289         std::to_string(status_fd),
290         path,
291     };
292     if (retry_count > 0)
293         cmd->push_back("retry");
294     return 0;
295 }
296 #endif  // !AB_OTA_UPDATER
297 
298 // If the package contains an update binary, extract it and run it.
299 static int
try_update_binary(const char * path,ZipArchive * zip,bool * wipe_cache,std::vector<std::string> & log_buffer,int retry_count)300 try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache,
301                   std::vector<std::string>& log_buffer, int retry_count)
302 {
303     read_source_target_build(zip, log_buffer);
304 
305     int pipefd[2];
306     pipe(pipefd);
307 
308     std::vector<std::string> args;
309     int ret = update_binary_command(path, zip, retry_count, pipefd[1], &args);
310     mzCloseZipArchive(zip);
311     if (ret) {
312         close(pipefd[0]);
313         close(pipefd[1]);
314         return ret;
315     }
316 
317     // When executing the update binary contained in the package, the
318     // arguments passed are:
319     //
320     //   - the version number for this interface
321     //
322     //   - an fd to which the program can write in order to update the
323     //     progress bar.  The program can write single-line commands:
324     //
325     //        progress <frac> <secs>
326     //            fill up the next <frac> part of of the progress bar
327     //            over <secs> seconds.  If <secs> is zero, use
328     //            set_progress commands to manually control the
329     //            progress of this segment of the bar.
330     //
331     //        set_progress <frac>
332     //            <frac> should be between 0.0 and 1.0; sets the
333     //            progress bar within the segment defined by the most
334     //            recent progress command.
335     //
336     //        firmware <"hboot"|"radio"> <filename>
337     //            arrange to install the contents of <filename> in the
338     //            given partition on reboot.
339     //
340     //            (API v2: <filename> may start with "PACKAGE:" to
341     //            indicate taking a file from the OTA package.)
342     //
343     //            (API v3: this command no longer exists.)
344     //
345     //        ui_print <string>
346     //            display <string> on the screen.
347     //
348     //        wipe_cache
349     //            a wipe of cache will be performed following a successful
350     //            installation.
351     //
352     //        clear_display
353     //            turn off the text display.
354     //
355     //        enable_reboot
356     //            packages can explicitly request that they want the user
357     //            to be able to reboot during installation (useful for
358     //            debugging packages that don't exit).
359     //
360     //   - the name of the package zip file.
361     //
362     //   - an optional argument "retry" if this update is a retry of a failed
363     //   update attempt.
364     //
365 
366     // Convert the vector to a NULL-terminated char* array suitable for execv.
367     const char* chr_args[args.size() + 1];
368     chr_args[args.size()] = NULL;
369     for (size_t i = 0; i < args.size(); i++) {
370         chr_args[i] = args[i].c_str();
371     }
372 
373     pid_t pid = fork();
374     if (pid == 0) {
375         umask(022);
376         close(pipefd[0]);
377         execv(chr_args[0], const_cast<char**>(chr_args));
378         fprintf(stdout, "E:Can't run %s (%s)\n", chr_args[0], strerror(errno));
379         _exit(-1);
380     }
381     close(pipefd[1]);
382 
383     *wipe_cache = false;
384     bool retry_update = false;
385 
386     char buffer[1024];
387     FILE* from_child = fdopen(pipefd[0], "r");
388     while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
389         char* command = strtok(buffer, " \n");
390         if (command == NULL) {
391             continue;
392         } else if (strcmp(command, "progress") == 0) {
393             char* fraction_s = strtok(NULL, " \n");
394             char* seconds_s = strtok(NULL, " \n");
395 
396             float fraction = strtof(fraction_s, NULL);
397             int seconds = strtol(seconds_s, NULL, 10);
398 
399             ui->ShowProgress(fraction * (1-VERIFICATION_PROGRESS_FRACTION), seconds);
400         } else if (strcmp(command, "set_progress") == 0) {
401             char* fraction_s = strtok(NULL, " \n");
402             float fraction = strtof(fraction_s, NULL);
403             ui->SetProgress(fraction);
404         } else if (strcmp(command, "ui_print") == 0) {
405             char* str = strtok(NULL, "\n");
406             if (str) {
407                 ui->PrintOnScreenOnly("%s", str);
408             } else {
409                 ui->PrintOnScreenOnly("\n");
410             }
411             fflush(stdout);
412         } else if (strcmp(command, "wipe_cache") == 0) {
413             *wipe_cache = true;
414         } else if (strcmp(command, "clear_display") == 0) {
415             ui->SetBackground(RecoveryUI::NONE);
416         } else if (strcmp(command, "enable_reboot") == 0) {
417             // packages can explicitly request that they want the user
418             // to be able to reboot during installation (useful for
419             // debugging packages that don't exit).
420             ui->SetEnableReboot(true);
421         } else if (strcmp(command, "retry_update") == 0) {
422             retry_update = true;
423         } else if (strcmp(command, "log") == 0) {
424             // Save the logging request from updater and write to
425             // last_install later.
426             log_buffer.push_back(std::string(strtok(NULL, "\n")));
427         } else {
428             LOGE("unknown command [%s]\n", command);
429         }
430     }
431     fclose(from_child);
432 
433     int status;
434     waitpid(pid, &status, 0);
435     if (retry_update) {
436         return INSTALL_RETRY;
437     }
438     if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
439         LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status));
440         return INSTALL_ERROR;
441     }
442 
443     return INSTALL_SUCCESS;
444 }
445 
446 static int
really_install_package(const char * path,bool * wipe_cache,bool needs_mount,std::vector<std::string> & log_buffer,int retry_count)447 really_install_package(const char *path, bool* wipe_cache, bool needs_mount,
448                        std::vector<std::string>& log_buffer, int retry_count)
449 {
450     ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
451     ui->Print("Finding update package...\n");
452     // Give verification half the progress bar...
453     ui->SetProgressType(RecoveryUI::DETERMINATE);
454     ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
455     LOGI("Update location: %s\n", path);
456 
457     // Map the update package into memory.
458     ui->Print("Opening update package...\n");
459 
460     if (path && needs_mount) {
461         if (path[0] == '@') {
462             ensure_path_mounted(path+1);
463         } else {
464             ensure_path_mounted(path);
465         }
466     }
467 
468     MemMapping map;
469     if (sysMapFile(path, &map) != 0) {
470         LOGE("failed to map file\n");
471         return INSTALL_CORRUPT;
472     }
473 
474     // Verify package.
475     if (!verify_package(map.addr, map.length)) {
476         log_buffer.push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
477         sysReleaseMap(&map);
478         return INSTALL_CORRUPT;
479     }
480 
481     // Try to open the package.
482     ZipArchive zip;
483     int err = mzOpenZipArchive(map.addr, map.length, &zip);
484     if (err != 0) {
485         LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
486         log_buffer.push_back(android::base::StringPrintf("error: %d", kZipOpenFailure));
487 
488         sysReleaseMap(&map);
489         return INSTALL_CORRUPT;
490     }
491 
492     // Verify and install the contents of the package.
493     ui->Print("Installing update...\n");
494     if (retry_count > 0) {
495         ui->Print("Retry attempt: %d\n", retry_count);
496     }
497     ui->SetEnableReboot(false);
498     int result = try_update_binary(path, &zip, wipe_cache, log_buffer, retry_count);
499     ui->SetEnableReboot(true);
500     ui->Print("\n");
501 
502     sysReleaseMap(&map);
503 
504     return result;
505 }
506 
507 int
install_package(const char * path,bool * wipe_cache,const char * install_file,bool needs_mount,int retry_count)508 install_package(const char* path, bool* wipe_cache, const char* install_file,
509                 bool needs_mount, int retry_count)
510 {
511     modified_flash = true;
512     auto start = std::chrono::system_clock::now();
513 
514     FILE* install_log = fopen_path(install_file, "w");
515     if (install_log) {
516         fputs(path, install_log);
517         fputc('\n', install_log);
518     } else {
519         LOGE("failed to open last_install: %s\n", strerror(errno));
520     }
521     int result;
522     std::vector<std::string> log_buffer;
523     if (setup_install_mounts() != 0) {
524         LOGE("failed to set up expected mounts for install; aborting\n");
525         result = INSTALL_ERROR;
526     } else {
527         result = really_install_package(path, wipe_cache, needs_mount, log_buffer, retry_count);
528     }
529     if (install_log != nullptr) {
530         fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
531         fputc('\n', install_log);
532         std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
533         int count = static_cast<int>(duration.count());
534         // Report the time spent to apply OTA update in seconds.
535         fprintf(install_log, "time_total: %d\n", count);
536         fprintf(install_log, "retry: %d\n", retry_count);
537 
538         for (const auto& s : log_buffer) {
539             fprintf(install_log, "%s\n", s.c_str());
540         }
541 
542         fclose(install_log);
543     }
544     return result;
545 }
546 
verify_package(const unsigned char * package_data,size_t package_size)547 bool verify_package(const unsigned char* package_data, size_t package_size) {
548     std::vector<Certificate> loadedKeys;
549     if (!load_keys(PUBLIC_KEYS_FILE, loadedKeys)) {
550         LOGE("Failed to load keys\n");
551         return false;
552     }
553     LOGI("%zu key(s) loaded from %s\n", loadedKeys.size(), PUBLIC_KEYS_FILE);
554 
555     // Verify package.
556     ui->Print("Verifying update package...\n");
557     auto t0 = std::chrono::system_clock::now();
558     int err = verify_file(const_cast<unsigned char*>(package_data), package_size, loadedKeys);
559     std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0;
560     ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err);
561     if (err != VERIFY_SUCCESS) {
562         LOGE("Signature verification failed\n");
563         LOGE("error: %d\n", kZipVerificationFailure);
564         return false;
565     }
566     return true;
567 }
568