Skip to content

Commit

Permalink
Report uncrypt errors in details
Browse files Browse the repository at this point in the history
Add the error codes for uncrypt and report the failure details in
uncrypt_status.

Test: uncrypt_error logs correctly in last_install
Bug: 31603820
Change-Id: I8e0de845ce1707b6f8f5ae84564c5e93fd5f5ef5
  • Loading branch information
Tianjie Xu committed Sep 27, 2016
1 parent 95afc91 commit da44cf1
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 41 deletions.
22 changes: 22 additions & 0 deletions error_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,26 @@ enum CauseCode {
kVendorFailure = 200
};

enum UncryptErrorCode {
kUncryptNoError = -1,
kUncryptErrorHolder = 50,
kUncryptTimeoutError = 100,
kUncryptFileRemoveError,
kUncryptFileOpenError,
kUncryptSocketOpenError,
kUncryptSocketWriteError,
kUncryptSocketListenError,
kUncryptSocketAcceptError,
kUncryptFstabReadError,
kUncryptFileStatError,
kUncryptBlockOpenError,
kUncryptIoctlError,
kUncryptReadError,
kUncryptWriteError,
kUncryptFileSyncError,
kUncryptFileCloseError,
kUncryptFileRenameError,
kUncryptPackageMissingError,
};

#endif
2 changes: 1 addition & 1 deletion install.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ install_package(const char* path, bool* wipe_cache, const char* install_file,
std::string uncrypt_status;
if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) {
PLOG(WARNING) << "failed to read uncrypt status";
} else if (!android::base::StartsWith(uncrypt_status, "uncrypt_time:")) {
} else if (!android::base::StartsWith(uncrypt_status, "uncrypt_:")) {
PLOG(WARNING) << "corrupted uncrypt_status: " << uncrypt_status;
} else {
log_buffer.push_back(android::base::Trim(uncrypt_status));
Expand Down
105 changes: 65 additions & 40 deletions uncrypt/uncrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@
#include <cutils/sockets.h>
#include <fs_mgr.h>

#include "error_code.h"

#define WINDOW_SIZE 5

// uncrypt provides three services: SETUP_BCB, CLEAR_BCB and UNCRYPT.
Expand Down Expand Up @@ -231,26 +233,26 @@ static int produce_block_map(const char* path, const char* map_file, const char*
std::string err;
if (!android::base::RemoveFileIfExists(map_file, &err)) {
LOG(ERROR) << "failed to remove the existing map file " << map_file << ": " << err;
return -1;
return kUncryptFileRemoveError;
}
std::string tmp_map_file = std::string(map_file) + ".tmp";
android::base::unique_fd mapfd(open(tmp_map_file.c_str(),
O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR));
if (mapfd == -1) {
PLOG(ERROR) << "failed to open " << tmp_map_file;
return -1;
return kUncryptFileOpenError;
}

// Make sure we can write to the socket.
if (!write_status_to_socket(0, socket)) {
LOG(ERROR) << "failed to write to socket " << socket;
return -1;
return kUncryptSocketWriteError;
}

struct stat sb;
if (stat(path, &sb) != 0) {
LOG(ERROR) << "failed to stat " << path;
return -1;
return kUncryptFileStatError;
}

LOG(INFO) << " block size: " << sb.st_blksize << " bytes";
Expand All @@ -265,7 +267,7 @@ static int produce_block_map(const char* path, const char* map_file, const char*
static_cast<int64_t>(sb.st_blksize));
if (!android::base::WriteStringToFd(s, mapfd)) {
PLOG(ERROR) << "failed to write " << tmp_map_file;
return -1;
return kUncryptWriteError;
}

std::vector<std::vector<unsigned char>> buffers;
Expand All @@ -278,15 +280,15 @@ static int produce_block_map(const char* path, const char* map_file, const char*
android::base::unique_fd fd(open(path, O_RDONLY));
if (fd == -1) {
PLOG(ERROR) << "failed to open " << path << " for reading";
return -1;
return kUncryptFileOpenError;
}

android::base::unique_fd wfd;
if (encrypted) {
wfd.reset(open(blk_dev, O_WRONLY));
if (wfd == -1) {
PLOG(ERROR) << "failed to open " << blk_dev << " for writing";
return -1;
return kUncryptBlockOpenError;
}
}

Expand All @@ -304,14 +306,14 @@ static int produce_block_map(const char* path, const char* map_file, const char*
// write out head buffer
int block = head_block;
if (ioctl(fd, FIBMAP, &block) != 0) {
LOG(ERROR) << "failed to find block " << head_block;
return -1;
PLOG(ERROR) << "failed to find block " << head_block;
return kUncryptIoctlError;
}
add_block_to_ranges(ranges, block);
if (encrypted) {
if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd,
static_cast<off64_t>(sb.st_blksize) * block) != 0) {
return -1;
return kUncryptWriteError;
}
}
head = (head + 1) % WINDOW_SIZE;
Expand All @@ -324,7 +326,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, buffers[tail].data(), to_read)) {
PLOG(ERROR) << "failed to read " << path;
return -1;
return kUncryptReadError;
}
pos += to_read;
} else {
Expand All @@ -340,14 +342,14 @@ static int produce_block_map(const char* path, const char* map_file, const char*
// write out head buffer
int block = head_block;
if (ioctl(fd, FIBMAP, &block) != 0) {
LOG(ERROR) << "failed to find block " << head_block;
return -1;
PLOG(ERROR) << "failed to find block " << head_block;
return kUncryptIoctlError;
}
add_block_to_ranges(ranges, block);
if (encrypted) {
if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd,
static_cast<off64_t>(sb.st_blksize) * block) != 0) {
return -1;
return kUncryptWriteError;
}
}
head = (head + 1) % WINDOW_SIZE;
Expand All @@ -357,55 +359,55 @@ 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)) {
PLOG(ERROR) << "failed to write " << tmp_map_file;
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)) {
PLOG(ERROR) << "failed to write " << tmp_map_file;
return -1;
return kUncryptWriteError;
}
}

if (fsync(mapfd) == -1) {
PLOG(ERROR) << "failed to fsync \"" << tmp_map_file << "\"";
return -1;
return kUncryptFileSyncError;
}
if (close(mapfd.release()) == -1) {
PLOG(ERROR) << "failed to close " << tmp_map_file;
return -1;
return kUncryptFileCloseError;
}

if (encrypted) {
if (fsync(wfd) == -1) {
PLOG(ERROR) << "failed to fsync \"" << blk_dev << "\"";
return -1;
return kUncryptFileSyncError;
}
if (close(wfd.release()) == -1) {
PLOG(ERROR) << "failed to close " << blk_dev;
return -1;
return kUncryptFileCloseError;
}
}

if (rename(tmp_map_file.c_str(), map_file) == -1) {
PLOG(ERROR) << "failed to rename " << tmp_map_file << " to " << map_file;
return -1;
return kUncryptFileRenameError;
}
// Sync dir to make rename() result written to disk.
std::string file_name = map_file;
std::string dir_name = dirname(&file_name[0]);
android::base::unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY));
if (dfd == -1) {
PLOG(ERROR) << "failed to open dir " << dir_name;
return -1;
return kUncryptFileOpenError;
}
if (fsync(dfd) == -1) {
PLOG(ERROR) << "failed to fsync " << dir_name;
return -1;
return kUncryptFileSyncError;
}
if (close(dfd.release()) == -1) {
PLOG(ERROR) << "failed to close " << dir_name;
return -1;
return kUncryptFileCloseError;
}
return 0;
}
Expand Down Expand Up @@ -444,45 +446,52 @@ 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) {
LOG(INFO) << "writing block map " << 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 bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) {
// Initialize the uncrypt error to kUncryptErrorHolder.
if (!android::base::WriteStringToFile(android::base::StringPrintf(
"uncrypt_error: %d\n", kUncryptErrorHolder), UNCRYPT_STATUS)) {
PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS;
}

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;
}
return false;
}
input_path = package.c_str();
}
CHECK(map_file != nullptr);

#define UNCRYPT_TIME_HOLDER 0x7FFFFFFF
// Intialize the uncrypt time cost to a huge number so that we can tell from
// the statistics if an uncrypt fails to finish.
if (!android::base::WriteStringToFile(android::base::StringPrintf(
"uncrypt_time: %d\n", UNCRYPT_TIME_HOLDER), UNCRYPT_STATUS)) {
PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS;
}

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)) {
PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS;
}

write_status_to_socket(-1, socket);
return false;
}

std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
int count = static_cast<int>(duration.count());
// Overwrite the uncrypt_time if uncrypt finishes successfully.
if (!android::base::WriteStringToFile(
android::base::StringPrintf("uncrypt_time: %d\n", count), UNCRYPT_STATUS)) {
if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) {
PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS;
}

Expand Down Expand Up @@ -560,6 +569,10 @@ 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;
}
return 1;
}

Expand All @@ -568,18 +581,30 @@ 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;
}
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;
}
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;
}
return 1;
}

Expand Down

0 comments on commit da44cf1

Please sign in to comment.