# How Magisk Handles SELinux Policies with magiskpolicy

> Discover how Magisk handles SELinux policies using the magiskpolicy binary. Learn how it patches kernel security at boot for enhanced system control.

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

---

**Magisk handles SELinux policies through the standalone `magiskpolicy` Rust binary, which patches the kernel's security policy at boot by loading the stock configuration, injecting built-in Magisk rules, and merging module-specific statements before writing the result directly to `/sys/fs/selinux/policy`.**

The `topjohnwu/Magisk` repository implements a comprehensive SELinux management system centered on the `magiskpolicy` utility. This tool allows the framework to modify mandatory access controls without recompiling entire policy binaries, enabling root functionality while maintaining Android's security model.

## What Is magiskpolicy and Where It Lives

The `magiskpolicy` binary is a Rust-based utility that serves as the primary interface for SELinux policy manipulation in Magisk.

### Source Code Location

The implementation resides in the native Rust codebase:

- **[`native/src/sepolicy/cli.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/sepolicy/cli.rs)** – Contains the command-line interface implementation, argument parsing, and policy statement handling logic.
- **[`native/src/sepolicy/Cargo.toml`](https://github.com/topjohnwu/Magisk/blob/main/native/src/sepolicy/Cargo.toml)** – Defines the crate configuration and links against `libsepol` for low-level policy operations.

### Build System Integration

The binary is compiled through the Android NDK build system as defined in **`native/src/Android.mk`**, which packages `magiskpolicy` alongside other Magisk native components. During the build process, the Rust crate is compiled into a static binary suitable for Android's execution environment.

### Legacy Compatibility

For backward compatibility with legacy SuperSU scripts, [`scripts/live_setup.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/live_setup.sh) creates a symbolic link exposing `magiskpolicy` as **`supolicy`**:

```bash
ln -s ./magiskpolicy $MAGISKTMP/supolicy

```

This alias ensures existing modules and scripts referencing the older `supolicy` command continue to function correctly.

## Loading and Applying Policies at Boot

During the live-boot stage, Magisk orchestrates policy patching through [`scripts/live_setup.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/live_setup.sh) to establish the necessary security context for daemon operation.

### The Boot-Time Orchestration

The setup script invokes `magiskpolicy` with specific flags to load the device's stock policy and inject Magisk-specific rules:

```bash
./magiskpolicy --load /vendor/etc/selinux/precompiled_sepolicy --live --magisk $RULESCMD
./magiskpolicy --load /sepolicy --live --magisk $RULESCMD
./magiskpolicy --live --magisk $RULESCMD

```

These commands attempt to load the precompiled vendor policy first, falling back to the root `/sepolicy` file if unavailable, and finally operating on the current live policy if neither file exists.

### Command-Line Flags Explained

Each flag serves a distinct function in the policy pipeline:

- **`--load <file>`** – Reads a monolithic policy binary from the specified path (e.g., `/vendor/etc/selinux/precompiled_sepolicy`).
- **`--live`** – Sends the modified policy directly to the kernel via the `/sys/fs/selinux/policy` interface, applying changes immediately without reboot.
- **`--magisk`** – Automatically injects the built-in Magisk rule set, effectively executing `allow magisk * * *` to permit the Magisk domain universal access.

The `$RULESCMD` variable contains additional policy statements supplied by the user or modules, passed internally using the `--apply` mechanism.

## Policy Syntax and Capabilities

The `magiskpolicy` parser, implemented in **[`native/src/sepolicy/cli.rs`](https://github.com/topjohnwu/Magisk/blob/main/native/src/sepolicy/cli.rs)**, supports a statement format mirroring classic SELinux `.te` (Type Enforcement) syntax supplied via command-line arguments.

### Supported Statement Types

According to the documentation in [`docs/tools.md`](https://github.com/topjohnwu/Magisk/blob/main/docs/tools.md), the utility recognizes several policy statement types:

- **`allow *source_type *target_type *class *perm_set`** – Standard access control rules allowing a source domain to perform actions on target objects.
- **`allowxperm …`** – Extended permission rules (X-perm) for ioctl controls, introduced for Android O compatibility.
- **`permissive ^type`** – Switches a specific domain to permissive mode for debugging.
- **`enforce ^type`** – Re-enables enforcing mode for a specified domain.

Arguments may be specified as wildcards (`*`), lists (e.g., `{ s1 s2 }`), or specific identifiers, providing flexibility in rule definition.

## Extending Policies via Magisk Modules

Magisk modules can ship custom SELinux rules without modifying the core policy binary, leveraging the `--apply` interface for safe, isolated extensions.

### Module Policy Files

Modules typically include a **`sepolicy.rules`** file within their directory structure (`/data/adb/modules/<module>/sepolicy.rules`). When Magisk initializes modules during boot, it invokes:

```bash
./magiskpolicy --live --magisk --apply /data/adb/modules/<module>/sepolicy.rules

```

### Runtime Merging Process

The merging logic concatenates parsed statements from the module's rule file into the in-memory policy representation before committing the final policy to the kernel. This approach allows modules to declare necessary permissions (e.g., accessing hardware nodes or system properties) without conflicting with the stock SELinux configuration or other modules.

## Runtime Usage and Developer Workflows

Beyond boot-time automation, `magiskpolicy` functions as a standalone developer tool for debugging and policy analysis.

### Direct Shell Invocation

Developers can invoke the binary directly from an ADB shell or terminal emulator to inspect or modify the current security policy:

```bash

# Display all active rules in the running policy

magiskpolicy --print-rules

# Inject a temporary rule for testing

magiskpolicy --live "allow my_app file file { read write }"

```

### Advanced Policy Operations

The CLI supports additional workflows for policy manipulation:

- **`--save <file>`** – Exports the current live policy to a binary file for offline analysis.
- **`--load-split`** – Handles split policy configurations common in newer Android versions, loading from `/vendor/etc/selinux/precompiled_sepolicy` and associated split contexts.

These capabilities enable developers to extract stock policies, modify them using external tools, and re-inject the modified versions for testing.

## Summary

- **`magiskpolicy`** is a Rust binary located in `native/src/sepolicy/` that serves as Magisk's sole interface for SELinux manipulation.
- At boot, **[`scripts/live_setup.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/live_setup.sh)** invokes the tool with `--load`, `--live`, and `--magisk` flags to patch the kernel policy and establish the `magisk` domain.
- Modules extend policies by placing rules in `sepolicy.rules` files, processed via the `--apply` flag during module loading.
- The tool supports standard SELinux syntax including `allow`, `allowxperm`, and `permissive` statements with wildcard and list expansion.
- Runtime usage via `--print-rules` and `--save` enables debugging and policy analysis without requiring a full rebuild cycle.

## Frequently Asked Questions

### What is the difference between magiskpolicy and supolicy?

`magiskpolicy` is the current binary name for Magisk's SELinux policy tool, while `supolicy` is a legacy alias maintained for backward compatibility. During initialization, [`scripts/live_setup.sh`](https://github.com/topjohnwu/Magisk/blob/main/scripts/live_setup.sh) creates a symbolic link from `magiskpolicy` to `supolicy`, ensuring older modules and scripts referencing the SuperSU-era command continue to function without modification.

### How do I add custom SELinux rules to a Magisk module?

Create a file named `sepolicy.rules` in your module's root directory (`/data/adb/modules/<your-module>/`). Place valid SELinux statements inside using standard Type Enforcement syntax (e.g., `allow my_daemon property_type property_service { set }`). Magisk automatically passes this file to `magiskpolicy --apply` during the boot sequence, merging your rules into the live kernel policy.

### Can I use magiskpolicy to modify policies on a running device?

Yes. The `--live` flag enables runtime policy modification without rebooting. You can execute commands like `magiskpolicy --live "allow my_app device chr_file { read write }"` from a root shell to temporarily extend permissions. However, these changes persist only until the next reboot unless incorporated into a module's `sepolicy.rules` file.

### Where does magiskpolicy store the modified policy?

The tool does not store policies in persistent storage by default. When using `--live`, it writes directly to `/sys/fs/selinux/policy`, modifying the kernel's in-memory policy representation. To save a policy binary for offline editing, use the `--save <filename>` flag, which exports the current live policy to the specified file path.