# How Magisk Injects Binaries into the System PATH: The magiskinit Mount Strategy

> Discover how Magisk injects binaries like su into system PATH using its magiskinit mount strategy. Learn how Magisk ensures its commands are prioritized for root access and system modifications.

- Repository: [John Wu/Magisk](https://github.com/topjohnwu/Magisk)
- Tags: internals
- Published: 2026-03-05

---

**Magisk creates a temporary `tmpfs` mount at `/magisk`, populates it with symlinks to its core binaries (`su`, `resetprop`, `magiskpolicy`), and prepends this directory to the global `$PATH` during early init, ensuring all system processes resolve these commands to the Magisk versions before reaching stock ROM binaries.**

Magisk achieves privileged binary interception without modifying the read-only `/system` partition by manipulating the process environment before Android fully boots. According to the topjohnwu/Magisk source code, the injection mechanism relies on `magiskinit` to establish a writable temporary filesystem, extract the necessary binaries from the Magisk APK, and export a modified `PATH` variable that prioritizes Magisk's utilities.

## Creating the MAGISKTMP Mount Point in magiskinit

During the earliest phase of device initialization, `magiskinit` establishes a dedicated staging area for Magisk's binaries. This occurs before the main Android init process begins, ensuring the environment is prepared for all subsequent processes.

### Mounting the tmpfs Filesystem

In [`native/src/init/mount.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/init/mount.cpp), the initialization code creates a writable `tmpfs` filesystem at the fixed location `/magisk`. This provides a volatile, executable directory that persists only for the current boot session:

```cpp
// native/src/init/mount.cpp
mount("tmpfs", "/magisk", "tmpfs", 0, "mode=0755");
setenv("MAGISKTMP", "/magisk", 1);

```

The `mount()` call establishes the directory with `0755` permissions, making it executable and accessible to the processes that need to resolve binaries from this location. The `setenv()` call immediately exports the **`MAGISKTMP`** environment variable, making the mount point path available to helper scripts and subsequent binary installation steps.

## Populating the Temporary Directory with Magisk Binaries

Once the mount point exists, Magisk must place its privileged binaries inside `$MAGISKTMP`. This extraction and linking process is handled by **[`scripts/live_setup.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/live_setup.sh)**, which runs during the pre-init phase.

### Extracting Binaries from the APK

The live setup script extracts the native libraries from the Magisk APK and restructures them as executable commands. Rather than copying multiple files, Magisk creates symbolic links that point various command names to the core `magisk` binary or its specialized tools:

```sh

# scripts/live_setup.sh

# Extract binaries from the APK for the target ABI

unzip -oj magisk.apk "lib/$ABI/*" -x "lib/$ABI/libbusybox.so"

# Create symlinks for the main utilities

ln -s ./magisk $MAGISKTMP/su
ln -s ./magisk $MAGISKTMP/resetprop
ln -s ./magiskpolicy $MAGISKTMP/supolicy

```

Here, **`su`** and **`resetprop`** are symlinked to the main `magisk` binary, which acts as a multi-call binary (similar to BusyBox) and changes behavior based on `argv[0]`. The **`magiskpolicy`** tool is linked separately as `supolicy` to maintain compatibility with legacy scripts while providing SELinux policy manipulation capabilities.

## Injecting the Mount Point into the Global PATH

With the binaries in place, the final step ensures that shell sessions and spawned processes find the Magisk versions before any stock implementations in `/system/bin` or `/vendor/bin`.

### Prepending MAGISKTMP to PATH

Immediately after creating the mount, [`native/src/init/mount.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/init/mount.cpp) modifies the global `PATH` environment variable by prepending `$MAGISKTMP` to the existing value:

```cpp
// native/src/init/mount.cpp – after mounting /magisk
char *old_path = getenv("PATH");
char *new_path;
asprintf(&new_path, "%s:%s", getenv("MAGISKTMP"), old_path ? old_path : "/system/bin");
setenv("PATH", new_path, 1);

```

This operation uses **`asprintf`** to construct a new string with the format `/magisk:<original_path>`, then calls `setenv()` with the overwrite flag set to `1`. Consequently, any process spawned from this environment—including `app_process`, shell sessions, and system services—inherits a `PATH` that resolves `su`, `resetprop`, and `magiskpolicy` to `/magisk/` first.

### System-Wide Binary Resolution

The PATH modification happens early enough in the boot sequence that the Android runtime itself inherits these variables. When an application or script calls `su`, the shell searches directories in the order specified by `PATH`, finding `/magisk/su` before `/system/bin/su`. This mechanism allows Magisk to provide root access and property manipulation without altering the immutable system partition or triggering SafetyNet flags related to system modifications.

## Summary

- **Magisk creates a temporary `tmpfs`** at `/magisk` during early init via `magiskinit`, exporting the path as `MAGISKTMP` in [`native/src/init/mount.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/init/mount.cpp).
- **Binaries are extracted and linked** by [`scripts/live_setup.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/live_setup.sh), which creates symlinks for `su`, `resetprop`, and `magiskpolicy` pointing to the core Magisk binary or its policy tool.
- **PATH manipulation occurs in native code** by prepending `$MAGISKTMP` to the existing `PATH` variable, ensuring all child processes prioritize Magisk binaries over stock alternatives.
- **No system partition modification is required**, as the entire injection relies on runtime environment variables and a volatile mount point that disappears on reboot.

## Frequently Asked Questions

### Why does Magisk use a tmpfs mount instead of directly modifying /system?

Magisk avoids modifying the `/system` partition to maintain a "systemless" approach that does not alter the cryptographic hash of the read-only filesystem. By using a `tmpfs` mount at `/magisk` and modifying the `PATH` variable, Magisk intercepts binary calls without changing the underlying system image, allowing it to pass SafetyNet and similar integrity checks while still providing root access.

### How does the PATH modification persist across different process forks?

The `setenv("PATH", new_path, 1)` call in [`native/src/init/mount.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/init/mount.cpp) executes in the context of `magiskinit`, which becomes the ancestor of the main Android init process. Because environment variables are inherited by child processes through `fork()` and `exec()`, the modified `PATH` propagates automatically to the Zygote, system server, and all application processes without requiring additional injection code in each process.

### What is the relationship between magiskpolicy and the supolicy symlink?

`magiskpolicy` is the dedicated binary for manipulating SELinux policies. In [`scripts/live_setup.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/live_setup.sh), the line `ln -s ./magiskpolicy $MAGISKTMP/supolicy` creates a symlink named `supolicy` that points to the `magiskpolicy` executable. This maintains compatibility with legacy SuperSU scripts and modules that expect a `supolicy` command while using Magisk's modern policy implementation.

### Can the MAGISKTMP location be changed from /magisk?

While the current implementation in [`native/src/init/mount.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/init/mount.cpp) hardcodes `/magisk` as the mount point and exports it via `MAGISKTMP`, changing this would require recompiling `magiskinit` with a modified path string. The location is fixed at compile time to ensure that [`live_setup.sh`](https://github.com/topjohnwu/Magisk/blob/main/live_setup.sh) and other components can reliably locate the binary staging area during the pre-init boot phase.