topjohnwu / Magisk

The Magic Mask for Android
GNU General Public License v3.0
48.51k stars 12.4k forks source link

VIVO/iQOO kernel restictions: "Operation not permitted" when executing `su` or mounting to `/system`, or bootloops if rooted #5148

Closed canyie closed 2 years ago

canyie commented 2 years ago

Device: iQOO Z1/VIVO X70 PRO/iQOO NEO3, and more Android version: N/A Magisk version name: N/A Magisk version code: N/A, but more serious since 24302

Magisk fails to mount /system on some Vivo/iQOO devices.

01-01 08:17:34.721  root   650   652 E Magisk  : mount tmpfs->/system/bin failed with 1: Operation not permitted
01-01 08:17:34.721  root   650   652 E Magisk  : mount /dev/Qnh/.magisk/mirror/system/bin/AudioSetParam->/system/bin/AudioSetParam failed with 1: Operation not permitted
01-01 08:17:34.721  root   650   652 E Magisk  : mount /dev/Qnh/.magisk/mirror/system/bin/TEST_IServiceManager->/system/bin/TEST_IServiceManager failed with 1: Operation not permitted
01-01 08:17:34.721  root   650   652 E Magisk  : mount /dev/Qnh/.magisk/mirror/system/bin/abb->/system/bin/abb failed with 1: Operation not permitted

According to a bug report from a "Vivo internal staff" who has a device running userdebug build, adb root and manually mount /system works but fails when mounting in Magisk superuser environment. After debugging with him/her/them, we found that the device only allows programs in /system to mount the system partition (move binary that will mount /system to other partitions, and it fails even in adb root environment). I believe that the device has an allowlist and refuses to mount key partitions for programs if their partition is not in the allowlist.

I think the following two solutions may fix it:

  1. Reimplement magic mounting logic in rc script language and add it to init.rc.
  2. Inject Magisk binaries to /system in magiskinit.

I'm unsure when this problem will be solved, so I opened an issue to track the relevant information.


Edit: even successfully mount su to /system/bin/su, executing su will throw an operation not permitted error.

yujincheng08 commented 2 years ago

/system/bin/su cannot be executed by other processes so there may be kernel restriction. This issue is hard to fix if no kernel source is available.

yujincheng08 commented 2 years ago

Kernel sources of some vivo devices, but unfortunately, there are no ones of relative devices

https://opensource.vivo.com/Project

canyie commented 2 years ago

Update: Kernel source code of iQOO Z1 is currently available!

jnelson89 commented 2 years ago

Update: Kernel source code of iQOO Z1 is currently available!

Here are my Device Vivo V5 mt6750 kernel sources which can be helpful for you to fix my problem https://github.com/Dawn-Blossoms/android_kernel_oppo_mt6750 https://github.com/Power535/android_kernel_common_MT6763

canyie commented 2 years ago

Found something (Chinese) about Vivo's unqine behavior: https://bbs.pediy.com/thread-268165.htm

This points out adding mount to init.rc can work: https://bbs.pediy.com/thread-199415.htm

jnelson89 commented 2 years ago

Found something (Chinese) about Vivo's unqine behavior: https://bbs.pediy.com/thread-268165.htm

This points out adding mount to init.rc can work: https://bbs.pediy.com/thread-199415.htm

Can you make a build, to fix this?

aIecxs commented 2 years ago

consider Magisk is systemless-root method (and probably will stay)

ASIMKHAN222 commented 2 years ago

Found something (Chinese) about Vivo's unqine behavior: https://bbs.pediy.com/thread-268165.htm

This points out adding mount to init.rc can work: https://bbs.pediy.com/thread-199415.htm

please Guide which Tools we use for unpack or modify System.img to grant root Access

Fox2Code commented 2 years ago

I have though about it a bit, the problem of this issue is Magisk is not marked as a "system process" because it register itself as a service.

Maybe the init system is removing permission from the service processes unless a specific flag is given.

init calling the mount/magisk applet calling the mount syscall should in no way be different of each other.

Maybe a solution would be to make magiskinit sleep in the background until it need to launch magisk itself.

This is to avoid using init.rc services at all cost to not get an unprivileged context from the init process.

canyie commented 2 years ago
  1. adb shell magisk su -c mount xxx /system # Operation not permitted
  2. adb root && adb shell mount xxx /system # OK
  3. adb root && adb shell sh -c mount xxx /system # Operation not permitted
  4. adb shell su # Operation not permitted
  5. adb shell magisk su # OK
  6. adb shell cp /system/bin/echo /data/local/tmp/su && adb shell /data/local/tmp/su # Operation not permitted
  7. adb shell cp /sbin/su /sbin/suu && adb shell /sbin/suu # OK
  8. adb root && adb shell cp /system/bin/mount /sbin && adb shell /sbin/mount # Operation not permitted

According these tests, I think the kernel:

  1. Prevent binary named "su" from being executed
  2. Prevent mounting to /system if the process's grandparent process is not init (in other words, the process is not created by a init's direct child process)
  3. Prevent mounting to /system if the program path is not in allowlist

If so, there must be some weird restrictions in their kernel.

Fox2Code commented 2 years ago

As magisk is directly in the init process it can mount according to theses 3 rules.

Making magisk daemon handle mount/unmount could be a workaround.

Also hex-patching the kernel could also be a viable solution, like what's already done with Samsung defex.

canyie commented 2 years ago

Yes but we still have another issue (apps cannot execute any binary named "su") so I tend to patch the kernel, but I cannot find anything about this weird behavior in their kernel source code. I will upload the source code to github.

Fox2Code commented 2 years ago

Well, making libsu prefer using magisk su rather than su could be a workaround. Sure apps requiring su would not work, but at least apps using libsu could still get access to root.

aIecxs commented 2 years ago

does it affect symlinks?

Fox2Code commented 2 years ago

@aIecxs actually su is already a symlink to magisk, so yes it does affect symlinks.

canyie commented 2 years ago

Uploaded the kernel source code to https://github.com/canyie/iQOO-Z1-kernel Also, source code of iQOO neo3's kernel is available at https://opensource.vivo.com/Project

Parafinchik commented 2 years ago

+

вс, 20 февр. 2022 г., 06:02 jnelson89 @.***>:

Update: Kernel source code of iQOO Z1 is currently available!

Here are my Device Vivo V5 mt6750 kernel sources which can be helpful for you to fix my problem https://github.com/Dawn-Blossoms/android_kernel_oppo_mt6750 https://github.com/Power535/android_kernel_common_MT6763

— Reply to this email directly, view it on GitHub https://github.com/topjohnwu/Magisk/issues/5148#issuecomment-1046158043, or unsubscribe https://github.com/notifications/unsubscribe-auth/AXUS2U5KC5FKQ2OZX3PSOCTU4BRUFANCNFSM5K7ZZK6A . You are receiving this because you are subscribed to this thread.Message ID: @.***>

canyie commented 2 years ago

Trying to execute any binary named "su" in Twoyi (an android container that interprets syscalls and run another Android system on an android device) or even in TWRP will also throw an operation not permitted error. So this may be a hardware restriction, wanna know why they did strange things to their devices 🤔

Fox2Code commented 2 years ago

@canyie it's really common for most TWRP recoveries to use stock kernel to work properly on a device. I still think focusing on analyzing the kernel source code to resolve the issue is the best idea. I already made a pull request to libsu to help workaround the su issue. -> https://github.com/topjohnwu/libsu/pull/104

Fox2Code commented 2 years ago

The "Prevent mounting to /system if the program path is not in allowlist", maybe it's possible to get magisk daemon to be in the allow list by using LD_PRELOAD on a program on the allow list, the mount and sh applets seems to be on the allow list.

yujincheng08 commented 2 years ago

@Fox2Code you got a vivo device? are you sure mount is allowed? as far as we tested, mount still produces EPERM.

but the mount issue can be easily bypassed. i hv done one. the core issue is su. we read the kernel source and nothing helped. so we assume there're some hardware constraints.

Fox2Code commented 2 years ago

@yujincheng08 nah, I'm just theorizing, if I didn't had so many problems in my life and the money I would probably just buy one to try to fix the bug, unfortunately I need to take care of my life first.

canyie commented 2 years ago

(Unconfirmed) A Vivo S5 (Android 10) user reports device refuses to boot if su does exist in PATH. No logs were provided.

romanovj commented 2 years ago

people reporting working magisk on stock rom vivo xfold 24309 vivo x70 pro plus 24306

I have vivo y31 2021, but magisk 24300 can only grant root on LOS 19.1 GSI bvS with removed phh-su. It's can't mount modules, can't mount -o remount,rw /

But adb root can do this. To test zygisk and modules I manualy mounting them during boot process with adb root, adb shell stop etc

12-24 18:48:34.803 980 983 E : mount /sbin/.magisk/zygisk/app_process32->/system/bin/app_process32 failed with 1: Operation not permitted 12-24 18:48:34.803 980 983 E : mount /sbin/.magisk/zygisk/app_process64->/system/bin/app_process64 failed with 1: Operation not permitted 05-24 20:52:50.845 980 983 I : * late_start service mode running 05-24 20:52:50.845 980 983 I : Running service.d scripts 05-24 20:52:50.845 980 983 I : * Running module service scripts 05-24 20:55:08.172 2756 2756 I : zygisk64: replaced com/android/internal/os/Zygote#nativeForkAndSpecialize 05-24 20:55:08.172 2756 2756 I : zygisk64: replaced com/android/internal/os/Zygote#nativeForkSystemServer 05-24 20:55:08.172 2756 2756 I : zygisk64: replaced com/android/internal/os/Zygote#nativeSpecializeAppProcess

qiurigao commented 2 years ago

@topjohnwu

qiurigao commented 2 years ago

Why is there no su limit when uid=0? 为啥uid=0的时候没有su限制呢

qiurigao commented 2 years ago

是的,但我们还有另一个问题(应用程序无法执行任何名为“su”的二进制文件)所以我倾向于修补内核,但我在他们的内核源代码中找不到任何关于这种奇怪行为的信息。我会把源代码上传到github。

不,他只是限制非root用户,如果你切换到adb root 执行su不会收到阻碍

canyie commented 2 years ago

是的,但我们还有另一个问题(应用程序无法执行任何名为“su”的二进制文件)所以我倾向于修补内核,但我在他们的内核源代码中找不到任何关于这种奇怪行为的信息。我会把源代码上传到github。

不,他只是限制非root用户,如果你切换到adb root 执行su不会收到阻碍

但问题是,应用执行不了 su 也就切换不到 root 用户。adb shell 其实是可以执行 su 的,但是 app 就会被拒绝

qiurigao commented 2 years ago

是的,但我们还有另一个问题(应用程序无法执行任何名为“su”的二进制文件)所以我倾向于修补内核,但我在他们的内核源代码中找不到任何关于这种奇怪行为的信息。我会把源代码上传到github。

不,他只是限制非root用户,如果你切换到adb root 执行su不会收到阻碍

但问题是,应用执行不了 su 也就切换不到 root 用户。adb shell 其实是可以执行 su 的,但是 app 就会被拒绝

shell用户(uid=2000)我这边测试的是无法运行文件名为su的任何程序,放切换到root环境(包括TWRP)时,su不会收到限制。 因此我猜想可能是vendor供应商某个.so文件的作用,因为我曾经编译过los,当系统在开机第二屏幕时,su没有限制(此时blob文件未加载)。等进入系统后,su就被限制了。另一个猜想是kernel限制,可是我通过IDA 分析以后,并且修改了所有可能的su字符串,此限制依旧。所以我人为内核的限制可能性较小,如果有可能,有没有办法在twrp环境中使adb shell的权限为uid2000,然后尝试su限制状态

qiurigao commented 2 years ago

是的,但我们还有另一个问题(应用程序无法执行任何名为“su”的二进制文件)所以我倾向于修补内核,但我在他们的内核源代码中找不到任何关于这种奇怪行为的信息。我会把源代码上传到github。

不,他只是限制非root用户,如果你切换到adb root 执行su不会收到阻碍

但问题是,应用执行不了 su 也就切换不到 root 用户。adb shell 其实是可以执行 su 的,但是 app 就会被拒绝

我只是在寻找su限制的具体源头,然后通过eflpatch修改,已达到绕过su限制的目的

canyie commented 2 years ago

So according to #5971 there are some devices don't even allow magiskinit to mount something to /system... wtf?!

qiurigao commented 2 years ago

所以根据#5971有一些设备甚至不允许 magiskinit 将某些东西挂载到 /system... wtf?!

这可能是另一个限制,因为vivo设备运行TWRP环境时,甚至不允许刷写system分区,似乎和su的限制相同,然而官方rec居然没有限制,我猜测是做了某种修改

yujincheng08 commented 2 years ago

哪来那么多猜测,直接编译一个 kernel 测试不就好。

qiurigao commented 2 years ago

来猜猜,直接编译一个内核不就好了。

前提是拥有完整的内核源代码,别指望他们的开源,那些都是半成品

canyie commented 2 years ago

iQOO Z1 的内核源码:https://github.com/canyie/iqoo-z1-kernel ,不知道能不能编译,我是懒得搞了

qiurigao commented 2 years ago

iQOO Z1 的内核内核:https://github.com/canyie/iqoo-z1-kernel,不知道能编译,我是懒得搞了

我安装了lineage-19.1-20220613-UNOFFICIAL-arm64_bvS的GSI后,发现su完全没有限制,adb 和应用均可以执行su,该版本为userdebug,难道是内核限制user版本无法执行su?

canyie commented 2 years ago

@qiurigao 有人用 vivo 官方的 userdebug 测试过了,adb root 可以运行,adb shell 也可以执行 su,但是 app 还是受到限制

qiurigao commented 2 years ago

@qiurigao 有人用 vivo 官方的 userdebug 测试过了,adb root 可以运行,adb shell 也可以执行 su,但是 app 还是受到限制

这个我也测试过刷入boot-debug.img就有adb root,不过仅此而已。可能和system有关 IMG20220616013127

olbb commented 2 years ago

It looks like the kernel is restricting app access to su. But we have a way to make adb shell have root privileges. Is there a way to workaround to make magisk work properly, by manually modifying system files or by adding some magisk files to the system?

yujincheng08 commented 2 years ago

@olbb compile customized kernel

olbb commented 2 years ago

Thank U for reply. I'm afraid I can't because my device's kernel code is not opened.

olbb commented 2 years ago

https://github.com/vivo-source-mirror/Y53s/blob/2b1b1f054ccce7ed551137f0eb1d0cce6976f2aa/fs/vrr_internal.hpp

#if defined(CONFIG_RS_CHECK_FUNC) && defined(CONFIG_MOUNT_RESTRICT)
    #define VIVO_DEFINE_FC_DO_MOUNT_BEGIN_STUB  \
        RS_DEFINE_FC_BEGIN_PUB(do_mount);           \
        RS_FORWARD_FC_END_PUB(do_mount);

    #define VIVO_DEFINE_FC_DO_MOUNT_BODY    RS_DEFINE_FC_BODY(do_mount)

    #define VIVO_DEFINE_FC_DO_MOUNT_END_STUB    \
        RS_DEFINE_FC_END_PUB(do_mount);
#else
    #define VIVO_DEFINE_FC_DO_MOUNT_BEGIN_STUB
    #define VIVO_DEFINE_FC_DO_MOUNT_BODY
    #define VIVO_DEFINE_FC_DO_MOUNT_END_STUB
#endif

https://github.com/vivo-source-mirror/Y53s/blob/2b1b1f054ccce7ed551137f0eb1d0cce6976f2aa/include/linux/vrr.hpp

#define CONFIG_MOUNT_RESTRICT
    /*#define PASS_MOUNT_RESTRICT*/
    #define CONFIG_MOUNT_BIND_MOVE_RESTRICT /*限制 mount -o bind/move*/

Is it restricted here? Whether it can be bypassed by kernel patch?

yujincheng08 commented 2 years ago

I think it should be a won't fix because those configs are too many, and bypassing them one by one is tricky.

olbb commented 2 years ago

Successed! By modify the kernel file with IDA. But it is really difficult to find a common way to patch vivo roms. The address of the restriction method in different roms may be different.

romanovj commented 2 years ago

can you post wich things did you change?

olbb commented 2 years ago

can you post wich things did you change?

The 'do_mount_check' method(Maybe confused in kernel)

@romanovj

romanovj commented 2 years ago

@olbb =( no such method in /proc/kallsyms (vivo y31 2021, sdm662)

qiurigao commented 2 years ago

成功了!通过使用 IDA 修改内核文件。 但是要找到一个通用的方法来修补vivo rom真的很难。 不同的rom中限制方法的地址可能不同。

Can you share your modification process, maybe I can refer to it

olbb commented 2 years ago

Take a look at 'ssc_utils.c' in Y53s's kernel code.

#if 1 /*defined(CONFIG_RS_OBFUSCATED_NAME)*/
/*有可能把user版判为eng版?*/
#define RS_HIDE(name) name##_v_r_s_h_s
#else
#define RS_HIDE(name) name
#endif
#define do_mount_check RS_HIDE(_yb)

The do_mount_check method is confused to "_yb_v_r_s_h_s". Maybe different in different roms. Find the method in ida, and modify and let the method ret 0.

qiurigao commented 2 years ago

关于su的限制在内核中找到了吗