diff options
-rw-r--r-- | error_code.h | 22 | ||||
-rw-r--r-- | install.cpp | 52 | ||||
-rw-r--r-- | recovery.cpp | 19 | ||||
-rw-r--r-- | uncrypt/uncrypt.cpp | 84 |
4 files changed, 125 insertions, 52 deletions
diff --git a/error_code.h b/error_code.h index fe38ba476..dfea0eb38 100644 --- a/error_code.h +++ b/error_code.h @@ -44,4 +44,26 @@ enum CauseCode { kVendorFailure = 200 }; +enum UncryptErrorCode { + kUncryptNoError = -1, + kUncryptErrorPlaceholder = 50, + kUncryptTimeoutError = 100, + kUncryptFileRemoveError, + kUncryptFileOpenError, + kUncryptSocketOpenError, + kUncryptSocketWriteError, + kUncryptSocketListenError, + kUncryptSocketAcceptError, + kUncryptFstabReadError, + kUncryptFileStatError, + kUncryptBlockOpenError, + kUncryptIoctlError, + kUncryptReadError, + kUncryptWriteError, + kUncryptFileSyncError, + kUncryptFileCloseError, + kUncryptFileRenameError, + kUncryptPackageMissingError, +}; + #endif diff --git a/install.cpp b/install.cpp index 02c845cb8..d30890a9e 100644 --- a/install.cpp +++ b/install.cpp @@ -30,6 +30,7 @@ #include <string> #include <vector> +#include <android-base/file.h> #include <android-base/parseint.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> @@ -54,6 +55,7 @@ static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt static constexpr const char* AB_OTA_PAYLOAD = "payload.bin"; #define PUBLIC_KEYS_FILE "/res/keys" static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata"; +static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status"; // Default allocation of progress bar segments to operations static const int VERIFICATION_PROGRESS_TIME = 60; @@ -511,13 +513,6 @@ install_package(const char* path, bool* wipe_cache, const char* install_file, modified_flash = true; auto start = std::chrono::system_clock::now(); - FILE* install_log = fopen_path(install_file, "w"); - if (install_log) { - fputs(path, install_log); - fputc('\n', install_log); - } else { - LOGE("failed to open last_install: %s\n", strerror(errno)); - } int result; std::vector<std::string> log_buffer; if (setup_install_mounts() != 0) { @@ -526,21 +521,40 @@ install_package(const char* path, bool* wipe_cache, const char* install_file, } else { result = really_install_package(path, wipe_cache, needs_mount, log_buffer, retry_count); } - if (install_log != nullptr) { - fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log); - fputc('\n', install_log); - std::chrono::duration<double> duration = std::chrono::system_clock::now() - start; - int count = static_cast<int>(duration.count()); - // Report the time spent to apply OTA update in seconds. - fprintf(install_log, "time_total: %d\n", count); - fprintf(install_log, "retry: %d\n", retry_count); - - for (const auto& s : log_buffer) { - fprintf(install_log, "%s\n", s.c_str()); + + // Measure the time spent to apply OTA update in seconds. + std::chrono::duration<double> duration = std::chrono::system_clock::now() - start; + int time_total = static_cast<int>(duration.count()); + + if (ensure_path_mounted(UNCRYPT_STATUS) != 0) { + LOGW("Can't mount %s\n", UNCRYPT_STATUS); + } else { + std::string uncrypt_status; + if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) { + LOGW("failed to read uncrypt status: %s\n", strerror(errno)); + } else if (!android::base::StartsWith(uncrypt_status, "uncrypt_")) { + LOGW("corrupted uncrypt_status: %s: %s\n", uncrypt_status.c_str(), strerror(errno)); + } else { + log_buffer.push_back(android::base::Trim(uncrypt_status)); } + } - fclose(install_log); + // The first two lines need to be the package name and install result. + std::vector<std::string> log_header = { + path, + result == INSTALL_SUCCESS ? "1" : "0", + "time_total: " + std::to_string(time_total), + "retry: " + std::to_string(retry_count), + }; + std::string log_content = android::base::Join(log_header, "\n") + "\n" + + android::base::Join(log_buffer, "\n"); + if (!android::base::WriteStringToFile(log_content, install_file)) { + LOGE("failed to write %s: %s\n", install_file, strerror(errno)); } + + // Write a copy into last_log. + LOGI("%s\n", log_content.c_str()); + return result; } diff --git a/recovery.cpp b/recovery.cpp index ccb2d223b..0f0b978e7 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -1429,15 +1429,18 @@ static bool bootreason_in_blacklist() { } static void log_failure_code(ErrorCode code, const char *update_package) { - FILE* install_log = fopen_path(TEMPORARY_INSTALL_FILE, "w"); - if (install_log != nullptr) { - fprintf(install_log, "%s\n", update_package); - fprintf(install_log, "0\n"); - fprintf(install_log, "error: %d\n", code); - fclose(install_log); - } else { - LOGE("failed to open last_install: %s\n", strerror(errno)); + std::vector<std::string> log_buffer = { + update_package, + "0", // install result + "error: " + std::to_string(code), + }; + std::string log_content = android::base::Join(log_buffer, "\n"); + if (!android::base::WriteStringToFile(log_content, TEMPORARY_INSTALL_FILE)) { + LOGE("failed to write %s: %s\n", TEMPORARY_INSTALL_FILE, strerror(errno)); } + + // Also write the info into last_log. + LOGI("%s\n", log_content.c_str()); } static ssize_t logbasename( diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index 5e804bcca..280568d23 100644 --- a/uncrypt/uncrypt.cpp +++ b/uncrypt/uncrypt.cpp @@ -118,6 +118,7 @@ #define LOG_TAG "uncrypt" #include <log/log.h> +#include "error_code.h" #include "unique_fd.h" #define WINDOW_SIZE 5 @@ -134,6 +135,7 @@ // devices, on which /cache partitions always exist. static const std::string CACHE_BLOCK_MAP = "/cache/recovery/block.map"; static const std::string UNCRYPT_PATH_FILE = "/cache/recovery/uncrypt_file"; +static const std::string UNCRYPT_STATUS = "/cache/recovery/uncrypt_status"; static const std::string UNCRYPT_SOCKET = "uncrypt"; static struct fstab* fstab = nullptr; @@ -234,25 +236,25 @@ static int produce_block_map(const char* path, const char* map_file, const char* std::string err; if (!android::base::RemoveFileIfExists(map_file, &err)) { ALOGE("failed to remove the existing map file %s: %s", map_file, err.c_str()); - return -1; + return kUncryptFileRemoveError; } std::string tmp_map_file = std::string(map_file) + ".tmp"; unique_fd mapfd(open(tmp_map_file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)); if (!mapfd) { ALOGE("failed to open %s: %s\n", tmp_map_file.c_str(), strerror(errno)); - return -1; + return kUncryptFileOpenError; } // Make sure we can write to the socket. if (!write_status_to_socket(0, socket)) { ALOGE("failed to write to socket %d\n", socket); - return -1; + return kUncryptSocketWriteError; } struct stat sb; if (stat(path, &sb) != 0) { ALOGE("failed to stat %s", path); - return -1; + return kUncryptFileStatError; } ALOGI(" block size: %ld bytes", static_cast<long>(sb.st_blksize)); @@ -266,7 +268,7 @@ static int produce_block_map(const char* path, const char* map_file, const char* blk_dev, sb.st_size, static_cast<long>(sb.st_blksize)); if (!android::base::WriteStringToFd(s, mapfd.get())) { ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); - return -1; + return kUncryptWriteError; } std::vector<std::vector<unsigned char>> buffers; @@ -279,7 +281,7 @@ static int produce_block_map(const char* path, const char* map_file, const char* unique_fd fd(open(path, O_RDONLY)); if (!fd) { ALOGE("failed to open %s for reading: %s", path, strerror(errno)); - return -1; + return kUncryptFileOpenError; } unique_fd wfd(-1); @@ -287,7 +289,7 @@ static int produce_block_map(const char* path, const char* map_file, const char* wfd = open(blk_dev, O_WRONLY); if (!wfd) { ALOGE("failed to open fd for writing: %s", strerror(errno)); - return -1; + return kUncryptBlockOpenError; } } @@ -306,13 +308,13 @@ static int produce_block_map(const char* path, const char* map_file, const char* int block = head_block; if (ioctl(fd.get(), FIBMAP, &block) != 0) { ALOGE("failed to find block %d", head_block); - return -1; + return kUncryptIoctlError; } add_block_to_ranges(ranges, block); if (encrypted) { if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(), static_cast<off64_t>(sb.st_blksize) * block) != 0) { - return -1; + return kUncryptWriteError; } } head = (head + 1) % WINDOW_SIZE; @@ -325,7 +327,7 @@ static int produce_block_map(const char* path, const char* map_file, const char* std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos)); if (!android::base::ReadFully(fd.get(), buffers[tail].data(), to_read)) { ALOGE("failed to read: %s", strerror(errno)); - return -1; + return kUncryptReadError; } pos += to_read; } else { @@ -342,13 +344,13 @@ static int produce_block_map(const char* path, const char* map_file, const char* int block = head_block; if (ioctl(fd.get(), FIBMAP, &block) != 0) { ALOGE("failed to find block %d", head_block); - return -1; + return kUncryptIoctlError; } add_block_to_ranges(ranges, block); if (encrypted) { if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(), static_cast<off64_t>(sb.st_blksize) * block) != 0) { - return -1; + return kUncryptWriteError; } } head = (head + 1) % WINDOW_SIZE; @@ -358,41 +360,41 @@ static int produce_block_map(const char* path, const char* map_file, const char* if (!android::base::WriteStringToFd( android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd.get())) { ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); - return -1; + return kUncryptWriteError; } for (size_t i = 0; i < ranges.size(); i += 2) { if (!android::base::WriteStringToFd( android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd.get())) { ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); - return -1; + return kUncryptWriteError; } } if (fsync(mapfd.get()) == -1) { ALOGE("failed to fsync \"%s\": %s", tmp_map_file.c_str(), strerror(errno)); - return -1; + return kUncryptFileSyncError; } if (close(mapfd.get()) == -1) { ALOGE("failed to close %s: %s", tmp_map_file.c_str(), strerror(errno)); - return -1; + return kUncryptFileCloseError; } mapfd = -1; if (encrypted) { if (fsync(wfd.get()) == -1) { ALOGE("failed to fsync \"%s\": %s", blk_dev, strerror(errno)); - return -1; + return kUncryptFileSyncError; } if (close(wfd.get()) == -1) { ALOGE("failed to close %s: %s", blk_dev, strerror(errno)); - return -1; + return kUncryptFileCloseError; } wfd = -1; } if (rename(tmp_map_file.c_str(), map_file) == -1) { ALOGE("failed to rename %s to %s: %s", tmp_map_file.c_str(), map_file, strerror(errno)); - return -1; + return kUncryptFileRenameError; } // Sync dir to make rename() result written to disk. std::string file_name = map_file; @@ -400,15 +402,15 @@ static int produce_block_map(const char* path, const char* map_file, const char* unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY)); if (!dfd) { ALOGE("failed to open dir %s: %s", dir_name.c_str(), strerror(errno)); - return -1; + return kUncryptFileOpenError; } if (fsync(dfd.get()) == -1) { ALOGE("failed to fsync %s: %s", dir_name.c_str(), strerror(errno)); - return -1; + return kUncryptFileSyncError; } if (close(dfd.get()) == -1) { ALOGE("failed to close %s: %s", dir_name.c_str(), strerror(errno)); - return -1; + return kUncryptFileCloseError; } dfd = -1; return 0; @@ -448,30 +450,58 @@ static int uncrypt(const char* input_path, const char* map_file, const int socke // and /sdcard we leave the file alone. if (strncmp(path, "/data/", 6) == 0) { ALOGI("writing block map %s", map_file); - if (produce_block_map(path, map_file, blk_dev, encrypted, socket) != 0) { - return 1; - } + return produce_block_map(path, map_file, blk_dev, encrypted, socket); } return 0; } +static void log_uncrypt_error_code(UncryptErrorCode error_code) { + if (!android::base::WriteStringToFile(android::base::StringPrintf( + "uncrypt_error: %d\n", error_code), UNCRYPT_STATUS)) { + ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno)); + } +} + static bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) { + // Initialize the uncrypt error to kUncryptErrorPlaceholder. + log_uncrypt_error_code(kUncryptErrorPlaceholder); + std::string package; if (input_path == nullptr) { if (!find_uncrypt_package(UNCRYPT_PATH_FILE, &package)) { write_status_to_socket(-1, socket); + // Overwrite the error message. + log_uncrypt_error_code(kUncryptPackageMissingError); return false; } input_path = package.c_str(); } CHECK(map_file != nullptr); + + auto start = std::chrono::system_clock::now(); int status = uncrypt(input_path, map_file, socket); + std::chrono::duration<double> duration = std::chrono::system_clock::now() - start; + int count = static_cast<int>(duration.count()); + + std::string uncrypt_message = android::base::StringPrintf("uncrypt_time: %d\n", count); if (status != 0) { + // Log the time cost and error code if uncrypt fails. + uncrypt_message += android::base::StringPrintf("uncrypt_error: %d\n", status); + if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) { + ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno)); + } + write_status_to_socket(-1, socket); return false; } + + if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) { + ALOGW("failed to write to %s: %s", UNCRYPT_STATUS.c_str(), strerror(errno)); + } + write_status_to_socket(100, socket); + return true; } @@ -561,6 +591,7 @@ int main(int argc, char** argv) { } if ((fstab = read_fstab()) == nullptr) { + log_uncrypt_error_code(kUncryptFstabReadError); return 1; } @@ -569,18 +600,21 @@ int main(int argc, char** argv) { unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str())); if (!service_socket) { ALOGE("failed to open socket \"%s\": %s", UNCRYPT_SOCKET.c_str(), strerror(errno)); + log_uncrypt_error_code(kUncryptSocketOpenError); return 1; } fcntl(service_socket.get(), F_SETFD, FD_CLOEXEC); if (listen(service_socket.get(), 1) == -1) { ALOGE("failed to listen on socket %d: %s", service_socket.get(), strerror(errno)); + log_uncrypt_error_code(kUncryptSocketListenError); return 1; } unique_fd socket_fd(accept4(service_socket.get(), nullptr, nullptr, SOCK_CLOEXEC)); if (!socket_fd) { ALOGE("failed to accept on socket %d: %s", service_socket.get(), strerror(errno)); + log_uncrypt_error_code(kUncryptSocketAcceptError); return 1; } |