给小米 13 解锁刷了 EU 版本并给了 KernelSU LKM,但是 momo 一直检测到 magisk 模块。
Debug 了一下下。
KernelSU 卸载模块实现
kernel 内部使用 path_umount 单独给某个 app 卸载模块 overlay 挂载点
# https://github.com/tiann/KernelSU/blob/v1.0.2/kernel/core_hook.c#L451
static void ksu_umount_mnt(struct path *path, int flags)
{
int err = path_umount(path, flags);
if (err) {
pr_info("umount %s failed: %d\n", path->dentry->d_iname, err);
}
}
static void try_umount(const char *mnt, bool check_mnt, int flags)
{
struct path path;
int err = kern_path(mnt, 0, &path);
...
ksu_umount_mnt(&path, flags);
}
int ksu_handle_setuid(struct cred *new, const struct cred *old)
{
...
try_umount("/system", true, 0);
try_umount("/vendor", true, 0);
try_umount("/product", true, 0);
try_umount("/data/adb/modules", false, MNT_DETACH);
...
}
HyperOS 会使用 overlay 挂载 mi_ext
mi_ext
时候是小米用来添加一些额外 app 和 配置文件的eu
版本这个分区除了 etc
,其他都是空文件夹
# cn 固件的 mi_ext 分区
$ tree
.
├── etc
│ ├── build.prop
│ ├── init
│ │ └── init.miui.mi_ext.rc
│ └── NOTICE.xml.gz
├── product
│ ├── app
│ ├── bin
│ ├── data-app
│ ├── etc
│ │ ├── permissions
│ │ │ ├── hyperos.sdk2.xml
│ │ │ ├── privapp-permissions-product-miext.xml
│ │ │ └── system_launcher_private_permission.xml
│ │ ├── precust_theme
│ │ ├── preferred-apps
│ │ ├── security
│ │ └── sysconfig
│ ├── framework
│ │ └── hyperos.sdk2.jar
│ ├── lib
│ ├── lib64
│ ├── media
│ ├── opcust
│ ├── overlay
│ │ ├── GmsMiCSPTelecommOverlay.apk
│ │ ├── GmsMiCSPTelephonyOverlay.apk
│ │ └── MiuiStkResOverlay.apk
│ ├── priv-app
│ └── usr
├── system
│ ├── app
│ ├── etc
│ │ ├── permissions
│ │ │ └── privapp-permissions-system-miext.xml
│ │ └── sysconfig
│ ├── framework
│ └── priv-app
└── system_ext
└── etc
└── permissions
fstab
:
fuxi:/ $ cat /vendor/etc/fstab.qcom
mi_ext /mnt/vendor/mi_ext erofs ro wait,slotselect,logical,first_stage_mount,nofail
mi_ext /mnt/vendor/mi_ext ext4 ro,barrier=1,discard wait,slotselect,logical,first_stage_mount,nofail
/mnt/vendor/mi_ext /mi_ext erofs ro,bind wait,nofail
overlay /product/overlay overlay ro,lowerdir=/mnt/vendor/mi_ext/product/overlay/:/product/overlay check,nofail
overlay /product/app overlay ro,lowerdir=/mnt/vendor/mi_ext/product/app/:/product/app check,nofail
....
挂载混在一起
大致挂载顺序:
fstab 中的 overlay
KSU 的 overlay
init 额外的 overlay
/mi_ext/etc/init/init.miui.mi_ext.rc
启动时额外的 overlay 挂载on boot mount overlay overlay product/usr lowerdir=/mnt/vendor/mi_ext/product/usr:/product/usr mount overlay overlay product/etc/precust_theme lowerdir=/mnt/vendor/mi_ext/product/etc/precust_theme:product/etc/precust_theme
某个 commit 会恢复一些原厂的挂载
不确定是不是有影响
解决
原本想的是直接修改 fstab 了事,但是发现 android 10 新加了 super 动态分区,把 system/vender/...
分段在一个分区里,类似套娃。
而且这些分区基本都是 erofs(readonly fs)
,想单独改某个分区还挺麻烦的。
看了下 KernelSU Model guide,发现刚好有在 fs 完成后的脚本执行点(post-fs-data.sh)。
那可以全局 umount,来回退 fstab 的挂载(eu
版本,这些挂载没有用处)
以下是脚本:模块下载
#!/system/bin/sh
MODDIR=${0%/*}
BINDDIR=/tmp/mi_ext
LOGFILE=$BINDDIR/mi_ext.log
PATHES="
/product/overlay
/product/app
/product/priv-app
/product/lib
/product/framework
/product/media
/product/opcust
/product/data-app
/product/etc/sysconfig
/product/etc/permissions
/system/app
/system/priv-app
/system/framework
/system/etc/sysconfig
/system/etc/permissions
/product/usr
/product/etc/precust_theme
/product/etc/preferred-apps
/product/etc/security
/vendor/etc/camera
/vendor/lib/rfsa/adsp
"
mkdir -p $BINDDIR
echo '' > $LOGFILE
umount -lvf -t overlay /product/bin >> $LOGFILE 2>&1
umount -lvf -t overlay /product/lib64 >> $LOGFILE 2>&1
for p in $PATHES; do
umount -v -t overlay $p >> $LOGFILE 2>&1
done
mount --bind -o ro $BINDDIR /mnt/vendor/mi_ext/system
mount --bind -o ro $BINDDIR /mi_ext/system
mount --bind -o ro $BINDDIR /mnt/vendor/mi_ext/product
mount --bind -o ro $BINDDIR /mi_ext/product
mount --bind -o ro $BINDDIR /mnt/vendor/mi_ext/vendor
mount --bind -o ro $BINDDIR /mi_ext/vendor