Upon source hash validation failure, log ext4 remount information am: 4e13cf4743 am: 7e1e2f819f
am: 8cbf2b7525
Change-Id: Iecd492b72db16e6debadf37ca2ff42d9f1e73fff
diff --git a/Android.mk b/Android.mk
index 5a3129e..d79d89b 100644
--- a/Android.mk
+++ b/Android.mk
@@ -141,6 +141,7 @@
payload_consumer/file_writer.cc \
payload_consumer/filesystem_verifier_action.cc \
payload_consumer/install_plan.cc \
+ payload_consumer/mount_history.cc \
payload_consumer/payload_constants.cc \
payload_consumer/payload_verifier.cc \
payload_consumer/postinstall_runner_action.cc \
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 45ad58b..d5ae3e6 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -50,6 +50,7 @@
#include "update_engine/payload_consumer/extent_reader.h"
#include "update_engine/payload_consumer/extent_writer.h"
#include "update_engine/payload_consumer/file_descriptor_utils.h"
+#include "update_engine/payload_consumer/mount_history.h"
#if USE_MTD
#include "update_engine/payload_consumer/mtd_file_descriptor.h"
#endif
@@ -1079,8 +1080,10 @@
// Compare |calculated_hash| with source hash in |operation|, return false and
// dump hash and set |error| if don't match.
+// |source_fd| is the file descriptor of the source partition.
bool ValidateSourceHash(const brillo::Blob& calculated_hash,
const InstallOperation& operation,
+ const FileDescriptorPtr source_fd,
ErrorCode* error) {
brillo::Blob expected_source_hash(operation.src_sha256_hash().begin(),
operation.src_sha256_hash().end());
@@ -1107,6 +1110,9 @@
LOG(ERROR) << "Operation source (offset:size) in blocks: "
<< base::JoinString(source_extents, ",");
+ // Log remount history if this device is an ext4 partition.
+ LogMountHistory(source_fd);
+
*error = ErrorCode::kDownloadStateInitializationError;
return false;
}
@@ -1131,7 +1137,8 @@
&source_hash));
if (operation.has_src_sha256_hash()) {
- TEST_AND_RETURN_FALSE(ValidateSourceHash(source_hash, operation, error));
+ TEST_AND_RETURN_FALSE(
+ ValidateSourceHash(source_hash, operation, source_fd_, error));
}
return true;
@@ -1217,8 +1224,8 @@
total_blocks -= read_blocks;
}
TEST_AND_RETURN_FALSE(source_hasher.Finalize());
- TEST_AND_RETURN_FALSE(
- ValidateSourceHash(source_hasher.raw_hash(), operation, error));
+ TEST_AND_RETURN_FALSE(ValidateSourceHash(
+ source_hasher.raw_hash(), operation, source_fd_, error));
return true;
}
diff --git a/payload_consumer/mount_history.cc b/payload_consumer/mount_history.cc
new file mode 100644
index 0000000..43a75b3
--- /dev/null
+++ b/payload_consumer/mount_history.cc
@@ -0,0 +1,72 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "update_engine/payload_consumer/mount_history.h"
+
+#include <inttypes.h>
+
+#include <string>
+#include <vector>
+
+#include <base/logging.h>
+#include <base/time/time.h>
+
+#include "update_engine/common/utils.h"
+
+namespace chromeos_update_engine {
+void LogMountHistory(const FileDescriptorPtr blockdevice_fd) {
+ static constexpr ssize_t kBlockSize = 4096;
+
+ if (blockdevice_fd == nullptr) {
+ return;
+ }
+
+ brillo::Blob block0_buffer(kBlockSize);
+ ssize_t bytes_read;
+
+ if (!utils::PReadAll(
+ blockdevice_fd, block0_buffer.data(), kBlockSize, 0, &bytes_read)) {
+ LOG(WARNING) << "PReadAll failed";
+ return;
+ }
+
+ if (bytes_read != kBlockSize) {
+ LOG(WARNING) << "Could not read an entire block";
+ return;
+ }
+
+ // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
+ // Super block starts from block 0, offset 0x400
+ // 0x2C: len32 Mount time
+ // 0x30: len32 Write time
+ // 0x34: len16 Number of mounts since the last fsck
+ // 0x38: len16 Magic signature 0xEF53
+
+ time_t mount_time =
+ *reinterpret_cast<uint32_t*>(&block0_buffer[0x400 + 0x2C]);
+ uint16_t mount_count =
+ *reinterpret_cast<uint16_t*>(&block0_buffer[0x400 + 0x34]);
+ uint16_t magic = *reinterpret_cast<uint16_t*>(&block0_buffer[0x400 + 0x38]);
+
+ if (magic == 0xEF53) {
+ if (mount_count > 0) {
+ LOG(WARNING) << "Device was remounted R/W " << mount_count << " times. "
+ << "Last remount happened on "
+ << base::Time::FromTimeT(mount_time) << ".";
+ }
+ }
+}
+} // namespace chromeos_update_engine
diff --git a/payload_consumer/mount_history.h b/payload_consumer/mount_history.h
new file mode 100644
index 0000000..ba0c65d
--- /dev/null
+++ b/payload_consumer/mount_history.h
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef UPDATE_ENGINE_PAYLOAD_CONSUMER_MOUNT_HISTORY_H_
+#define UPDATE_ENGINE_PAYLOAD_CONSUMER_MOUNT_HISTORY_H_
+
+#include "update_engine/payload_consumer/file_descriptor.h"
+
+namespace chromeos_update_engine {
+// Try to parse an ext4 from the partition specified by |blockdevice_fd|.
+// If ext4 header exists and remount is detected, log mount count and date.
+void LogMountHistory(const FileDescriptorPtr blockdevice_fd);
+} // namespace chromeos_update_engine
+
+#endif // UPDATE_ENGINE_PAYLOAD_CONSUMER_MOUNT_HISTORY_H_
diff --git a/update_engine.gyp b/update_engine.gyp
index f312a1d..f72ca14 100644
--- a/update_engine.gyp
+++ b/update_engine.gyp
@@ -181,6 +181,7 @@
'payload_consumer/file_writer.cc',
'payload_consumer/filesystem_verifier_action.cc',
'payload_consumer/install_plan.cc',
+ 'payload_consumer/mount_history.cc',
'payload_consumer/payload_constants.cc',
'payload_consumer/payload_verifier.cc',
'payload_consumer/postinstall_runner_action.cc',