aboutsummaryrefslogtreecommitdiffstats
path: root/install.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'install.cpp')
-rw-r--r--install.cpp151
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");
+}