Android - How to disable dm-verity on Android with "user" build type ROM?

I'm going to give a general overview of how dm-verity and related things work on Android according to my limited knowledge. Situation might differ on different devices and ROMs.

HOW IS DM-VERITY ENFORCED?

dm-verity (Verified Boot and AVB) as well as dm-crypt (FDE) are targets of device-mapper feature of Linux kernel. dm-verity verifies the integrity of each block as they are read from block device; enforced by init_first_stage as per fs_mgr_flags set in fstab (1). On system-as-root devices (A/B and non-A/B), kernel is patched to force verity while mounting /system and /vendor if verify/avb flags are found in fstab device tree (dtb).
dm-crypt decrypts/encrypts data transparently when read/written from/to block device. FBE is based on a different kernel framework fscrypt; but both are managed by vold (which runs as a native service) if fs_mgr_flags contain voldmanaged.

WHERE FSTAB IS?

fstab has traditionally been a file on Linux to specify filesystems to be mounted on boot. It's a core component of fs_mgr functionality on Android.

On pre-Oreo releases fstab was in ramdisk. With Treble it was moved to /vendor (or /system/vendor) while the fstab entries for system and vendor (and odm) are moved to Device Tree Blob (dtb). Kernel exports dtb fstab entries in device tree directory at /proc/device-tree/firmware/android.

Some OEMs also put fstab in odm or nvdata partitions.

Source: Android Storage Device Configuration

WHERE DTB IS?

Device Tree is a data structure for describing hardware which is not discoverable to kernel. Device Tree Source (dts) can be converted to dtb (binary blob of DT) and vice versa using dtc. DTB is loaded by bootloader at boot time and passed to kernel so that it can discover hardware and create device nodes accordingly.

DTB is either:

  • Appended to kernel zImage or Image.gz in boot.img (2). It can be split from gzip archive using split-appended-dtb (sadtb).
  • Or in dtbo partition as some OEMs do. This can be checked with:

    ~# ls -l /dev/block/bootdevice/by-name/dtbo*
    ~# grep -C5 PARTNAME=dtbo /sys/dev/block/*/uevent | grep DEVNAME | sed 's/.*=//; s|^|/dev/block/&|'
    
  • Or at the end of boot.img after 2nd stage, or in odm partition (rare, some OEMs do).

Also if the device is non-A/B, dtb (from boot.img and/or dtbo partition) is also added to recovery.img in DTBO section after header, kernel, ramdisk and 2nd stage (3). However this doesn't matter for normal boot. But if the device is also system-as-root, Magisk needs to be installed in this recovery partition as the boot.img contains no ramdisk (4).

In case if DTB is not appended to kernel, dtb(s) are converted to dtb.img using mkdtimg. Same tool can dump back the image.

Source: Implementing DTO

HOW TO DISABLE DM-VERITY?

On userdebug ROMs, dm-verity can be disabled using adb. It modifies magic number of verity metadata block (5, 6) which is written after the last filesystem block on block device (system or vendor) (7). Quoted from here:

the absence of this magic number will halt the verification process

In case of AVB, adb modifies vbmeta header to disable hashtree image verification (8, 9). Quoted from here:

if the AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED flag is set in the top-level vbmeta, then androidboot.veritymode is set to disabled

On user builds ro.debuggable is 0 and adbd isn't running as root. Also there are other differences like that of ALLOW_ADBD_DISABLE_VERITY, so adb won't disable dm-verity. Other approach is to remove verify or avb (10) flag from fstab. Quoted from here:

To verify the partition...
...
In the fstab for the relevant entry, add verify to the fs_mgr flags.

Similarly to remove encryption, forceencrypt=, forcefdeorfbe= or fileencryption= need to be replaced with encryptable=. However encryption cannot be removed without factory reset (FBE too?), so unchecking Preserve force encryption in Magisk app will do nothing.

Some OEMs also use support_scfs fs_mgr flag and ro.config.dmverity=true property on devices with dm-verity enabled.

There are also some exploits discovered in bootloader and adb implementation of some OEMs which can be used to disable dm-verity on affected devices. However such security flaws usually get fixed over time with updates from OEMs.

OPTION 1
Set options in configuration file before installing Magisk:

~# echo 'KEEPVERITY=false' >/cache/.magisk
~# echo 'KEEPFORCEENCRYPT=true' >>/cache/.magisk

If installed, after unchecking Preserve AVB v2.0/dm-verity in app, Magisk needs to be reinstalled. Quoted from here:

in Magisk Manager, “Uninstall > Restore Images” to restore the images, check “Preserve AVB 2.0/dm-verity” box in Advanced Settings, then reinstall Magisk via the app.

OPTION 2
Use some dm-verity disabler zips like this.

OPTION 3
Figure out where the fstab entries of /system and /vendor are on your device.

If in ramdisk (pre-Treble):

  • Extract ramdisk, modify fstab and repack.
  • Or patch ramdisk directly:

    ~# magiskboot cpio ramdisk.cpio 'patch false true'
    

If in dtb:

  • If appended to kernel:
    • Extract boot.img
    • Split appended dtb(s)
    • Patch dtb(s).
    • Append dtb(s) to kernel
    • Repack boot.img
  • If in dtbo partition or in boot.img after 2nd stage, patch dtb.img and write back to partition or boot.img.

How to Unpack / Repack Boot or Recovery image and Ramdisk?
Use AIK or magiskboot.

How to Patch dtb?
Patch directly using magiskboot or manually convert dtb to dts, edit dts with any text editor to remove dm-verity flags, and convert dts back to dtb.

RELATED: