`tune2fs -O verity` if the kernel supports fs-verity

CAVEAT: Once the script runs on a device (that has fs-verity support in
kernel), rolling back this change does not revert the effect on disk.

BUG=b:156386476
TEST=start a new Chrome OS  # fs-verity not enabled for the partition
     cros deploy chromeos-init; reboot  # fs-verity is enabled

Change-Id: I0989556073393121a999afcabdbbdddc9704ec19
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2276585
Tested-by: Victor Hsieh <victorhsieh@chromium.org>
Auto-Submit: Victor Hsieh <victorhsieh@chromium.org>
Reviewed-by: Amin Hassani <ahassani@chromium.org>
Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Commit-Queue: Victor Hsieh <victorhsieh@chromium.org>
diff --git a/chromeos-common-script/share/chromeos-common.sh b/chromeos-common-script/share/chromeos-common.sh
index fa96e39..a70175b 100644
--- a/chromeos-common-script/share/chromeos-common.sh
+++ b/chromeos-common-script/share/chromeos-common.sh
@@ -379,3 +379,11 @@
   # Return true if kernel support ext4 directory encryption.
   "${direncryption_enabled}" && [ -e /sys/fs/ext4/features/encryption ]
 }
+
+ext4_fsverity_supported() {
+  # Can be set in the ebuild.
+  local fsverity_enabled=false
+
+  # Return true if kernel supports fs-verity in ext4.
+  "${fsverity_enabled}" && [ -e /sys/fs/ext4/features/verity ]
+}
diff --git a/init/chromeos_startup b/init/chromeos_startup
index 95a41e8..a286a62 100755
--- a/init/chromeos_startup
+++ b/init/chromeos_startup
@@ -256,7 +256,7 @@
     fi
   fi
 
-  # Check if we enable ext4 crypto.
+  # Check if we enable ext4 features.
   if [ "${FS_FORMAT_STATE}" = "ext4" ]; then
     # Enable directory encryption for existing install.
     if ! dumpe2fs -h "${STATE_DEV}" 2>/dev/null | \
@@ -270,10 +270,21 @@
         tune2fs -O encrypt "${STATE_DEV}" || :
       fi
     fi
-  fi
 
-  # Enable/disable quota feature.
-  if [ "${FS_FORMAT_STATE}" = "ext4" ]; then
+    # Enable fs-verity for existing install.
+    if ! dumpe2fs -h "${STATE_DEV}" 2>/dev/null | \
+         grep -qe "^Filesystem features:.* verity.*"; then
+      # The stateful partition is not set for fs-verity.
+      # Check if we should migrate.
+      if ext4_fsverity_supported; then
+        # Ensure to replay the journal first so it doesn't overwrite the flag.
+        e2fsck -p -E journal_only "${STATE_DEV}" || :
+        # The kernel support fs-verity, do it!
+        tune2fs -O verity "${STATE_DEV}" || :
+      fi
+    fi
+
+    # Enable/disable quota feature.
     if ! dumpe2fs -h "${STATE_DEV}" 2>/dev/null | \
          grep -qe "^Reserved blocks gid.*20119"; then
       # Add Android's AID_RESERVED_DISK to resgid.
diff --git a/installer/chromeos-install b/installer/chromeos-install
index e1f694c..c6d548a 100755
--- a/installer/chromeos-install
+++ b/installer/chromeos-install
@@ -463,6 +463,11 @@
     set -- "$@" -O encrypt
   fi
 
+  # Check if the kernel we are going to install support ext4 fs-verity.
+  if ext4_fsverity_supported; then
+    set -- "$@" -O verity
+  fi
+
   local num_4k_sectors
   if [ "${DST_BLKSIZE}" -gt 4096 ]; then
     num_4k_sectors=$(( NUM_STATEFUL_SECTORS * (DST_BLKSIZE / 4096) ))