Read-only OEM overlays are reported as read-write system partitions (false HIGH)
Version: 2026.9.15.dev4+g7973e90 (main at 7973e90), installed with pip install -e .
Environment: Python 3.14.7, macOS 26.5 (arm64); input is an Android bug report zip
Command: mvt-android check-bugreport -o out <bugreport.zip>
Steps to reproduce
- Take a bug report from a stock Xiaomi-family device (HyperOS / MIUI, Android 13–16 — any
Redmi,POCOorXiaomibuild carryingmi_extoverlays). - Run
check-bugreporton it. - Read the
mountsmodule's alerts.
Expected
No alert: those overlays are read-only. /proc/PID/mountinfo carries two option sets with
different meaning — fields[5] are the per-mount (VFS) flags, the field after the - separator
belongs to the superblock — and a mount is writable only if both allow it. The line below is a
rw VFS mount over a read-only superblock; a write to it fails with EROFS:
340 192 0:137 / /product/usr rw,relatime shared:76 - overlay overlay ro,seclabel,lowerdir=/mnt/vendor/mi_ext/product/usr:/product/usr
^^^^^^^^^ VFS: rw ^^ superblock: roActual
parse_mountinfo() merges both option sets into one list and sets is_read_write = "rw" in options, so check_indicators() reports, on a stock unrooted phone:
HIGH — System partition /product/usr is mounted as read-write (rw). This may indicate system modifications.
MEDIUM — Suspicious mount options found for /product/usr: rwHow often
Measured on 50 bug reports carrying mountinfo — the 28 where this fires plus 22 controls
(14 brands, Android 10–16), by running the artifact code as shipped: 94 HIGH and 119 MEDIUM
alerts, of which 94 HIGH and 94 MEDIUM are this false positive. Every one is a read-only
superblock under a rw VFS mount. The 28 are Xiaomi-family stock builds (Redmi 22, POCO 4,
Xiaomi 2), Android 13–16; the mount points are /product/usr (28),
/product/etc/precust_theme (28), /system_ext/app (23), /system_ext/priv-app (15).
A false HIGH on "system partition mounted read-write" is the alert an analyst reads as evidence of rooting, so it is expensive to leave in place.
Fix
I have a fix and a regression test ready (there is no tests/android/test_artifact_mounts.py
today), verified against this set: the 94 HIGH and 94 MEDIUM go, the 22 controls stay identical,
and the same number of mount entries is parsed either way. Happy to open the PR — say the word and
whether you want the rw-as-suspicious-option half in the same change.
Source: mvt-project/mvt