diff options
Diffstat (limited to 'install.cpp')
-rw-r--r-- | install.cpp | 151 |
1 files changed, 143 insertions, 8 deletions
diff --git a/install.cpp b/install.cpp index d30890a9..a24ef6f1 100644 --- a/install.cpp +++ b/install.cpp @@ -23,6 +23,8 @@ #include <sys/stat.h> #include <sys/wait.h> #include <unistd.h> +#include <setjmp.h> +#include <sys/mount.h> #include <chrono> #include <limits> @@ -48,6 +50,8 @@ #include "ui.h" #include "verifier.h" +#include "cutils/properties.h" + extern RecoveryUI* ui; #define ASSUMED_UPDATE_BINARY_NAME "META-INF/com/google/android/update-binary" @@ -297,6 +301,12 @@ update_binary_command(const char* path, ZipArchive* zip, int retry_count, } #endif // !AB_OTA_UPDATER +static jmp_buf jb; +static void sig_bus(int sig) +{ + longjmp(jb, 1); +} + // If the package contains an update binary, extract it and run it. static int try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache, @@ -438,22 +448,112 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache, return INSTALL_RETRY; } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - LOGE("Error in %s\n(Status %d)\n", path, WEXITSTATUS(status)); + if (WEXITSTATUS(status) != 7) { + LOGE("Installation error in %s\n(Status %d)\n", path, WEXITSTATUS(status)); + } else { + LOGE("Failed to install %s\n", path); + LOGE("Please take note of all the above lines for reports\n"); + } return INSTALL_ERROR; } return INSTALL_SUCCESS; } +#ifdef USE_MDTP +static int +mdtp_update() +{ + const char** args = (const char**)malloc(sizeof(char*) * 2); + + if (args == NULL) { + LOGE("Failed to allocate memory for MDTP FOTA app arguments\n"); + return 0; + } + + args[0] = "/sbin/mdtp_fota"; + args[1] = NULL; + int status = 0; + + ui->Print("Running MDTP integrity verification and update...\n"); + + /* Make sure system partition is mounted, so MDTP can process its content. */ + status = mount("/dev/block/bootdevice/by-name/system", "/system", "ext4", + MS_NOATIME | MS_NODEV | MS_NODIRATIME | + MS_RDONLY, ""); + + if (status) { + LOGE("Failed to mount the system partition, error=%s.\n", strerror(errno)); + free(args); + return 0; + } + + status = mount("/dev/block/bootdevice/by-name/modem", "/firmware", "vfat", + MS_NOATIME | MS_NODEV | MS_NODIRATIME | + MS_RDONLY, ""); + + if (status) { + LOGE("Failed to mount the modem (firmware) partition, error=%s.\n", strerror(errno)); + free(args); + return 0; + } + + status = 0; + + pid_t pid = fork(); + if (pid == 0) { + execv(args[0], (char* const*)args); + LOGE("Can't run %s (%s)\n", args[0], strerror(errno)); + _exit(-1); + } + if (pid > 0) { + LOGE("Waiting for MDTP FOTA to complete...\n"); + pid = waitpid(pid, &status, 0); + LOGE("MDTP FOTA completed, status: %d\n", status); + } + + /* Leave the system partition unmounted before we finish. */ + umount("/system"); + umount("/firmware"); + + free(args); + + return (status > 0) ? 1 : 0; +} +#endif /* USE_MDTP */ + static int really_install_package(const char *path, bool* wipe_cache, bool needs_mount, std::vector<std::string>& log_buffer, int retry_count) { + int ret = 0; + ui->SetBackground(RecoveryUI::INSTALLING_UPDATE); ui->Print("Finding update package...\n"); // Give verification half the progress bar... ui->SetProgressType(RecoveryUI::DETERMINATE); ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME); + + // Resolve symlink in case legacy /sdcard path is used + // Requires: symlink uses absolute path + char new_path[PATH_MAX]; + if (strlen(path) > 1) { + char *rest = strchr(path + 1, '/'); + if (rest != NULL) { + int readlink_length; + int root_length = rest - path; + char *root = (char *)malloc(root_length + 1); + strncpy(root, path, root_length); + root[root_length] = 0; + readlink_length = readlink(root, new_path, PATH_MAX); + if (readlink_length > 0) { + strncpy(new_path + readlink_length, rest, PATH_MAX - readlink_length); + path = new_path; + } + free(root); + } + } + LOGI("Update location: %s\n", path); // Map the update package into memory. @@ -464,6 +564,7 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, ensure_path_mounted(path+1); } else { ensure_path_mounted(path); + remount_no_selinux(path); } } @@ -473,10 +574,13 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, return INSTALL_CORRUPT; } + set_perf_mode(true); + // Verify package. if (!verify_package(map.addr, map.length)) { log_buffer.push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure)); sysReleaseMap(&map); + set_perf_mode(false); return INSTALL_CORRUPT; } @@ -488,6 +592,7 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, log_buffer.push_back(android::base::StringPrintf("error: %d", kZipOpenFailure)); sysReleaseMap(&map); + set_perf_mode(false); return INSTALL_CORRUPT; } @@ -497,13 +602,25 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount, ui->Print("Retry attempt: %d\n", retry_count); } ui->SetEnableReboot(false); - int result = try_update_binary(path, &zip, wipe_cache, log_buffer, retry_count); + ret = try_update_binary(path, &zip, wipe_cache, log_buffer, retry_count); ui->SetEnableReboot(true); ui->Print("\n"); sysReleaseMap(&map); - return result; +#ifdef USE_MDTP + /* If MDTP update failed, return an error such that recovery will not finish. */ + if (ret == INSTALL_SUCCESS) { + if (!mdtp_update()) { + ui->Print("Unable to verify integrity of /system for MDTP, update aborted.\n"); + return INSTALL_ERROR; + } + ui->Print("Successfully verified integrity of /system for MDTP.\n"); + } +#endif /* USE_MDTP */ + + set_perf_mode(false); + return ret; } int @@ -513,9 +630,11 @@ install_package(const char* path, bool* wipe_cache, const char* install_file, modified_flash = true; auto start = std::chrono::system_clock::now(); - int result; + int result = 0; std::vector<std::string> log_buffer; - if (setup_install_mounts() != 0) { + if (needs_mount == true) + result = setup_install_mounts(); + if (result != 0) { LOGE("failed to set up expected mounts for install; aborting\n"); result = INSTALL_ERROR; } else { @@ -569,9 +688,20 @@ bool verify_package(const unsigned char* package_data, size_t package_size) { // Verify package. ui->Print("Verifying update package...\n"); auto t0 = std::chrono::system_clock::now(); - int err = verify_file(const_cast<unsigned char*>(package_data), package_size, loadedKeys); - std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0; - ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err); + int err; + + // Because we mmap() the update file which is backed by FUSE, we get + // SIGBUS when the host aborts the transfer. We handle this by using + // setjmp/longjmp. + signal(SIGBUS, sig_bus); + if (setjmp(jb) == 0) { + err = verify_file(const_cast<unsigned char*>(package_data), package_size, loadedKeys); + std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0; + ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err); + } else { + err = VERIFY_FAILURE; + } + signal(SIGBUS, SIG_DFL); if (err != VERIFY_SUCCESS) { LOGE("Signature verification failed\n"); LOGE("error: %d\n", kZipVerificationFailure); @@ -579,3 +709,8 @@ bool verify_package(const unsigned char* package_data, size_t package_size) { } return true; } + +void +set_perf_mode(bool enable) { + property_set("recovery.perf.mode", enable ? "1" : "0"); +} |