recovery: Add support for MDTP

Mobile Device Theft Protection prevents unauthorized modification
of the system image, ensuring existing of an Anti-Theft solution.

During FOTA, the baseline of the system image which is stored in
a dedicated DIP partition (Device Integrity Partition) is updated
with the baseline of the new received system image.

CRs-fixed: 777015
Change-Id: Ib2ff4bb16db5a08e69432ef3d6d7af26a447dea5
diff --git a/install.cpp b/install.cpp
index 5a439a1..0860d85 100644
--- a/install.cpp
+++ b/install.cpp
@@ -22,6 +22,7 @@
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <sys/mount.h>
 
 #include <chrono>
 #include <string>
@@ -272,6 +273,58 @@
     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,
                        std::vector<std::string>& log_buffer, int retry_count)
@@ -345,6 +398,17 @@
 
     sysReleaseMap(&map);
 
+#ifdef USE_MDTP
+    /* If MDTP update failed, return an error such that recovery will not finish. */
+    if (result == 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 */
+
     return result;
 }