diff options
Diffstat (limited to 'uncrypt/uncrypt.cpp')
-rw-r--r-- | uncrypt/uncrypt.cpp | 78 |
1 files changed, 53 insertions, 25 deletions
diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp index e1b6a1c20..a06384dd5 100644 --- a/uncrypt/uncrypt.cpp +++ b/uncrypt/uncrypt.cpp @@ -118,7 +118,8 @@ #include "error_code.h" -#define WINDOW_SIZE 5 +static constexpr int WINDOW_SIZE = 5; +static constexpr int FIBMAP_RETRY_LIMIT = 3; // uncrypt provides three services: SETUP_BCB, CLEAR_BCB and UNCRYPT. // @@ -233,6 +234,26 @@ static bool find_uncrypt_package(const std::string& uncrypt_path_file, std::stri return true; } +static int retry_fibmap(const int fd, const char* name, int* block, const int head_block) { + CHECK(block != nullptr); + for (size_t i = 0; i < FIBMAP_RETRY_LIMIT; i++) { + if (fsync(fd) == -1) { + PLOG(ERROR) << "failed to fsync \"" << name << "\""; + return kUncryptFileSyncError; + } + if (ioctl(fd, FIBMAP, block) != 0) { + PLOG(ERROR) << "failed to find block " << head_block; + return kUncryptIoctlError; + } + if (*block != 0) { + return kUncryptNoError; + } + sleep(1); + } + LOG(ERROR) << "fibmap of " << head_block << "always returns 0"; + return kUncryptIoctlError; +} + static int produce_block_map(const char* path, const char* map_file, const char* blk_dev, bool encrypted, int socket) { std::string err; @@ -314,6 +335,15 @@ static int produce_block_map(const char* path, const char* map_file, const char* PLOG(ERROR) << "failed to find block " << head_block; return kUncryptIoctlError; } + + if (block == 0) { + LOG(ERROR) << "failed to find block " << head_block << ", retrying"; + int error = retry_fibmap(fd, path, &block, head_block); + if (error != kUncryptNoError) { + return error; + } + } + add_block_to_ranges(ranges, block); if (encrypted) { if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd, @@ -350,6 +380,15 @@ static int produce_block_map(const char* path, const char* map_file, const char* PLOG(ERROR) << "failed to find block " << head_block; return kUncryptIoctlError; } + + if (block == 0) { + LOG(ERROR) << "failed to find block " << head_block << ", retrying"; + int error = retry_fibmap(fd, path, &block, head_block); + if (error != kUncryptNoError) { + return error; + } + } + add_block_to_ranges(ranges, block); if (encrypted) { if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd, @@ -457,22 +496,23 @@ static int uncrypt(const char* input_path, const char* map_file, const int socke return 0; } -static bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) { - // Initialize the uncrypt error to kUncryptErrorHolder. +static void log_uncrypt_error_code(UncryptErrorCode error_code) { if (!android::base::WriteStringToFile(android::base::StringPrintf( - "uncrypt_error: %d\n", kUncryptErrorHolder), UNCRYPT_STATUS)) { + "uncrypt_error: %d\n", error_code), UNCRYPT_STATUS)) { PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; } +} + +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. - if (!android::base::WriteStringToFile(android::base::StringPrintf( - "uncrypt_error: %d\n", kUncryptPackageMissingError), UNCRYPT_STATUS)) { - PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; - } + log_uncrypt_error_code(kUncryptPackageMissingError); return false; } input_path = package.c_str(); @@ -529,7 +569,7 @@ static bool setup_bcb(const int socket) { std::string content; content.resize(length); if (!android::base::ReadFully(socket, &content[0], length)) { - PLOG(ERROR) << "failed to read the length"; + PLOG(ERROR) << "failed to read the message"; return false; } LOG(INFO) << " received command: [" << content << "] (" << content.size() << ")"; @@ -591,10 +631,7 @@ int main(int argc, char** argv) { } if ((fstab = read_fstab()) == nullptr) { - if (!android::base::WriteStringToFile(android::base::StringPrintf( - "uncrypt_error: %d\n", kUncryptFstabReadError), UNCRYPT_STATUS)) { - PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; - } + log_uncrypt_error_code(kUncryptFstabReadError); return 1; } @@ -614,30 +651,21 @@ int main(int argc, char** argv) { android::base::unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str())); if (service_socket == -1) { PLOG(ERROR) << "failed to open socket \"" << UNCRYPT_SOCKET << "\""; - if (!android::base::WriteStringToFile(android::base::StringPrintf( - "uncrypt_error: %d\n", kUncryptSocketOpenError), UNCRYPT_STATUS)) { - PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; - } + log_uncrypt_error_code(kUncryptSocketOpenError); return 1; } fcntl(service_socket, F_SETFD, FD_CLOEXEC); if (listen(service_socket, 1) == -1) { PLOG(ERROR) << "failed to listen on socket " << service_socket.get(); - if (!android::base::WriteStringToFile(android::base::StringPrintf( - "uncrypt_error: %d\n", kUncryptSocketListenError), UNCRYPT_STATUS)) { - PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; - } + log_uncrypt_error_code(kUncryptSocketListenError); return 1; } android::base::unique_fd socket_fd(accept4(service_socket, nullptr, nullptr, SOCK_CLOEXEC)); if (socket_fd == -1) { PLOG(ERROR) << "failed to accept on socket " << service_socket.get(); - if (!android::base::WriteStringToFile(android::base::StringPrintf( - "uncrypt_error: %d\n", kUncryptSocketAcceptError), UNCRYPT_STATUS)) { - PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS; - } + log_uncrypt_error_code(kUncryptSocketAcceptError); return 1; } |