Adding error for when overlayfs is enabled in OTA
when running adb remount, overlayfs is enabled on the device interfering
with OTA being able to run. Currently we don't have a good debug message
and users aren't able to realize why the OTA fails. Adding this log will
make it clear this behavior is intended, and we need verity-enabled for
OTA to work
Test: adb remount, update_device.py
Bug: 286889613
Change-Id: Ibcd27911afe6f02ddf0c38ad40904a7e17735b31
diff --git a/aosp/dynamic_partition_control_android.cc b/aosp/dynamic_partition_control_android.cc
index a309b6e..d8df520 100644
--- a/aosp/dynamic_partition_control_android.cc
+++ b/aosp/dynamic_partition_control_android.cc
@@ -48,6 +48,7 @@
#include "update_engine/aosp/dynamic_partition_utils.h"
#include "update_engine/common/boot_control_interface.h"
#include "update_engine/common/dynamic_partition_control_interface.h"
+#include "update_engine/common/error_code.h"
#include "update_engine/common/platform_constants.h"
#include "update_engine/common/utils.h"
#include "update_engine/payload_consumer/cow_writer_file_descriptor.h"
@@ -449,7 +450,8 @@
uint32_t target_slot,
const DeltaArchiveManifest& manifest,
bool update,
- uint64_t* required_size) {
+ uint64_t* required_size,
+ ErrorCode* error) {
source_slot_ = source_slot;
target_slot_ = target_slot;
if (required_size != nullptr) {
@@ -458,10 +460,14 @@
if (fs_mgr_overlayfs_is_setup()) {
// Non DAP devices can use overlayfs as well.
- LOG(WARNING)
+ LOG(ERROR)
<< "overlayfs overrides are active and can interfere with our "
"resources.\n"
<< "run adb enable-verity to deactivate if required and try again.";
+ if (error) {
+ *error = ErrorCode::kOverlayfsenabledError;
+ return false;
+ }
}
// If metadata is erased but not formatted, it is possible to not mount
@@ -852,6 +858,7 @@
auto target_device =
device_dir.Append(GetSuperPartitionName(target_slot)).value();
+
return StoreMetadata(target_device, builder.get(), target_slot);
}
diff --git a/aosp/dynamic_partition_control_android.h b/aosp/dynamic_partition_control_android.h
index 830901b..35a79fd 100644
--- a/aosp/dynamic_partition_control_android.h
+++ b/aosp/dynamic_partition_control_android.h
@@ -55,7 +55,8 @@
uint32_t target_slot,
const DeltaArchiveManifest& manifest,
bool update,
- uint64_t* required_size) override;
+ uint64_t* required_size,
+ ErrorCode* error = nullptr) override;
bool FinishUpdate(bool powerwash_required) override;
std::unique_ptr<AbstractAction> GetCleanupPreviousUpdateAction(
BootControlInterface* boot_control,
diff --git a/aosp/dynamic_partition_control_android_unittest.cc b/aosp/dynamic_partition_control_android_unittest.cc
index 6f1d4ef..30780f0 100644
--- a/aosp/dynamic_partition_control_android_unittest.cc
+++ b/aosp/dynamic_partition_control_android_unittest.cc
@@ -164,6 +164,7 @@
target(),
PartitionSizesToManifest(partition_sizes),
true,
+ nullptr,
nullptr);
}
void SetSlots(const TestParam& slots) { slots_ = slots; }
@@ -363,7 +364,7 @@
// DynamicPartitionControlAndroidTest::PreparePartitionsForUpdate(), since we
// don't want any default group in the PartitionMetadata.
EXPECT_TRUE(dynamicControl().PreparePartitionsForUpdate(
- source(), target(), {}, true, nullptr));
+ source(), target(), {}, true, nullptr, nullptr));
// Should use dynamic source partitions.
EXPECT_CALL(dynamicControl(), GetState(S("system")))
@@ -504,6 +505,7 @@
target(),
PartitionSizesToManifest({{"system", 2_GiB}, {"vendor", 1_GiB}}),
false,
+ nullptr,
nullptr));
// Dynamic partition "system".
@@ -759,6 +761,7 @@
target(),
PartitionSizesToManifest({{"foo", 4_MiB}}),
false,
+ nullptr,
nullptr));
dynamicControl().set_fake_mapped_devices({T("foo")});
@@ -1041,8 +1044,12 @@
}));
}
bool PreparePartitionsForUpdate(uint64_t* required_size) {
- return dynamicControl().PreparePartitionsForUpdate(
- source(), target(), manifest_, true /* update */, required_size);
+ return dynamicControl().PreparePartitionsForUpdate(source(),
+ target(),
+ manifest_,
+ true /* update */,
+ required_size,
+ nullptr);
}
MockSnapshotManager* snapshot_ = nullptr;
DeltaArchiveManifest manifest_;
diff --git a/aosp/update_attempter_android.cc b/aosp/update_attempter_android.cc
index 0c834ad..fcb142e 100644
--- a/aosp/update_attempter_android.cc
+++ b/aosp/update_attempter_android.cc
@@ -1218,12 +1218,23 @@
string payload_id = GetPayloadId(headers);
uint64_t required_size = 0;
+ ErrorCode error_code{};
+
if (!DeltaPerformer::PreparePartitionsForUpdate(prefs_,
boot_control_,
GetTargetSlot(),
manifest,
payload_id,
- &required_size)) {
+ &required_size,
+ &error_code)) {
+ if (error_code == ErrorCode::kOverlayfsenabledError) {
+ LogAndSetError(error,
+ __LINE__,
+ __FILE__,
+ "OverlayFS Shouldn't be enabled for OTA.",
+ error_code);
+ return 0;
+ }
if (required_size == 0) {
LogAndSetGenericError(
error, __LINE__, __FILE__, "Failed to allocate space for payload.");
@@ -1300,6 +1311,7 @@
std::make_unique<PostinstallRunnerAction>(boot_control_, hardware_);
SetStatusAndNotify(UpdateStatus::VERIFYING);
postinstall_runner_action->set_delegate(this);
+ ErrorCode error_code{};
// If last error code is kUpdatedButNotActive, we know that we reached this
// state by calling applyPayload() with switch_slot=false. That applyPayload()
@@ -1314,11 +1326,11 @@
GetTargetSlot(),
manifest,
false /* should update */,
- nullptr)) {
+ nullptr,
+ &error_code)) {
return LogAndSetGenericError(
error, __LINE__, __FILE__, "Failed to PreparePartitionsForUpdate");
}
- ErrorCode error_code{};
if (!install_plan_.ParsePartitions(manifest.partitions(),
boot_control_,
manifest.block_size(),
diff --git a/common/dynamic_partition_control_interface.h b/common/dynamic_partition_control_interface.h
index 490892e..5c0a03b 100644
--- a/common/dynamic_partition_control_interface.h
+++ b/common/dynamic_partition_control_interface.h
@@ -106,7 +106,8 @@
uint32_t target_slot,
const DeltaArchiveManifest& manifest,
bool update,
- uint64_t* required_size) = 0;
+ uint64_t* required_size,
+ ErrorCode* error = nullptr) = 0;
// After writing to new partitions, before rebooting into the new slot, call
// this function to indicate writes to new partitions are done.
diff --git a/common/dynamic_partition_control_stub.cc b/common/dynamic_partition_control_stub.cc
index fd9a3b4..7d681cf 100644
--- a/common/dynamic_partition_control_stub.cc
+++ b/common/dynamic_partition_control_stub.cc
@@ -62,7 +62,8 @@
uint32_t target_slot,
const DeltaArchiveManifest& manifest,
bool update,
- uint64_t* required_size) {
+ uint64_t* required_size,
+ ErrorCode* error) {
return true;
}
diff --git a/common/dynamic_partition_control_stub.h b/common/dynamic_partition_control_stub.h
index 1db6a78..610a82a 100644
--- a/common/dynamic_partition_control_stub.h
+++ b/common/dynamic_partition_control_stub.h
@@ -43,7 +43,8 @@
uint32_t target_slot,
const DeltaArchiveManifest& manifest,
bool update,
- uint64_t* required_size) override;
+ uint64_t* required_size,
+ ErrorCode* error = nullptr) override;
bool FinishUpdate(bool powerwash_required) override;
std::unique_ptr<AbstractAction> GetCleanupPreviousUpdateAction(
diff --git a/common/error_code.h b/common/error_code.h
index a889888..7924579 100644
--- a/common/error_code.h
+++ b/common/error_code.h
@@ -87,6 +87,7 @@
kDeviceCorrupted = 61,
kPackageExcludedFromUpdate = 62,
kPostInstallMountError = 63,
+ kOverlayfsenabledError = 64,
// VERY IMPORTANT! When adding new error codes:
//
diff --git a/common/error_code_utils.cc b/common/error_code_utils.cc
index 421544a..12a98bf 100644
--- a/common/error_code_utils.cc
+++ b/common/error_code_utils.cc
@@ -175,6 +175,8 @@
return "ErrorCode::kPackageExcludedFromUpdate";
case ErrorCode::kPostInstallMountError:
return "ErrorCode::kPostInstallMountError";
+ case ErrorCode::kOverlayfsenabledError:
+ return "ErrorCode::kOverlayfsenabledError";
// Don't add a default case to let the compiler warn about newly added
// error codes which should be added here.
}
diff --git a/common/mock_dynamic_partition_control.h b/common/mock_dynamic_partition_control.h
index 79909b4..968246a 100644
--- a/common/mock_dynamic_partition_control.h
+++ b/common/mock_dynamic_partition_control.h
@@ -66,11 +66,15 @@
std::optional<uint64_t> label),
(override));
- MOCK_METHOD(
- bool,
- PreparePartitionsForUpdate,
- (uint32_t, uint32_t, const DeltaArchiveManifest&, bool, uint64_t*),
- (override));
+ MOCK_METHOD(bool,
+ PreparePartitionsForUpdate,
+ (uint32_t,
+ uint32_t,
+ const DeltaArchiveManifest&,
+ bool,
+ uint64_t*,
+ ErrorCode*),
+ (override));
MOCK_METHOD(bool, ResetUpdate, (PrefsInterface*), (override));
MOCK_METHOD(std::unique_ptr<AbstractAction>,
diff --git a/metrics_utils.cc b/metrics_utils.cc
index ec35fe2..94a0520 100644
--- a/metrics_utils.cc
+++ b/metrics_utils.cc
@@ -73,6 +73,7 @@
case ErrorCode::kVerityCalculationError:
case ErrorCode::kNotEnoughSpace:
case ErrorCode::kDeviceCorrupted:
+ case ErrorCode::kOverlayfsenabledError:
return metrics::AttemptResult::kOperationExecutionError;
case ErrorCode::kDownloadMetadataSignatureMismatch:
@@ -190,6 +191,7 @@
case ErrorCode::kFilesystemCopierError:
case ErrorCode::kPostinstallRunnerError:
case ErrorCode::kPostInstallMountError:
+ case ErrorCode::kOverlayfsenabledError:
case ErrorCode::kPayloadMismatchedType:
case ErrorCode::kInstallDeviceOpenError:
case ErrorCode::kKernelDeviceOpenError:
@@ -367,8 +369,8 @@
TimeDelta time_to_reboot = current_time - system_updated_at;
if (time_to_reboot.ToInternalValue() < 0) {
LOG(WARNING) << "time_to_reboot is negative - system_updated_at: "
- << utils::ToString(system_updated_at) << " current time: "
- << utils::ToString(current_time);
+ << utils::ToString(system_updated_at)
+ << " current time: " << utils::ToString(current_time);
return false;
}
metrics_reporter->ReportTimeToReboot(time_to_reboot.InMinutes());
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index 298bde1..267805e 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -440,6 +440,9 @@
// were written, or false on any error, regardless of progress
// and stores an action exit code in |error|.
bool DeltaPerformer::Write(const void* bytes, size_t count, ErrorCode* error) {
+ if (!error) {
+ return false;
+ }
*error = ErrorCode::kSuccess;
const char* c_bytes = reinterpret_cast<const char*>(bytes);
@@ -730,8 +733,10 @@
// slot suffix of the partitions in the metadata.
if (install_plan_->target_slot != BootControlInterface::kInvalidSlot) {
uint64_t required_size = 0;
- if (!PreparePartitionsForUpdate(&required_size)) {
- if (required_size > 0) {
+ if (!PreparePartitionsForUpdate(&required_size, error)) {
+ if (*error == ErrorCode::kOverlayfsenabledError) {
+ return false;
+ } else if (required_size > 0) {
*error = ErrorCode::kNotEnoughSpace;
} else {
*error = ErrorCode::kInstallDeviceOpenError;
@@ -802,7 +807,8 @@
return true;
}
-bool DeltaPerformer::PreparePartitionsForUpdate(uint64_t* required_size) {
+bool DeltaPerformer::PreparePartitionsForUpdate(uint64_t* required_size,
+ ErrorCode* error) {
// Call static PreparePartitionsForUpdate with hash from
// kPrefsUpdateCheckResponseHash to ensure hash of payload that space is
// preallocated for is the same as the hash of payload being applied.
@@ -814,7 +820,8 @@
install_plan_->target_slot,
manifest_,
update_check_response_hash,
- required_size);
+ required_size,
+ error);
}
bool DeltaPerformer::PreparePartitionsForUpdate(
@@ -823,7 +830,8 @@
BootControlInterface::Slot target_slot,
const DeltaArchiveManifest& manifest,
const std::string& update_check_response_hash,
- uint64_t* required_size) {
+ uint64_t* required_size,
+ ErrorCode* error) {
string last_hash;
ignore_result(
prefs->GetString(kPrefsDynamicPartitionMetadataUpdated, &last_hash));
@@ -845,9 +853,11 @@
target_slot,
manifest,
!is_resume /* should update */,
- required_size)) {
+ required_size,
+ error)) {
LOG(ERROR) << "Unable to initialize partition metadata for slot "
- << BootControlInterface::SlotName(target_slot);
+ << BootControlInterface::SlotName(target_slot) << " "
+ << utils::ErrorCodeToString(*error);
return false;
}
diff --git a/payload_consumer/delta_performer.h b/payload_consumer/delta_performer.h
index 2616b6e..e83e000 100644
--- a/payload_consumer/delta_performer.h
+++ b/payload_consumer/delta_performer.h
@@ -158,7 +158,7 @@
// complete metadata. Returns kMetadataParseError if the metadata can't be
// parsed given the payload.
MetadataParseResult ParsePayloadMetadata(const brillo::Blob& payload,
- ErrorCode* error);
+ ErrorCode* error = nullptr);
void set_public_key_path(const std::string& public_key_path) {
public_key_path_ = public_key_path;
@@ -189,7 +189,8 @@
BootControlInterface::Slot target_slot,
const DeltaArchiveManifest& manifest,
const std::string& update_check_response_hash,
- uint64_t* required_size);
+ uint64_t* required_size,
+ ErrorCode* error = nullptr);
protected:
// Exposed as virtual for testing purposes.
@@ -221,7 +222,7 @@
// Parse and move the update instructions of all partitions into our local
// |partitions_| variable based on the version of the payload. Requires the
// manifest to be parsed and valid.
- bool ParseManifestPartitions(ErrorCode* error);
+ bool ParseManifestPartitions(ErrorCode* error = nullptr);
// Appends up to |*count_p| bytes from |*bytes_p| to |buffer_|, but only to
// the extent that the size of |buffer_| does not exceed |max|. Advances
@@ -233,7 +234,7 @@
// sets |*error| accordingly. Otherwise does nothing. Returns |op_result|.
bool HandleOpResult(bool op_result,
const char* op_type_name,
- ErrorCode* error);
+ ErrorCode* error = nullptr);
// Logs the progress of downloading/applying an update.
void LogProgress(const char* message_prefix);
@@ -263,9 +264,9 @@
bool PerformReplaceOperation(const InstallOperation& operation);
bool PerformZeroOrDiscardOperation(const InstallOperation& operation);
bool PerformSourceCopyOperation(const InstallOperation& operation,
- ErrorCode* error);
+ ErrorCode* error = nullptr);
bool PerformDiffOperation(const InstallOperation& operation,
- ErrorCode* error);
+ ErrorCode* error = nullptr);
// Extracts the payload signature message from the current |buffer_| if the
// offset matches the one specified by the manifest. Returns whether the
@@ -300,7 +301,8 @@
// After install_plan_ is filled with partition names and sizes, initialize
// metadata of partitions and map necessary devices before opening devices.
// Also see comment for the static PreparePartitionsForUpdate().
- bool PreparePartitionsForUpdate(uint64_t* required_size);
+ bool PreparePartitionsForUpdate(uint64_t* required_size,
+ ErrorCode* error = nullptr);
// Check if current manifest contains timestamp errors.
// Return: