Mark block device as read-only before mounting.
Mounting a block device as read-only still allows the filesystem to
write to the block device, while keeping the user-facing filesystem
interface "read-only". This behavior will make dm-verity to fail after
reboot if any block is modified during postinstall.
This patch marks the block device as read-only before mounting it, and
marks them read-only or read-write before using them during the update.
Bug: 27859604
TEST=Added logging and deployed an update to brillo, devices are marked RO/RW as needed during a delta update.
(cherry picked from commit 5fb356cac8a87c62fa83005d99370aa2f8416064)
Change-Id: I8797c35514e1f38c2a0395cedc8e1dce53e28350
diff --git a/payload_consumer/delta_performer.cc b/payload_consumer/delta_performer.cc
index e2613da..faf67a0 100644
--- a/payload_consumer/delta_performer.cc
+++ b/payload_consumer/delta_performer.cc
@@ -109,6 +109,10 @@
// Opens path for read/write. On success returns an open FileDescriptor
// and sets *err to 0. On failure, sets *err to errno and returns nullptr.
FileDescriptorPtr OpenFile(const char* path, int mode, int* err) {
+ // Try to mark the block device read-only based on the mode. Ignore any
+ // failure since this won't work when passing regular files.
+ utils::SetBlockDeviceReadOnly(path, (mode & O_ACCMODE) == O_RDONLY);
+
FileDescriptorPtr fd = CreateFileDescriptor(path);
#if USE_MTD
// On NAND devices, we can either read, or write, but not both. So here we
diff --git a/payload_consumer/postinstall_runner_action.cc b/payload_consumer/postinstall_runner_action.cc
index db1ec3c..98f4eaf 100644
--- a/payload_consumer/postinstall_runner_action.cc
+++ b/payload_consumer/postinstall_runner_action.cc
@@ -132,6 +132,18 @@
return CompletePostinstall(ErrorCode::kPostinstallRunnerError);
}
+#ifdef __ANDROID__
+ // In Chromium OS, the postinstall step is allowed to write to the block
+ // device on the target image, so we don't mark it as read-only and should
+ // be read-write since we just wrote to it during the update.
+
+ // Mark the block device as read-only before mounting for post-install.
+ if (!utils::SetBlockDeviceReadOnly(mountable_device, true)) {
+ return CompletePartitionPostinstall(
+ 1, "Error marking the device " + mountable_device + " read only.");
+ }
+#endif // __ANDROID__
+
if (!utils::MountFilesystem(mountable_device,
fs_mount_dir_,
MS_RDONLY,