# How Magisk Handles Mount Namespaces: Global, Requester, and Isolate Modes Explained

> Understand Magisk mount namespaces: Global, Requester, and Isolate modes. Learn how Magisk isolates root processes for enhanced security and control on your Android device.

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

---

**Magisk isolates root-privileged processes by running them inside a mount namespace, offering three distinct modes—Global, Requester, and Isolate—that control whether the root session shares the system's init namespace, inherits the requesting app's namespace, or creates a completely private mount view.**

The **topjohnwu/Magisk** repository implements this namespace isolation in its native core to balance security, compatibility, and user flexibility. Understanding how Magisk handles mount namespaces requires examining the enum definitions in Rust, the database persistence layer, and the C++ daemon logic that executes the namespace switches.

## The Three Mount Namespace Modes

Magisk defines three mount namespace behaviors via the `MntNsMode` enum in **[`native/src/core/lib.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/core/lib.rs)** (lines 93-97). The default mode is **Requester** (`MntNsMode::Requester`), as specified in the `Default` implementation at lines 87-91.

### Global Mode

In **Global** mode, the root session enters the global mount namespace shared by the init process. This provides the same mount view seen by the core system, including the real `/system` layout and all system-wide mounts.

This mode is activated when the user passes the `-M` or `--mount-master` flag to the `su` command. According to the source in **[`native/src/core/su/su.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/core/su/su.cpp)** (lines 52-71), this sets the target PID to 0, which `exec_root_shell()` interprets as a request for the global namespace.

### Requester Mode

**Requester** mode is the default behavior. The root session inherits the mount namespace of the process that requested root access (the PID that invoked `su`).

When parsing command-line arguments in [`su.cpp`](https://github.com/topjohnwu/Magisk/blob/main/su.cpp), if the `-t <PID>` flag is provided, the daemon uses that specific PID's namespace. Otherwise, it defaults to the caller's PID. The daemon logs this with `LOGD("su: use namespace of pid=[%d]\n", req.target_pid)` before calling `switch_mnt_ns(req.target_pid)` to enter the target namespace.

### Isolate Mode

**Isolate** mode creates a brand-new private mount namespace detached from the rest of the system. This provides the strongest isolation, ensuring the root session cannot see mounts from other apps or processes.

When this mode is selected (either via Magisk Settings or forced under specific conditions), `exec_root_shell()` performs a sequence of operations:
1. Enters the requester's namespace via `switch_mnt_ns()`
2. Calls `xunshare(CLONE_NEWNS)` to create a fresh namespace
3. Executes `xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr)` to make the new namespace private and prevent mount propagation

## Namespace Configuration Storage

Magisk persists the user's preferred mount namespace mode in its internal SQLite database. The setting is stored under the key **`mnt_ns`** (represented as `DbEntryKey::SuMntNs` in the Rust code).

The database interactions are handled in **[`native/src/core/db.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/core/db.rs)** (lines 48-55). The daemon reads the current mode via `MagiskD::get_db_setting()` and writes updates through `set_db_setting()`. This allows the mount namespace behavior to survive daemon restarts and persist across reboots.

## Command-Line Interface and Request Parsing

The `su` binary serves as the command-line interface for namespace selection. Located at **[`native/src/core/su/su.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/core/su/su.cpp)**, the parser translates user flags into `SuRequest` fields:

| Option | Namespace Effect |
|--------|------------------|
| `-M` or `--mount-master` | Forces **Global** mode (uses init's namespace) |
| `-t <PID>` | Forces **Requester** mode for the specific PID |
| No flag (with Isolate setting) | Creates a new **Isolate** namespace |

The `exec_root_shell()` function processes these requests with logic that handles edge cases. For example, if `-M` (Global) is combined with `-t` (explicit PID), the daemon falls back to **Requester** mode rather than using the global namespace.

## Daemon Implementation and Namespace Switching

The actual namespace transition occurs in `exec_root_shell()` within **[`native/src/core/su/su.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/core/su/su.cpp)**. This function implements a switch statement that handles each `MntNsMode` variant:

```cpp
switch (mode) {
    case MntNsMode::Global:
        LOGD("su: use global namespace\n");
        break;
    case MntNsMode::Requester:
        LOGD("su: use namespace of pid=[%d]\n", req.target_pid);
        switch_mnt_ns(req.target_pid);
        break;
    case MntNsMode::Isolate:
        LOGD("su: use new isolated namespace\n");
        switch_mnt_ns(req.target_pid);
        xunshare(CLONE_NEWNS);
        xmount(nullptr, "/", nullptr,
               MS_PRIVATE | MS_REC, nullptr);
        break;
}

```

The low-level namespace switching is performed by `switch_mnt_ns(int pid)`, defined in **[`native/src/base/base.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/base/base.cpp)** (lines 89-106). This function implements a robust fallback mechanism:

1. First attempts modern kernel APIs: `pidfd_open()` followed by `setns()`
2. Falls back to the legacy method: opening `/proc/<pid>/ns/mnt` and calling `setns()` on the resulting file descriptor

This ensures compatibility across Android kernel versions while maintaining the ability to enter arbitrary process namespaces.

## Practical Usage Examples

Here are concrete examples demonstrating each mount namespace mode:

```bash

# Default Requester mode - inherits the calling app's namespace

$ su

# Global mode - shares the init process mount namespace

$ su -M

# Explicitly enter the namespace of a specific process (PID 1234)

$ su -t 1234

# Isolate mode - creates a private namespace (when configured in settings)

$ su

```

In **Global** mode, tools like `mount` show the complete system mount tree identical to the init process view. In **Requester** mode, the shell sees the same mounts as the requesting application, preserving app-specific storage views. In **Isolate** mode, the shell sees only the base rootfs mounts with no visibility into other process mounts.

## Summary

- Magisk implements three mount namespace modes—**Global**, **Requester**, and **Isolate**—defined in [`native/src/core/lib.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/core/lib.rs) as the `MntNsMode` enum.
- The default **Requester** mode inherits the namespace of the calling PID, while **Global** (`-M` flag) uses the init namespace and **Isolate** creates a private namespace.
- Configuration persists in the SQLite database via `DbEntryKey::SuMntNs`, handled in [`native/src/core/db.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/core/db.rs).
- The `su` daemon processes namespace requests in `exec_root_shell()` and executes switches via `switch_mnt_ns()` in [`native/src/base/base.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/base/base.cpp), using `pidfd_open` with a `/proc` fallback.

## Frequently Asked Questions

### What is the default mount namespace mode in Magisk?

The default mode is **Requester** (`MntNsMode::Requester`), as implemented in the `Default` trait for the enum in [`native/src/core/lib.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/core/lib.rs). This means that unless you specify otherwise with `-M` or the Magisk Settings are changed, every root session inherits the mount namespace of the application that called `su`.

### When should I use Global mount namespace mode?

Use **Global** mode (activated with `su -M`) when you need access to the system's true mount layout, such as when running tools that depend on the real `/system` partition structure or when debugging system-level mount issues. This mode places your shell in the same namespace as the init process, bypassing any app-specific mount views.

### How does Magisk handle namespace switching on older Android kernels?

The `switch_mnt_ns()` function in [`native/src/base/base.cpp`](https://github.com/topjohnwu/Magisk/blob/main/native/src/base/base.cpp) implements a dual-path approach. It first attempts to use the modern `pidfd_open()` syscall combined with `setns()`. If the kernel lacks pidfd support, it automatically falls back to opening `/proc/<pid>/ns/mnt` directly and calling `setns()` on that file descriptor, ensuring compatibility with older Android versions.