aboutsummaryrefslogtreecommitdiffstats
path: root/install.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'install.cpp')
-rw-r--r--install.cpp141
1 files changed, 133 insertions, 8 deletions
diff --git a/install.cpp b/install.cpp
index c7d382f..c557cd0 100644
--- a/install.cpp
+++ b/install.cpp
@@ -22,6 +22,8 @@
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
+#include <setjmp.h>
+#include <sys/mount.h>
#include "common.h"
#include "install.h"
@@ -35,6 +37,8 @@
#include "verifier.h"
#include "ui.h"
+#include "cutils/properties.h"
+
extern RecoveryUI* ui;
#define ASSUMED_UPDATE_BINARY_NAME "META-INF/com/google/android/update-binary"
@@ -46,6 +50,12 @@ static const float VERIFICATION_PROGRESS_FRACTION = 0.25;
static const float DEFAULT_FILES_PROGRESS_FRACTION = 0.4;
static const float DEFAULT_IMAGE_PROGRESS_FRACTION = 0.1;
+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) {
@@ -164,9 +174,9 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache) {
} else if (strcmp(command, "ui_print") == 0) {
char* str = strtok(NULL, "\n");
if (str) {
- ui->Print("%s", str);
+ ui->PrintOnScreenOnly("%s", str);
} else {
- ui->Print("\n");
+ ui->PrintOnScreenOnly("\n");
}
fflush(stdout);
} else if (strcmp(command, "wipe_cache") == 0) {
@@ -187,21 +197,101 @@ try_update_binary(const char* path, ZipArchive* zip, bool* wipe_cache) {
int status;
waitpid(pid, &status, 0);
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. */
+ mkdir("/system", 0755);
+ 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 = 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");
+
+ free(args);
+
+ return (status > 0) ? 1 : 0;
+}
+#endif /* USE_MDTP */
+
static int
really_install_package(const char *path, bool* wipe_cache, bool needs_mount)
{
+ 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.
@@ -212,6 +302,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);
}
}
@@ -229,16 +320,31 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount)
}
LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);
+ set_perf_mode(true);
+
ui->Print("Verifying update package...\n");
int err;
- err = verify_file(map.addr, map.length, loadedKeys, numKeys);
+
+ // 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(map.addr, map.length, loadedKeys, numKeys);
+ }
+ else {
+ err = VERIFY_FAILURE;
+ }
+ signal(SIGBUS, SIG_DFL);
+
free(loadedKeys);
LOGI("verify_file returned %d\n", err);
if (err != VERIFY_SUCCESS) {
LOGE("signature verification failed\n");
sysReleaseMap(&map);
- return INSTALL_CORRUPT;
+ ret = INSTALL_CORRUPT;
+ goto out;
}
/* Try to open the package.
@@ -248,20 +354,34 @@ really_install_package(const char *path, bool* wipe_cache, bool needs_mount)
if (err != 0) {
LOGE("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
sysReleaseMap(&map);
- return INSTALL_CORRUPT;
+ ret = INSTALL_CORRUPT;
+ goto out;
}
/* Verify and install the contents of the package.
*/
ui->Print("Installing update...\n");
ui->SetEnableReboot(false);
- int result = try_update_binary(path, &zip, wipe_cache);
+ ret = try_update_binary(path, &zip, wipe_cache);
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 */
+
+out:
+ set_perf_mode(false);
+ return ret;
}
int
@@ -291,3 +411,8 @@ install_package(const char* path, bool* wipe_cache, const char* install_file,
}
return result;
}
+
+void
+set_perf_mode(bool enable) {
+ property_set("recovery.perf.mode", enable ? "1" : "0");
+}