Magisk/native
topjohnwu a1ce6f5f12 Fix race condition when switching root manager
Before this change, the root manager package name is only written into
the database after the repackaged APK is installed. In the time between
the repackaged APK being installed and the package name being written
into the database, if some operation calls `get_manager`, the Magisk
daemon will cache this result and ignore the repackaged APK, even if
the package name is set afterwards, because the cache won't be
invalidated. The result is that the repackaged manager APK will not be
recognized as the root manager, breaking the hide manager feature.

This race condition is more likely to happen when Zygisk is enabled,
because `get_manager` is called with a very high frequency in that case.

To fix the issue, we have to set the new package name into the database
BEFORE installing the repackaged APK. We also stop pruning the
database if the repackaged manager is not found, moving this logic into
the Magisk app. By doing so, we can guarantee that the instant after
the repackaged manager APK is installed, the Magisk daemon will
immediately pick it up and treat it as the root manager.

Another small optimization: when the requester is root, simply bypass
the whole database + manager package check. Since the Magisk app hiding
APK installation proces will call `su` several times to run `pm` under
different UIDs, doing this opimization will reduce the amount of
unnecessary database query + filesystem traversals.
2023-03-06 03:58:58 -08:00
..
src Fix race condition when switching root manager 2023-03-06 03:58:58 -08:00
.gitignore Support Android Q new init setup 2019-03-03 06:35:25 -05:00
build.gradle.kts Fix SYSTEM_ROOT not passed to boot patch 2023-03-02 23:39:50 -08:00
README.md Restructure the native module 2022-07-23 13:51:56 -07:00

Native Development

Prerequisite

Install the NDK required to build and develop Magisk with ./build.py ndk. The NDK will be installed to $ANDROID_SDK_ROOT/ndk/magisk. You don't need to manually install a Rust toolchain with rustup, as the NDK installed already has a Rust toolchain bundled.

Build Configs

All C/C++ code and its dependencies are built with ndk-build and configured with several *.mk files scattered in many places.

The src folder is also a proper Cargo workspace, and all Rust code is built with cargo just like normal Rust projects.

Rust + C/C++

To reduce complexity involved in linking, all Rust code is built as staticlib and linked to C++ targets to ensure our final product is built with an officially supported NDK build system. Each C++ target can at most link to one Rust staticlib or else multiple definitions error will occur.

We use the cxx project for Rust and C++ interop.

Development / IDE

All C++ code should be recognized and properly indexed by Android Studio out of the box. For Rust:

  • Install the Rust plugin in Android Studio
  • In Preferences > Languages & Frameworks > Rust, set $ANDROID_SDK_ROOT/ndk/magisk/toolchains/rust/bin as the toolchain location
  • Open native/src/Cargo.toml, and select "Attach" in the "No Cargo projects found" banner

Note: run ./build.py binary before developing to make sure generated code is created.