Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(480)

Unified Diff: filesystem_copier_action.cc

Issue 5516009: AU: Split applied update verification into a separate step. (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/update_engine.git@master
Patch Set: review comments Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « filesystem_copier_action.h ('k') | filesystem_copier_action_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: filesystem_copier_action.cc
diff --git a/filesystem_copier_action.cc b/filesystem_copier_action.cc
index f3f71bdbee4b107ddfc7ccba92e1e68cb168da91..7da54a83cf9a6f792b2e0edbdb34d053b4902e85 100755
--- a/filesystem_copier_action.cc
+++ b/filesystem_copier_action.cc
@@ -32,12 +32,14 @@ using std::vector;
namespace chromeos_update_engine {
namespace {
-const off_t kCopyFileBufferSize = 512 * 1024;
+const off_t kCopyFileBufferSize = 128 * 1024;
} // namespace {}
FilesystemCopierAction::FilesystemCopierAction(
- bool copying_kernel_install_path)
+ bool copying_kernel_install_path,
+ bool verify_hash)
: copying_kernel_install_path_(copying_kernel_install_path),
+ verify_hash_(verify_hash),
src_stream_(NULL),
dst_stream_(NULL),
read_done_(false),
@@ -68,44 +70,49 @@ void FilesystemCopierAction::PerformAction() {
}
install_plan_ = GetInputObject();
- if (install_plan_.is_full_update || install_plan_.is_resume) {
- // No copy needed. Done!
+ // Note that we do need to run hash verification for new-style full updates
+ // but currently the |is_full_update| field is set to true only for old-style
+ // full updates and we don't have any expected partition info in that case.
+ if (install_plan_.is_full_update ||
+ (!verify_hash_ && install_plan_.is_resume)) {
+ // No copy or hash verification needed. Done!
if (HasOutputPipe())
SetOutputObject(install_plan_);
abort_action_completer.set_code(kActionCodeSuccess);
return;
}
- string source = copy_source_;
+ const string destination = copying_kernel_install_path_ ?
+ install_plan_.kernel_install_path :
+ install_plan_.install_path;
+ string source = verify_hash_ ? destination : copy_source_;
if (source.empty()) {
source = copying_kernel_install_path_ ?
utils::BootKernelDevice(utils::BootDevice()) :
utils::BootDevice();
}
-
- const string destination = copying_kernel_install_path_ ?
- install_plan_.kernel_install_path :
- install_plan_.install_path;
-
int src_fd = open(source.c_str(), O_RDONLY);
if (src_fd < 0) {
PLOG(ERROR) << "Unable to open " << source << " for reading:";
return;
}
- int dst_fd = open(destination.c_str(),
- O_WRONLY | O_TRUNC | O_CREAT,
+
+ if (!verify_hash_) {
+ int dst_fd = open(destination.c_str(),
+ O_WRONLY | O_TRUNC | O_CREAT,
0644);
- if (dst_fd < 0) {
- close(src_fd);
- PLOG(ERROR) << "Unable to open " << install_plan_.install_path
- << " for writing:";
- return;
+ if (dst_fd < 0) {
+ close(src_fd);
+ PLOG(ERROR) << "Unable to open " << install_plan_.install_path
+ << " for writing:";
+ return;
+ }
+
+ dst_stream_ = g_unix_output_stream_new(dst_fd, TRUE);
}
DetermineFilesystemSize(src_fd);
-
src_stream_ = g_unix_input_stream_new(src_fd, TRUE);
- dst_stream_ = g_unix_output_stream_new(dst_fd, TRUE);
for (int i = 0; i < 2; i++) {
buffer_[i].resize(kCopyFileBufferSize);
@@ -126,22 +133,22 @@ void FilesystemCopierAction::TerminateProcessing() {
}
}
-void FilesystemCopierAction::Cleanup(bool success) {
+void FilesystemCopierAction::Cleanup(ActionExitCode code) {
for (int i = 0; i < 2; i++) {
g_object_unref(canceller_[i]);
canceller_[i] = NULL;
}
g_object_unref(src_stream_);
src_stream_ = NULL;
- g_object_unref(dst_stream_);
- dst_stream_ = NULL;
+ if (dst_stream_) {
+ g_object_unref(dst_stream_);
+ dst_stream_ = NULL;
+ }
if (cancelled_)
return;
- if (success && HasOutputPipe())
+ if (code == kActionCodeSuccess && HasOutputPipe())
SetOutputObject(install_plan_);
- processor_->ActionComplete(
- this,
- success ? kActionCodeSuccess : kActionCodeError);
+ processor_->ActionComplete(this, code);
}
void FilesystemCopierAction::AsyncReadReadyCallback(GObject *source_object,
@@ -164,19 +171,21 @@ void FilesystemCopierAction::AsyncReadReadyCallback(GObject *source_object,
} else {
buffer_valid_size_[index] = bytes_read;
buffer_state_[index] = kBufferStateFull;
- }
-
- if (bytes_read > 0) {
filesystem_size_ -= bytes_read;
}
-
SpawnAsyncActions();
if (bytes_read > 0) {
+ // If read_done_ is set, SpawnAsyncActions may finalize the hash so the hash
+ // update below would happen too late.
+ CHECK(!read_done_);
if (!hasher_.Update(buffer_[index].data(), bytes_read)) {
LOG(ERROR) << "Unable to update the hash.";
failed_ = true;
}
+ if (verify_hash_) {
+ buffer_state_[index] = kBufferStateEmpty;
+ }
}
}
@@ -235,23 +244,26 @@ void FilesystemCopierAction::SpawnAsyncActions() {
}
if (failed_ || cancelled_) {
if (!reading && !writing) {
- Cleanup(false);
+ Cleanup(kActionCodeError);
}
return;
}
for (int i = 0; i < 2; i++) {
if (!reading && !read_done_ && buffer_state_[i] == kBufferStateEmpty) {
+ int64_t bytes_to_read = std::min(static_cast<int64_t>(buffer_[0].size()),
+ filesystem_size_);
g_input_stream_read_async(
src_stream_,
buffer_[i].data(),
- GetBytesToRead(),
+ bytes_to_read,
G_PRIORITY_DEFAULT,
canceller_[i],
&FilesystemCopierAction::StaticAsyncReadReadyCallback,
this);
reading = true;
buffer_state_[i] = kBufferStateReading;
- } else if (!writing && buffer_state_[i] == kBufferStateFull) {
+ } else if (!writing && !verify_hash_ &&
+ buffer_state_[i] == kBufferStateFull) {
g_output_stream_write_async(
dst_stream_,
buffer_[i].data(),
@@ -266,22 +278,43 @@ void FilesystemCopierAction::SpawnAsyncActions() {
}
if (!reading && !writing) {
// We're done!
+ ActionExitCode code = kActionCodeSuccess;
if (hasher_.Finalize()) {
- LOG(INFO) << "hash: " << hasher_.hash();
- if (copying_kernel_install_path_) {
- install_plan_.current_kernel_hash = hasher_.raw_hash();
+ LOG(INFO) << "Hash: " << hasher_.hash();
+ if (verify_hash_) {
+ if (copying_kernel_install_path_) {
+ if (install_plan_.kernel_hash != hasher_.raw_hash()) {
+ code = kActionCodeNewKernelVerificationError;
+ LOG(ERROR) << "New kernel verification failed.";
+ }
+ } else {
+ if (install_plan_.rootfs_hash != hasher_.raw_hash()) {
+ code = kActionCodeNewRootfsVerificationError;
+ LOG(ERROR) << "New rootfs verification failed.";
+ }
+ }
} else {
- install_plan_.current_rootfs_hash = hasher_.raw_hash();
+ if (copying_kernel_install_path_) {
+ install_plan_.kernel_hash = hasher_.raw_hash();
+ } else {
+ install_plan_.rootfs_hash = hasher_.raw_hash();
+ }
}
- Cleanup(true);
} else {
LOG(ERROR) << "Unable to finalize the hash.";
- Cleanup(false);
+ code = kActionCodeError;
}
+ Cleanup(code);
}
}
void FilesystemCopierAction::DetermineFilesystemSize(int fd) {
+ if (verify_hash_) {
+ filesystem_size_ = copying_kernel_install_path_ ?
+ install_plan_.kernel_size : install_plan_.rootfs_size;
+ LOG(INFO) << "Filesystem size: " << filesystem_size_;
+ return;
+ }
filesystem_size_ = kint64max;
int block_count = 0, block_size = 0;
if (!copying_kernel_install_path_ &&
@@ -292,8 +325,4 @@ void FilesystemCopierAction::DetermineFilesystemSize(int fd) {
}
}
-int64_t FilesystemCopierAction::GetBytesToRead() {
- return std::min(static_cast<int64_t>(buffer_[0].size()), filesystem_size_);
-}
-
} // namespace chromeos_update_engine
« no previous file with comments | « filesystem_copier_action.h ('k') | filesystem_copier_action_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698