summaryrefslogtreecommitdiffstats
path: root/uncrypt/uncrypt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'uncrypt/uncrypt.cpp')
-rw-r--r--uncrypt/uncrypt.cpp78
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;
}