add main branch files

This commit is contained in:
樱檩殇雪
2025-03-17 02:38:37 +08:00
commit a6e3221bdc
360 changed files with 44453 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
# App Profile
The App Profile is a mechanism provided by KernelSU for customizing the configuration of various apps.
For apps granted root permissions (i.e., able to use `su`), the App Profile can also be referred to as the Root Profile. It allows customization of the `uid`, `gid`, `groups`, `capabilities`, and `SELinux` rules of the `su` command, thereby restricting the privileges of the root user. For example, it can grant network permissions only to firewall apps while denying file access permissions, or it can grant shell permissions instead of full root access for freeze apps: **keeping the power confined with the principle of least privilege.**
For ordinary apps without root permissions, the App Profile can control the behavior of the kernel and module system towards these apps. For instance, it can determine whether modifications resulting from modules should be addressed. The kernel and module system can make decisions based on this configuration, such as performing operations akin to "hiding".
## Root Profile
### UID, GID, and Groups
Linux systems have two concepts: users and groups. Each user has a user ID (UID), and a user can belong to multiple groups, each with its own group ID (GID). These IDs are used to identify users in the system and determine which system resources they can access.
Users with a UID of 0 are known as root users, and groups with a GID of 0 are known as root groups. The root user group generally has the highest system privileges.
In the case of the Android system, each app functions as a separate user (except in cases of shared UIDs) with a unique UID. For example, `0` represents the root user, `1000` represents `system`, `2000` represents the ADB shell, and UIDs ranging from `10000` to `19999` represent ordinary apps.
::: info
Here, the UID mentioned isn't the same as the concept of multiple users or work profiles in the Android system. Work profiles are actually implemented by partitioning the UID range. For example, 10000-19999 represents the main user, while 110000-119999 represents a work profile. Each ordinary app among them has its own unique UID.
:::
Each app can have several groups, with the GID representing the primary group, which usually matches the UID. Other groups are known as supplementary groups. Certain permissions are controlled through groups, such as network access permissions or Bluetooth access.
For example, if we execute the `id` command in ADB shell, the output might look like this:
```sh
oriole:/ $ id
uid=2000(shell) gid=2000(shell) groups=2000(shell),1004(input),1007(log),1011(adb),1015(sdcard_rw),1028(sdcard_r),1078(ext_data_rw),1079(ext_obb_rw),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats),3009(readproc),3011(uhid),3012(readtracefs) context=u:r:shell:s0
```
Here, the UID is `2000`, and the GID (primary group ID) is also `2000`. Additionally, it belongs to several supplementary groups, such as `inet` (indicating the ability to create `AF_INET` and `AF_INET6` sockets) and `sdcard_rw` (indicating read/write permissions for the SD card).
KernelSU's Root Profile allows customization of the UID, GID, and groups for the root process after executing `su`. For example, the Root Profile of a root app can set its UID to `2000`, which means that when using `su`, the app's actual permissions are at the ADB shell level. Additionally, the `inet` group can be removed, preventing the `su` command from accessing the network.
::: tip NOTE
The App Profile only controls the permissions of the root process after using `su` and doesn't control the app's own permissions. If an app has requested network access permission, it can still access the network even without using `su`. Removing the `inet` group from `su` only prevents `su` from accessing the network.
:::
Root Profile is enforced in the kernel and doesn't rely on the voluntary behavior of root apps, unlike switching users or groups through `su`. Granting `su` permissions is entirely controlled by the user, not the developer.
### Capabilities
Capabilities are a mechanism for privilege separation in Linux.
For the purpose of performing permission checks, traditional `UNIX` implementations distinguish two categories of processes: privileged processes (whose effective user ID is `0`, referred to as superuser or root) and unprivileged processes (whose effective UID is nonzero). Privileged processes bypass all kernel permission checks, while unprivileged processes are subject to full permission checking based on the process's credentials (usually: effective UID, effective GID, and supplementary group list).
Starting with Linux 2.2, Linux divides the privileges traditionally associated with superuser into distinct units, known as capabilities, which can be independently enabled and disabled.
Each capability represents one or more privileges. For example, `CAP_DAC_READ_SEARCH` represents the ability to bypass permission checks for file reading, as well as directory read and execute permissions. If a user with an effective UID of `0` (root user) doesn't have the `CAP_DAC_READ_SEARCH` capability or higher, this means that even as root, they cannot freely read files.
KernelSU's Root Profile allows customization of the capabilities of the root process after executing `su`, thus granting partial "root privileges". Unlike the UID and GID mentioned above, certain root apps require a UID of `0` after using `su`. In such cases, limiting the capabilities of this root user with UID `0` can restrict the operations they're allowed to perform.
::: tip STRONG RECOMMENDATION
Linux's capability [official documentation](https://man7.org/linux/man-pages/man7/capabilities.7.html) provides detailed explanations of the abilities represented by each capability. If you intend to customize capabilities, it's strongly recommended that you read this document first.
:::
### SELinux
SELinux is a powerful Mandatory Access Control (MAC) mechanism. It operates on the principle of **default deny**. Any action not explicitly allowed is denied.
SELinux can run in two global modes:
1. Permissive mode: Denial events are logged, but not enforced.
2. Enforcing mode: Denial events are logged and enforced.
::: warning
Modern Android systems heavily rely on SELinux to ensure overall system security. It's highly recommended not to use any custom systems running in "Permissive mode" since it provides no significant advantages over a completely open system.
:::
Explaining the full concept of SELinux is complex and beyond the scope of this document. It's recommended to first understand how it works through the following resources:
1. [Wikipedia](https://en.wikipedia.org/wiki/Security-Enhanced_Linux)
2. [Red Hat: What Is SELinux?](https://www.redhat.com/en/topics/linux/what-is-selinux)
3. [ArchLinux: SELinux](https://wiki.archlinux.org/title/SELinux)
KernelSU's Root Profile allows customization of the SELinux context of the root process after executing `su`. Specific access control rules can be set for this context, enabling fine-grained control over root permissions.
In typical scenarios, when an app executes `su`, it switches the process to a SELinux domain with **unrestricted access**, such as `u:r:su:s0`. Through the Root Profile, this domain can be switched to a custom domain, such as `u:r:app1:s0`, and a series of rules can be defined for this domain:
```sh
type app1
enforce app1
typeattribute app1 mlstrustedsubject
allow app1 * * *
```
Note that the `allow app1 * * *` rule is used for demonstration purposes only. In practice, this rule shouldn't be used extensively, as it isn't much different from Permissive mode.
### Escalation
If the configuration of the Root Profile isn't set properly, an escalation scenario may occur. The restrictions imposed by the Root Profile can unintentionally fail.
For example, if you grant root permission to an ADB shell user (which is a common case) and then grant root permission to a regular app, but configure its Root Profile with UID 2000 (which is the UID of the ADB shell user), the app can obtain full root access by executing the `su` command twice:
1. The first execution of `su` will be subject to the App Profile and will switch to UID `2000` (ADB shell) instead of `0` (root).
2. The second execution of `su`, since the UID is `2000` and root access has been granted to UID `2000` (ADB shell) in the configuration, the app will gain full root privileges.
::: warning NOTE
This behavior is fully expected and isn't a bug. Therefore, we recommend the following:
If you genuinely need to grant root permissions to ADB (e.g., as a developer), it isn't advisable to change the UID to `2000` when configuring the Root Profile. Using `1000` (system) would be a better choice.
:::
## Non-root profile
### Umount modules
KernelSU provides a systemless mechanism to modify system partitions, achieved through the mounting of OverlayFS. However, some apps may be sensitive to this behavior. In this case, we can unload modules mounted in these apps by setting the "Umount modules" option.
Additionally, the KernelSU manager's settings interface provides the "Umount modules by default". By default, this option is **enabled**, which means that KernelSU or some modules will unload modules for this app unless additional settings are applied. If you don't prefer this setting or if it affects certain apps, you have the following options:
1. Keep the "Umount modules by default" option enabled and individually disable the "Umount modules" option in the App Profile for apps requiring module loading (acting as a "whitelist").
2. Disable the "Umount modules by default" option and individually enable the "Umount modules" option in the App Profile for apps requiring module loading (acting as a "blacklist").
::: info
In devices running kernel version 5.10 and above, the kernel performs without any further action the unloading of modules. However, for devices running kernel versions below 5.10, this option is merely a configuration setting, and KernelSU itself doesn't take any action. If you want to use the "Umount modules" option in kernel versions before 5.10 you need to backport the `path_umount` function in `fs/namespace.c`. You can get more information at the end of the [Intergrate for non-GKI devices](https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#how-to-backport-path_umount) page. Some modules, such as Zygisksu, may also use this option to determine if module unloading is necessary.
:::

View File

@@ -0,0 +1,28 @@
# Difference with Magisk
Although KernelSU and Magisk modules have many similarities, there are inevitably some differences due to their completely different implementation mechanisms. If you want your module to work on both Magisk and KernelSU, it's essential to understand these differences.
## Similarities
- Module file format: Both use the ZIP format to organize modules, and the module format is practically the same.
- Module installation directory: Both are located at `/data/adb/modules`.
- Systemless: Both support modifying `/system` in a systemless way through modules.
- post-fs-data.sh: Execution time and semantics are exactly the same.
- service.sh: Execution time and semantics are exactly the same.
- system.prop: Completely the same.
- sepolicy.rule: Completely the same.
- BusyBox: Scripts are run in BusyBox with "Standalone Mode" enabled in both cases.
## Differences
Before understanding the differences, it's important to know how to identify whether your module is running in KernelSU or Magisk. You can use the environment variable `KSU` to differentiate it in all places where you can run module scripts (`customize.sh`, `post-fs-data.sh`, `service.sh`). In KernelSU, this environment variable will be set to `true`.
Here are some differences:
- KernelSU modules cannot be installed in Recovery mode.
- KernelSU modules don't have built-in support for Zygisk, but you can use Zygisk modules through [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext)).
- The method for replacing or deleting files in KernelSU modules is completely different from Magisk. KernelSU doesn't support the `.replace` method. Instead, you need to create a same-named file with `mknod filename c 0 0` to delete the corresponding file.
- The directories for BusyBox are different. The built-in BusyBox in KernelSU is located at `/data/adb/ksu/bin/busybox`, while in Magisk it is at `/data/adb/magisk/busybox`. **Note that this is an internal behavior of KernelSU and may change in the future!**
- KernelSU doesn't support `.replace` files, but it supports the `REMOVE` and `REPLACE` variables to remove or replace files and folders.
- KernelSU adds the `boot-completed` stage to run scripts after the boot process is finished.
- KernelSU adds the `post-mount` stage to run scripts after OverlayFS is mounted.

78
website/docs/guide/faq.md Normal file
View File

@@ -0,0 +1,78 @@
# FAQ
## Does KernelSU support my device?
First, your devices should be able to unlock the bootloader. If not, then there is unsupported.
Next, install the KernelSU manager on your device and open it. If it shows `Unsupported`, then your device cannot be supported immediately. However, you can build kernel source and integrate KernelSU to make it work, or use [Unofficially supported devices](unofficially-support-devices).
## Does KernelSU need to unlock bootloader?
Certainly, yes.
## Does KernelSU support modules?
Yes, check [Module guide](module.md).
## Does KernelSU support Xposed?
Yes, you can use LSPosed with [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext).
## Does KernelSU support Zygisk?
KernelSU has no built-in Zygisk support, but you can use [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext).
## Is KernelSU compatible with Magisk?
KernelSU's module system conflicts with Magisk's magic mount. If any module is enabled in KernelSU, Magisk will stop working entirely.
However, if you only use the `su` of KernelSU, it will work well with Magisk. KernelSU modifies the `kernel`, while Magisk modifies the `ramdisk`, allowing both to work together.
## Will KernelSU substitute Magisk?
We believe that it isn't, and that isn't our goal. Magisk is good enough for userspace root solution and will have a long life. KernelSU's goal is to provide a kernel interface to users, not substituting Magisk.
## Can KernelSU support non-GKI devices?
It's possible. But you should download the kernel source and intergrate KernelSU into the source tree, and compile the kernel yourself.
## Can KernelSU support devices below Android 12?
It's the device's kernel that affects KernelSU's compatibility, and it has nothing to do with the Android version. The only restriction is that devices launched with Android 12 must have a kernel version of 5.10+ (GKI devices). So:
1. Devices launched with Android 12 must be supported.
2. Devices with an older kernel (some devices with Android 12 also have the older kernel) are compatible (you should build kernel yourself).
## Can KernelSU support old kernel?
It's possible. KernelSU is backported to kernel 4.14 now. For older kernels, you need to backport it manually, and PRs are always welcome!
## How to integrate KernelSU for an older kernel?
Please check the [Intergrate for non-GKI devices](how-to-integrate-for-non-gki) guide.
## Why my Android version is 13, and the kernel shows "android12-5.10"?
The kernel version has nothing to do with the Android version. If you need to flash kernel, always use the kernel version; the Android version isn't as important.
## I'm GKI 1.0, can I use this?
GKI 1.0 is completely different from GKI 2.0, you must compile kernel by yourself.
## How can I make `/system` RW?
We don't recommend that you modify the system partition directly. Please check [Module guide](module.md) to modify it systemlessly. If you insist on doing this, check [magisk_overlayfs](https://github.com/HuskyDG/magic_overlayfs).
## Can KernelSU modify hosts? How can I use AdAway
Of course. But KernelSU doesn't have built-in hosts support, you can install [systemless-hosts](https://github.com/symbuzzer/systemless-hosts-KernelSU-module) to do it.
## Why is there a huge 1 TB file?
The 1 TB `modules.img` file is a disk image file. **Don't worry about its size**; it's a special type of file known as a [sparse file](https://en.wikipedia.org/wiki/Sparse_file). Its actual size is only the size of the module you use, and it will decrease dynamically after you delete the module. In fact, it doesn't occupy 1 TB of disk space (your device might not even have that much space).
If you really care about the size of this file, you can use the `resize2fs -M` command to make it the actual size. However, the module may not work correctly in this case, and we won't provide any support for this.
## Why does my device show wrong storage size?
Certain devices use non-standard methods to calculate the device's storage size, which may lead to inaccurate storage calculations in system apps and menus, especially when dealing with 1 TB sparse files. Although this problem seems to be specific to Samsung devices, affecting only Samsung apps and services, it's important to note that the discrepancy mainly concerns the total storage size, and the free space calculation remains accurate.

View File

@@ -0,0 +1,7 @@
# Hidden features
## .ksurc
By default, `/system/bin/sh` loads `/system/etc/mkshrc`.
You can make su load customized rc file by creating a `/data/adb/ksu/.ksurc` file.

View File

@@ -0,0 +1,71 @@
# How to build
First, you should read the official Android documentation for kernel build:
1. [Build kernels](https://source.android.com/docs/setup/build/building-kernels)
2. [GKI release builds](https://source.android.com/docs/core/architecture/kernel/gki-release-builds)
::: warning
This page is for GKI devices, if you use an old kernel, please refer [Intergrate for non-GKI devices](how-to-integrate-for-non-gki).
:::
## Build kernel
### Sync the kernel source code
```sh
repo init -u https://android.googlesource.com/kernel/manifest
mv <kernel_manifest.xml> .repo/manifests
repo init -m manifest.xml
repo sync
```
The `<kernel_manifest.xml>` file is a manifest that uniquely identifies a build, allowing you to make it reproducible. To do this, you should download the manifest file from [GKI release builds](https://source.android.com/docs/core/architecture/kernel/gki-release-builds).
### Build
Please check the [Building kernels](https://source.android.com/docs/setup/build/building-kernels) first.
For example, to build an `aarch64` kernel image:
```sh
LTO=thin BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh
```
Don't forget to add the `LTO=thin` flag; otherwise, the build may fail if your computer has less than 24 GB of memory.
Starting from Android 13, the kernel is built by `bazel`:
```sh
tools/bazel build --config=fast //common:kernel_aarch64_dist
```
::: info
For some Android 14 kernels, to make Wi-Fi/Bluetooth work, it might be necessary to remove all GKI protected exports:
```sh
rm common/android/abi_gki_protected_exports_*
```
:::
## Build kernel with KernelSU
If you can successfully build the kernel, adding support for KernelSU will be relatively easy. In the root of kernel source directory, run any of the options listed below:
::: code-group
```sh[Latest tag (stable)]
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -
```
```sh[ main branch (dev)]
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s main
```
```sh[Select tag (such as v0.5.2)]
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.5.2
```
:::
Then, rebuild the kernel and you will get a kernel image with KernelSU!

View File

@@ -0,0 +1,377 @@
# Intergrate for non-GKI devices
KernelSU can be integrated into non-GKI kernels and was backported to 4.14 and earlier versions.
Due to the fragmentation of non-GKI kernels, we don't have a universal method to build it, so we cannot provide the non-GKI boot.img. However, you can build the kernel with KernelSU integrated on your own.
First, you should be able to build a bootable kernel from kernel source code. If the kernel isn't open source, then it is difficult to run KernelSU for your device.
If you're able to build a bootable kernel, there are two ways to integrate KernelSU into the kernel source code:
1. Automatically with `kprobe`
2. Manually
## Integrate with kprobe
KernelSU uses kprobe to do kernel hooks, if kprobe runs well in your kernel, it's recommended to use it this way.
First, add KernelSU to your kernel source tree:
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5
```
::: info
[KernelSU 1.0 and later versions no longer support non-GKI kernels](https://github.com/tiann/KernelSU/issues/1705). The last supported version is `v0.9.5`, so make sure to use the correct version.
:::
Then, you should check if kprobe is enabled in your kernel config. If it isn't, add these configs to it:
```txt
CONFIG_KPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_KPROBE_EVENTS=y
```
Now, when you re-build your kernel, KernelSU should work correctly.
If you find that KPROBES is still not enabled, you can try enabling `CONFIG_MODULES`. If that doesn't solve the issue, use `make menuconfig` to search for other KPROBES dependencies.
However, if you encounter a bootloop after integrating KernelSU, this may indicate that the **kprobe is broken in your kernel**, which means that you should fix the kprobe bug or use another way.
::: tip HOW TO CHECK IF KPROBE IS BROKEN
Comment out `ksu_enable_sucompat()` and `ksu_enable_ksud()` in `KernelSU/kernel/ksu.c`, if the device boots normally, then kprobe may be broken.
:::
::: info HOW TO GET MODULE UMOUNT FEATURE WORKING ON PRE-GKI?
If your kernel is older than 5.9, you should backport `path_umount` to `fs/namespace.c`. This is required to get "Umount module" feature work correctly. If you don't backport `path_umount`, "Umount module" feature won't work. You can get more info on how to achieve this at the end of this page.
:::
## Manually modify the kernel source
If kprobe doesn't work on your kernel this may be caused by an upstream bug or if the kernel is below 4.8), then you can try the following:
First, add KernelSU to your kernel source tree:
```sh
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.5
```
Keep in mind that, on some devices, your defconfig may be located at `arch/arm64/configs` or in other cases, it may be at `arch/arm64/configs/vendor/your_defconfig`. Regardless of the defconfig you're using, make sure to enable `CONFIG_KSU` with `y` to enable or `n` to disable it. For example, if you choose to enable it, your defconfig should contain the following string:
```txt
# KernelSU
CONFIG_KSU=y
```
Next, add KernelSU calls to the kernel source. Below are some patches for reference:
::: code-group
```diff[exec.c]
diff --git a/fs/exec.c b/fs/exec.c
index ac59664eaecf..bdd585e1d2cc 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1890,11 +1890,14 @@ static int __do_execve_file(int fd, struct filename *filename,
return retval;
}
+#ifdef CONFIG_KSU
+extern bool ksu_execveat_hook __read_mostly;
+extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr, void *argv,
+ void *envp, int *flags);
+extern int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
+ void *argv, void *envp, int *flags);
+#endif
static int do_execveat_common(int fd, struct filename *filename,
struct user_arg_ptr argv,
struct user_arg_ptr envp,
int flags)
{
+ #ifdef CONFIG_KSU
+ if (unlikely(ksu_execveat_hook))
+ ksu_handle_execveat(&fd, &filename, &argv, &envp, &flags);
+ else
+ ksu_handle_execveat_sucompat(&fd, &filename, &argv, &envp, &flags);
+ #endif
return __do_execve_file(fd, filename, argv, envp, flags, NULL);
}
```
```diff[open.c]
diff --git a/fs/open.c b/fs/open.c
index 05036d819197..965b84d486b8 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -348,6 +348,8 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
return ksys_fallocate(fd, mode, offset, len);
}
+#ifdef CONFIG_KSU
+extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
+ int *flags);
+#endif
/*
* access() needs to use the real uid/gid, not the effective uid/gid.
* We do this by temporarily clearing all FS-related capabilities and
@@ -355,6 +357,7 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
*/
long do_faccessat(int dfd, const char __user *filename, int mode)
{
const struct cred *old_cred;
struct cred *override_cred;
struct path path;
struct inode *inode;
struct vfsmount *mnt;
int res;
unsigned int lookup_flags = LOOKUP_FOLLOW;
+ #ifdef CONFIG_KSU
+ ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
+ #endif
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
return -EINVAL;
```
```diff[read_write.c]
diff --git a/fs/read_write.c b/fs/read_write.c
index 650fc7e0f3a6..55be193913b6 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -434,10 +434,14 @@ ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
}
EXPORT_SYMBOL(kernel_read);
+#ifdef CONFIG_KSU
+extern bool ksu_vfs_read_hook __read_mostly;
+extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr,
+ size_t *count_ptr, loff_t **pos);
+#endif
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
ssize_t ret;
+ #ifdef CONFIG_KSU
+ if (unlikely(ksu_vfs_read_hook))
+ ksu_handle_vfs_read(&file, &buf, &count, &pos);
+ #endif
+
if (!(file->f_mode & FMODE_READ))
return -EBADF;
if (!(file->f_mode & FMODE_CAN_READ))
```
```diff[stat.c]
diff --git a/fs/stat.c b/fs/stat.c
index 376543199b5a..82adcef03ecc 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -148,6 +148,8 @@ int vfs_statx_fd(unsigned int fd, struct kstat *stat,
}
EXPORT_SYMBOL(vfs_statx_fd);
+#ifdef CONFIG_KSU
+extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
+#endif
+
/**
* vfs_statx - Get basic and extra attributes by filename
* @dfd: A file descriptor representing the base dir for a relative filename
@@ -170,6 +172,7 @@ int vfs_statx(int dfd, const char __user *filename, int flags,
int error = -EINVAL;
unsigned int lookup_flags = LOOKUP_FOLLOW | LOOKUP_AUTOMOUNT;
+ #ifdef CONFIG_KSU
+ ksu_handle_stat(&dfd, &filename, &flags);
+ #endif
if ((flags & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
AT_EMPTY_PATH | KSTAT_QUERY_FLAGS)) != 0)
return -EINVAL;
```
:::
You should find the four functions in kernel source:
1. `do_faccessat`, usually in `fs/open.c`
2. `do_execveat_common`, usually in `fs/exec.c`
3. `vfs_read`, usually in `fs/read_write.c`
4. `vfs_statx`, usually in `fs/stat.c`
If your kernel doesn't have the `vfs_statx` function, use `vfs_fstatat` instead:
```diff
diff --git a/fs/stat.c b/fs/stat.c
index 068fdbcc9e26..5348b7bb9db2 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -87,6 +87,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
}
EXPORT_SYMBOL(vfs_fstat);
+#ifdef CONFIG_KSU
+extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
+#endif
int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
int flag)
{
@@ -94,6 +96,8 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
int error = -EINVAL;
unsigned int lookup_flags = 0;
+ #ifdef CONFIG_KSU
+ ksu_handle_stat(&dfd, &filename, &flag);
+ #endif
+
if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
AT_EMPTY_PATH)) != 0)
goto out;
```
For kernels eariler than 4.17, if you cannot find `do_faccessat`, just go to the definition of the `faccessat` syscall and place the call there:
```diff
diff --git a/fs/open.c b/fs/open.c
index 2ff887661237..e758d7db7663 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -355,6 +355,9 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
return error;
}
+#ifdef CONFIG_KSU
+extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
+ int *flags);
+#endif
+
/*
* access() needs to use the real uid/gid, not the effective uid/gid.
* We do this by temporarily clearing all FS-related capabilities and
@@ -370,6 +373,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
int res;
unsigned int lookup_flags = LOOKUP_FOLLOW;
+ #ifdef CONFIG_KSU
+ ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
+ #endif
+
if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
return -EINVAL;
```
### Safe Mode
To enable KernelSU's built-in Safe Mode, you should modify the `input_handle_event` function in `drivers/input/input.c`:
::: tip
It's strongly recommended to enable this feature, it's very useful for preventing bootloops!
:::
```diff
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 45306f9ef247..815091ebfca4 100755
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -367,10 +367,13 @@ static int input_get_disposition(struct input_dev *dev,
return disposition;
}
+#ifdef CONFIG_KSU
+extern bool ksu_input_hook __read_mostly;
+extern int ksu_handle_input_handle_event(unsigned int *type, unsigned int *code, int *value);
+#endif
+
static void input_handle_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
int disposition = input_get_disposition(dev, type, code, &value);
+ #ifdef CONFIG_KSU
+ if (unlikely(ksu_input_hook))
+ ksu_handle_input_handle_event(&type, &code, &value);
+ #endif
if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN)
add_input_randomness(type, code, value);
```
::: info ENTERING SAFE MODE ACCIDENTALLY?
If you're using manual integration and don't disable `CONFIG_KPROBES`, the user will be able to trigger Safe Mode by pressing the volume down button after booting! Therefore, if you're using manual integration, it's necessary to disable `CONFIG_KPROBES`!
:::
### Failed to execute `pm` in terminal?
You should modify `fs/devpts/inode.c`. Reference:
```diff
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c
index 32f6f1c68..d69d8eca2 100644
--- a/fs/devpts/inode.c
+++ b/fs/devpts/inode.c
@@ -602,6 +602,8 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
return dentry;
}
+#ifdef CONFIG_KSU
+extern int ksu_handle_devpts(struct inode*);
+#endif
+
/**
* devpts_get_priv -- get private data for a slave
* @pts_inode: inode of the slave
@@ -610,6 +612,7 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
*/
void *devpts_get_priv(struct dentry *dentry)
{
+ #ifdef CONFIG_KSU
+ ksu_handle_devpts(dentry->d_inode);
+ #endif
if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC)
return NULL;
return dentry->d_fsdata;
```
### How to backport path_umount
You can make the "Umount modules" feature work on pre-GKI kernels by manually backporting `path_umount` from 5.9. You can use this patch as reference:
```diff
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1739,6 +1739,39 @@ static inline bool may_mandlock(void)
}
#endif
+static int can_umount(const struct path *path, int flags)
+{
+ struct mount *mnt = real_mount(path->mnt);
+
+ if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
+ return -EINVAL;
+ if (!may_mount())
+ return -EPERM;
+ if (path->dentry != path->mnt->mnt_root)
+ return -EINVAL;
+ if (!check_mnt(mnt))
+ return -EINVAL;
+ if (mnt->mnt.mnt_flags & MNT_LOCKED) /* Check optimistically */
+ return -EINVAL;
+ if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ return 0;
+}
+
+int path_umount(struct path *path, int flags)
+{
+ struct mount *mnt = real_mount(path->mnt);
+ int ret;
+
+ ret = can_umount(path, flags);
+ if (!ret)
+ ret = do_umount(mnt, flags);
+
+ /* we mustn't call path_put() as that would clear mnt_expiry_mark */
+ dput(path->dentry);
+ mntput_no_expire(mnt);
+ return ret;
+}
/*
* Now umount can handle mount points as well as block devices.
* This is important for filesystems which use unnamed block devices.
```
Finally, build your kernel again, and KernelSU should work correctly.

View File

@@ -0,0 +1,280 @@
# Installation
## Check if your device is supported
Download KernelSU manager from [GitHub Releases](https://github.com/tiann/KernelSU/releases) and install it on your device:
- If the app shows `Unsupported`, it means that **you should compile the kernel yourself**, KernelSU won't and never provide a boot.img file for you to flash.
- If the app shows `Not installed`, then your device is officially supported by KernelSU.
::: info
For devices showing `Unsupported`, you can check the list of [Unofficially supported devices](unofficially-support-devices.md). You can compile the kernel yourself.
:::
## Backup stock boot.img
Before flashing, it's essential that you back up your stock boot.img. If you encounter any bootloop, you can always restore the system by flashing back to the stock factory boot using fastboot.
::: warning
Flashing may cause data loss. Make sure to do this step well before proceeding to the next step! You can also back up all the data on your device if necessary.
:::
## Necessary knowledge
### ADB and fastboot
By default, you will use ADB and fastboot tools in this tutorial, so if you don't know them, we recommend using a search engine to learn about them first.
### KMI
Kernel Module Interface (KMI), kernel versions with the same KMI are **compatible**, this is what "general" means in GKI; conversely, if the KMI is different, then these kernels aren't compatible with each other, and flashing a kernel image with a different KMI than your device may cause a bootloop.
Specifically, for GKI devices, the kernel version format should be as follows:
```txt
KernelRelease :=
Version.PatchLevel.SubLevel-AndroidRelease-KmiGeneration-suffix
w .x .y -zzz -k -something
```
`w.x-zzz-k` is the KMI version. For example, if a device kernel version is `5.10.101-android12-9-g30979850fc20`, then its KMI is `5.10-android12-9`. Theoretically, it can boot up normally with other KMI kernels.
::: tip
Note that the SubLevel in the kernel version isn't part of the KMI! This means that `5.10.101-android12-9-g30979850fc20` has the same KMI as `5.10.137-android12-9-g30979850fc20`!
:::
### Security patch level {#security-patch-level}
Newer Android devices may have anti-rollback mechanisms that prevent flashing a boot image with an old security patch level. For example, if your device kernel is `5.10.101-android12-9-g30979850fc20`, the security patch level is `2023-11`; even if you flash the kernel corresponding to the KMI, if the security patch level is older than `2023-11` (such as `2023-06`), it may cause a bootloop.
Therefore, kernels with latest security patch levels are preferred to maintain compatibility with the KMI.
### Kernel version vs Android version
Please note: **Kernel version and Android version aren't necessarily the same!**
If you find that your kernel version is `android12-5.10.101`, but your Android system version is Android 13 or other, don't be surprised, because the version number of the Android system isn't necessarily the same as the version number of the Linux kernel. The version number of the Linux kernel is generally correspondent to the version of the Android system that comes with the **device when it is shipped**. If the Android system is upgraded later, the kernel version will generally not change. So, before flashing anything, **always refer to the kernel version!**
## Introduction
Since version [0.9.0](https://github.com/tiann/KernelSU/releases/tag/v0.9.0), KernelSU supports two running modes on GKI devices:
1. `GKI`: Replace the original kernel of the device with the **Generic Kernel Image** (GKI) provided by KernelSU.
2. `LKM`: Load the **Loadable Kernel Module** (LKM) into the device kernel without replacing the original kernel.
These two modes are suitable for different scenarios, and you can choose the one according to your needs.
### GKI mode {#gki-mode}
In GKI mode, the original kernel of the device will be replaced with the generic kernel image provided by KernelSU. The advantages of GKI mode are:
1. Strong universality, suitable for most devices. For example, Samsung has enabled KNOX devices, and LKM mode cannot work. There are also some niche modified devices that can only use GKI mode.
2. Can be used without relying on official firmware, and there is no need to wait for official firmware updates, as long as the KMI is consistent, it can be used.
### LKM mode {#lkm-mode}
In LKM mode, the original kernel of the device won't be replaced, but the loadable kernel module will be loaded into the device kernel. The advantages of LKM mode are:
1. Won't replace the original kernel of the device. If you have special requirements for the original kernel of the device, or you want to use KernelSU while using a third-party kernel, you can use LKM mode.
2. It's more convenient to upgrade and OTA. When upgrading KernelSU, you can directly install it in the manager without flashing manually. After the system OTA, you can directly install it to the second slot without manual flashing.
3. Suitable for some special scenarios. For example, LKM can also be loaded with temporary root permissions. Since it doesn't need to replace the boot partition, it won't trigger AVB and won't cause the device to be bricked.
4. LKM can be temporarily uninstalled. If you want to temporarily disable root access, you can uninstall LKM. This process doesn't require flashing partitions, or even rebooting the device. If you want to enable root again, just reboot the device.
::: tip COEXISTENCE OF TWO MODES
After opening the manager, you can see the current mode of the device on the homepage. Note that the priority of GKI mode is higher than that of LKM. For example, if you use GKI kernel to replace the original kernel, and use LKM to patch the GKI kernel, the LKM will be ignored, and the device will always run in GKI mode.
:::
### Which one to choose? {#which-one}
If your device is a mobile phone, we recommend that you prioritize LKM mode. If your device is an emulator, WSA, or Waydroid, we recommend that you prioritize GKI mode.
## LKM installation
### Get the official firmware
To use LKM mode, you need to get the official firmware and patch it based on the official firmware. If you use a third-party kernel, you can use the `boot.img` of the third-party kernel as the official firmware.
There are many ways to get the official firmware. If your device supports `fastboot boot`, we recommend **the most recommended and simplest** method is to use `fastboot boot` to temporarily boot the GKI kernel provided by KernelSU, then install the manager, and finally install it directly in the manager. This method doesn't require manually downloading the official firmware or manually extracting the boot.
If your device doesn't support `fastboot boot`, you may need to manually download the official firmware package and extract the boot from it.
Unlike GKI mode, LKM mode modifies the `ramdisk`. Therefore, on devices with Android 13, it needs to patch the `init_boot` partition instead of the `boot` partition, while GKI mode always operates on the `boot` partition.
### Use the manager
Open the manager, click the installation icon in the upper right corner, and several options will appear:
1. Select a file. If your device doesn't have root privileges, you can choose this option and then select your official firmware. The manager will automatically patch it. After that, just flash this patched file to obtain root privileges permanently.
2. Direct install. If your device is already rooted, you can choose this option. The manager will automatically get your device information, and then automatically patch the official firmware, and flash it automatically. You can consider using `fastboot boot` KernelSU's GKI kernel to get temporary root and install the manager, and then use this option. This is also the main way to upgrade KernelSU.
3. Install to inactive slot. If your device supports A/B partition, you can choose this option. The manager will automatically patch the official firmware and install it to another partition. This method is suitable for devices after OTA, you can directly install it to another partition after OTA, and then restart the device.
### Use the command line
If you don't want to use the manager, you can also use the command line to install LKM. The `ksud` tool provided by KernelSU can help you quickly patch the official firmware and then flash it.
This tool supports macOS, Linux, and Windows. You can download the corresponding version from [GitHub Release](https://github.com/tiann/KernelSU/releases).
Usage: `ksud boot-patch` you can check the command line help for specific options.
```sh
oriole:/ # ksud boot-patch -h
Patch boot or init_boot images to apply KernelSU
Usage: ksud boot-patch [OPTIONS]
Options:
-b, --boot <BOOT> Boot image path. If not specified, it will try to find the boot image automatically
-k, --kernel <KERNEL> Kernel image path to be replaced
-m, --module <MODULE> LKM module path to be replaced. If not specified, the built-in module will be used
-i, --init <INIT> init to be replaced
-u, --ota Will use another slot if the boot image is not specified
-f, --flash Flash it to boot partition after patch
-o, --out <OUT> Output path. If not specified, the current directory will be used
--magiskboot <MAGISKBOOT> magiskboot path. If not specified, the built-in version will be used
--kmi <KMI> KMI version. If specified, the indicated KMI will be used
-h, --help Print help
```
A few options that need to be explained:
1. The `--magiskboot` option can specify the path of magiskboot. If not specified, ksud will look for it in the environment variables. If you dont know how to get magiskboot, you can check [here](#patch-boot-image).
2. The `--kmi` option can specify the `KMI` version. If the kernel name of your device doesn't follow the KMI specification, you can specify it using this option.
The most common usage is:
```sh
ksud boot-patch -b <boot.img> --kmi android13-5.10
```
## GKI mode installation
There are several installation methods for GKI mode, each suitable for a different scenario, so please choose accordingly:
1. Install with fastboot using the boot.img provided by KernelSU.
2. Install with a kernel flash app, such as [Kernel Flasher](https://github.com/capntrips/KernelFlasher/releases).
3. Repair the boot.img manually and install it.
4. Install with custom Recovery (e.g., TWRP).
## Install with boot.img provided by KernelSU
If your device's `boot.img` uses a commonly used compression format, you can use the GKI images provided by KernelSU to flash it directly. This doesn't require TWRP or self-patching the image.
### Find proper boot.img
KernelSU provides a generic boot.img for GKI devices, and you should flash the boot.img to the device's boot partition.
You can download boot.img from [GitHub Release](https://github.com/tiann/KernelSU/releases). Please note that you should use the correct version of boot.img. If you don't know which file to download, carefully read the description of [KMI](#kmi) and [Security patch level](#security-patch-level) in this document.
Normally, there are three boot files in different formats for the same KMI and security patch level. They're identical except for the kernel compression format. Please check the kernel compression format of your original boot.img. You should use the correct format, such as `lz4`, `gz`. If you use an incorrect compression format, you may encounter bootloop after flashing boot.img.
::: info COMPRESSION FORMAT OF BOOT.IMG
1. You can use magiskboot to get the compression format of your original boot.img. Alternatively, you can also ask members or developers in the community who have the same device model. Also, the compression format of the kernel usually doesn't change, so if you boot successfully with a certain compression format, you can try that format later as well.
2. Xiaomi devices usually use `gz` or `uncompressed`.
3. For Pixel devices, follow the instructions below:
:::
### Flash boot.img to device
Use `adb` to connect your device, then execute `adb reboot bootloader` to enter fastboot mode, and use this command to flash KernelSU:
```sh
fastboot flash boot boot.img
```
::: info
If your device supports `fastboot boot`, you can first use `fastboot boot boot.img` to try to use boot.img to boot the system first. If something unexpected happens, restart it again to boot.
:::
### Reboot
After the flash is completed, you should reboot your device:
```sh
fastboot reboot
```
## Install with Kernel Flasher
Steps:
1. Download the AnyKernel3 ZIP. If you don't know which file to download, carefully read the description of [KMI](#kmi) and [Security patch level](#security-patch-level) in this document.
2. Open the Kernel Flasher app, grant necessary root permissions, and use the provided AnyKernel3 ZIP to flash.
This way requires the Kernel Flasher app to have root permissions. You can use the following methods to achieve this:
1. Your device is rooted. For example, you have installed KernelSU and want to upgrade to the latest version or you have rooted through other methods (such as Magisk).
2. If your device isn't rooted, but the device supports the temporary boot method of `fastboot boot boot.img`, you can use the GKI image provided by KernelSU to temporarily boot your device, obtain temporary root permissions, and then use the Kernel Flash app to obtain permanent root privileges.
Some of kernel flashing apps that can be used for this:
1. [Kernel Flasher](https://github.com/capntrips/KernelFlasher/releases)
2. [Franco Kernel Manager](https://play.google.com/store/apps/details?id=com.franco.kernel)
3. [Ex Kernel Manager](https://play.google.com/store/apps/details?id=flar2.exkernelmanager)
Note: This method is more convenient when upgrading KernelSU and can be done without a computer (make a backup first).
## Patch boot.img manually {#patch-boot-image}
For some devices, the boot.img format isn't as common as `lz4`, `gz`, and `uncompressed`. A typical example is the Pixel, where the boot.img is compressed in the `lz4_legacy` format, while the, ramdisk may be in `gz` or also compressed in `lz4_legacy`. Currently, if you directly flash the boot.img provided by KernelSU, the device may not be able to boot. In this case, you can manually patch the boot.img to achieve this.
It's always recommended to use `magiskboot` to patch images, there are two ways:
1. [magiskboot](https://github.com/topjohnwu/Magisk/releases)
2. [magiskboot_build](https://github.com/ookiineko/magiskboot_build/releases/tag/last-ci)
The official build of `magiskboot` can only run on Android devices, if you want to run it on PC, you can try the second option.
::: tip
Android-Image-Kitchen isn't recommended for now because it doesn't handle the boot metadata (such as security patch level) correctly. Therefore, it may not work on some devices.
:::
### Preparation
1. Get your device's stock boot.img. You can get it from your device manufacturers. You may need [payload-dumper-go](https://github.com/ssut/payload-dumper-go).
2. Download the AnyKernel3 ZIP file provided by KernelSU that matches the KMI version of your device. You can refer to [Install with custom Recovery](#install-with-custom-recovery).
3. Unpack the AnyKernel3 package and get the `Image` file, which is the kernel file of KernelSU.
### Using magiskboot on Android devices {#using-magiskboot-on-Android-devices}
1. Download latest Magisk from [GitHub Releases](https://github.com/topjohnwu/Magisk/releases).
2. Rename `Magisk-*(version).apk` to `Magisk-*.zip` and unzip it.
3. Push `Magisk-*/lib/arm64-v8a/libmagiskboot.so` to your device by ADB: `adb push Magisk-*/lib/arm64-v8a/libmagiskboot.so /data/local/tmp/magiskboot`
4. Push stock boot.img and Image in AnyKernel3 to your device.
5. Enter ADB shell and run `cd /data/local/tmp/` directory, then `chmod +x magiskboot`
6. Enter ADB shell and run `cd /data/local/tmp/` directory, execute `./magiskboot unpack boot.img` to unpack `boot.img`, you will get a `kernel` file, this is your stock kernel.
7. Replace `kernel` with `Image` by running the command: `mv -f Image kernel`.
8. Execute `./magiskboot repack boot.img` to repack boot image, and you will get a `new-boot.img` file, flash this file to device by fastboot.
### Using magiskboot on Windows/macOS/Linux PC {#using-magiskboot-on-PC}
1. Download the corresponding `magiskboot` binary for your OS from [magiskboot_build](https://github.com/ookiineko/magiskboot_build/releases/tag/last-ci).
2. Prepare stock `boot.img` and `Image` in your PC.
3. Run `chmod +x magiskboot`.
4. Enter the corresponding directory, execute `./magiskboot unpack boot.img` to unpack `boot.img`, you will get a `kernel` file, this is your stock kernel.
5. Replace `kernel` with `Image` by running the command: `mv -f Image kernel`.
6. Execute `./magiskboot repack boot.img` to repack the boot image, and you will get a `new-boot.img` file, flash this file to device by fastboot.
::: info
Official `magiskboot` can run in `Linux` environments normally, if you're a Linux user, you can use the official build.
:::
## Install with custom Recovery {#install-with-custom-recovery}
Prerequisite: Your device must have a custom Recovery, such as TWRP. If there is no custom Recovery available for your device, use another method.
Steps:
1. On [GitHub Releases](https://github.com/tiann/KernelSU/releases), download the ZIP package starting with `AnyKernel3` that matches your device's version. For example, if the device's kernel version is `android12-5.10.66`, then you should download the `AnyKernel3-android12-5.10.66_yyyy-MM.zip` file (where `yyyy` is the year and `MM` is the month).
2. Reboot the device into TWRP.
3. Use ADB to place AnyKernel3-*.zip into the device's `/sdcard` location and choose to install it in the TWRP GUI, or you can directly run `adb sideload AnyKernel-*.zip` to install.
Note: This method is suitable for any installation (not limited to initial installation or subsequent upgrades), as long as you're using TWRP.
## Other methods
In fact, all of these installation methods have only one main idea, which is to **replace the original kernel for the one provided by KernelSU**, as long as this can be achieved, it can be installed. The following are other possible methods:
1. First, install Magisk, get root privileges through Magisk, and then use the Kernel Flasher to flash the AnyKernel3 ZIP from KernelSU.
2. Use any flashing toolkit on PC to flash the kernel provided by KernelSU.
However, if it doesn't work, please try `magiskboot` approach.

View File

@@ -0,0 +1,48 @@
# Module WebUI
In addition to executing boot scripts and modifying system files, KernelSU's modules also support displaying UI interfaces and interacting directly with users.
The module can write HTML + CSS + JavaScript pages through any web technology. KernelSU's manager will display these pages through WebView. It also provides some APIs to interact with the system, such as executing shell commands.
## `webroot` directory
Web resource files should be placed in the `webroot` subdirectory of the module root directory, and there **MUST** be a file named `index.html`, which is the module page entry. The simplest module structure containing a web interface is as follows:
```txt
tree .
.
|-- module.prop
`-- webroot
`-- index.html
```
::: warning
When installing the module, KernelSU will automatically set the permissions and SELinux context for this directory. If you don't know what you're doing, do not set the permissions for this directory yourself!
:::
If your page contains CSS and JavaScript, you need to place it in this directory as well.
## JavaScript API
If it's just a display page, it will function like a regular web page. However, the most important thing is that KernelSU provides a series of system APIs, allowing the implementation of module-specific functions.
KernelSU provides a JavaScript library, which is published on [npm](https://www.npmjs.com/package/kernelsu) and can be used in the JavaScript code of your web pages.
For example, you can execute a shell command to obtain a specific configuration or modify a property:
```JavaScript
import { exec } from 'kernelsu';
const { errno, stdout } = exec("getprop ro.product.model");
```
For another example, you can make the web page display full screen, or display a toast.
[API documentation](https://www.npmjs.com/package/kernelsu)
If you find that the existing API doesn't meet your needs or is inconvenient to use, you're welcome to give us suggestions [here](https://github.com/tiann/KernelSU/issues)!
## Some tips
1. You can use `localStorage` as usual to store some data, but keep in mind that it will be lost if the manager app is uninstalled. If you need persistent storage, you will need to manually save the data in a specific directory.
2. For simple pages, we recommend using [parceljs](https://parceljs.org/) for packaging. It requires no initial configuration and is extremely easy to use. However, if you're a front-end expert or have your own preferences, feel free to use the tool of your choice!

View File

@@ -0,0 +1,326 @@
# Module guide
KernelSU provides a module mechanism that achieves the effect of modifying the system directory while maintaining the integrity of the system partition. This mechanism is commonly known as "systemless".
The module mechanism of KernelSU is almost the same as that of Magisk. If you're familiar with Magisk module development, developing KernelSU modules is very similar. You can skip the introduction of modules below and just read [Difference with Magisk](difference-with-magisk.md).
## WebUI
KernelSU's modules support displaying interfaces and interacting with users. For more details, refer to the [WebUI documentation](module-webui.md).
## BusyBox
KernelSU ships with a feature-complete BusyBox binary (including full SELinux support). The executable is located at `/data/adb/ksu/bin/busybox`. KernelSU's BusyBox supports runtime toggle-able "ASH Standalone Shell Mode". What this Standalone Mode means is that when running in the `ash` shell of BusyBox, every single command will directly use the applet within BusyBox, regardless of what is set as `PATH`. For example, commands like `ls`, `rm`, `chmod` will **NOT** use what is in `PATH` (in the case of Android by default it will be `/system/bin/ls`, `/system/bin/rm`, and `/system/bin/chmod` respectively), but will instead directly call internal BusyBox applets. This makes sure that scripts always run in a predictable environment and always have the full suite of commands no matter which Android version it is running on. To force a command _not_ to use BusyBox, you have to call the executable with full paths.
Every single shell script running in the context of KernelSU will be executed in BusyBox's `ash` shell with Standalone Mode enabled. For what is relevant to 3rd party developers, this includes all boot scripts and module installation scripts.
For those who want to use this Standalone Mode feature outside of KernelSU, there are 2 ways to enable it:
1. Set environment variable `ASH_STANDALONE` to `1` <br>Example: `ASH_STANDALONE=1 /data/adb/ksu/bin/busybox sh <script>`
2. Toggle with command-line options:<br>`/data/adb/ksu/bin/busybox sh -o standalone <script>`
To make sure all subsequent `sh` shell executed also runs in Standalone Mode, option 1 is the preferred method (and this is what KernelSU and the KernelSU manager use internally) as environment variables are inherited down to child processes.
::: tip DIFFERENCE WITH MAGISK
KernelSU's BusyBox is now using the binary file compiled directly from the Magisk project. **Thanks to Magisk!** Therefore, you don't need to worry about compatibility issues between BusyBox scripts in Magisk and KernelSU, as they're exactly the same!
:::
## KernelSU modules
A KernelSU module is a folder placed in `/data/adb/modules` with the structure below:
```txt
/data/adb/modules
├── .
├── .
|
├── $MODID <--- The folder is named with the ID of the module
│ │
│ │ *** Module Identity ***
│ │
│ ├── module.prop <--- This file stores the metadata of the module
│ │
│ │ *** Main Contents ***
│ │
│ ├── system <--- This folder will be mounted if skip_mount does not exist
│ │ ├── ...
│ │ ├── ...
│ │ └── ...
│ │
│ │ *** Status Flags ***
│ │
│ ├── skip_mount <--- If exists, KernelSU will NOT mount your system folder
│ ├── disable <--- If exists, the module will be disabled
│ ├── remove <--- If exists, the module will be removed next reboot
│ │
│ │ *** Optional Files ***
│ │
│ ├── post-fs-data.sh <--- This script will be executed in post-fs-data
│ ├── post-mount.sh <--- This script will be executed in post-mount
│ ├── service.sh <--- This script will be executed in late_start service
│ ├── boot-completed.sh <--- This script will be executed on boot completed
| ├── uninstall.sh <--- This script will be executed when KernelSU removes your module
| ├── action.sh <--- This script will be executed when user click the Action button in KernelSU app
│ ├── system.prop <--- Properties in this file will be loaded as system properties by resetprop
│ ├── sepolicy.rule <--- Additional custom sepolicy rules
│ │
│ │ *** Auto Generated, DO NOT MANUALLY CREATE OR MODIFY ***
│ │
│ ├── vendor <--- A symlink to $MODID/system/vendor
│ ├── product <--- A symlink to $MODID/system/product
│ ├── system_ext <--- A symlink to $MODID/system/system_ext
│ │
│ │ *** Any additional files / folders are allowed ***
│ │
│ ├── ...
│ └── ...
|
├── another_module
│ ├── .
│ └── .
├── .
├── .
```
::: tip DIFFERENCE WITH MAGISK
KernelSU doesn't have built-in support for Zygisk, so there is no content related to Zygisk in the module. However, you can use [ZygiskNext](https://github.com/Dr-TSNG/ZygiskNext) to support Zygisk modules. In this case, the content of the Zygisk module is identical to that supported by Magisk.
:::
### module.prop
`module.prop` is a configuration file for a module. In KernelSU, if a module doesn't contain this file, it won't be recognized as a module. The format of this file is as follows:
```txt
id=<string>
name=<string>
version=<string>
versionCode=<int>
author=<string>
description=<string>
```
- `id` has to match this regular expression: `^[a-zA-Z][a-zA-Z0-9._-]+$` .<br>
Example: ✓ `a_module`, ✓ `a.module`, ✓ `module-101`, ✗ `a module`, ✗ `1_module`, ✗ `-a-module`<br>
This is the **unique identifier** of your module. You should not change it once published.
- `versionCode` has to be an **integer**. This is used to compare versions.
- Others that were not mentioned above can be any **single line** string.
- Make sure to use the `UNIX (LF)` line break type and not the `Windows (CR+LF)` or `Macintosh (CR)`.
### Shell scripts
Please read the [Boot scripts](#boot-scripts) section to understand the difference between `post-fs-data.sh` and `service.sh`. For most module developers, `service.sh` should be good enough if you just need to run a boot script, if you need to run the script after boot completed, please use `boot-completed.sh`. If you want to do something after mounting OverlayFS, please use `post-mount.sh`.
In all scripts of your module, please use `MODDIR=${0%/*}` to get your module's base directory path; do **NOT** hardcode your module path in scripts.
::: tip DIFFERENCE WITH MAGISK
You can use the environment variable `KSU` to determine if a script is running in KernelSU or Magisk. If running in KernelSU, this value will be set to `true`.
:::
### `system` directory
The contents of this directory will be overlaid on top of the system's `/system` partition using OverlayFS after the system is booted. This means that:
1. Files with the same name as those in the corresponding directory in the system will be overwritten by the files in this directory.
2. Folders with the same name as those in the corresponding directory in the system will be merged with the folders in this directory.
If you want to delete a file or folder in the original system directory, you need to create a file with the same name as the file/folder in the module directory using `mknod filename c 0 0`. This way, the OverlayFS system will automatically "whiteout" this file as if it has been deleted (the /system partition isn't actually changed).
You can also declare a variable named `REMOVE` containing a list of directories in `customize.sh` to execute removal operations, and KernelSU will automatically execute `mknod <TARGET> c 0 0` in the corresponding directories of the module. For example:
```sh
REMOVE="
/system/app/YouTube
/system/app/Bloatware
"
```
The above list will execute `mknod $MODPATH/system/app/YouTube c 0 0` and `mknod $MODPATH/system/app/Bloatware c 0 0`, `/system/app/YouTube` and `/system/app/Bloatware` will be removed after the module takes effect.
If you want to replace a directory in the system, you need to create a directory with the same path in your module directory, and then set the attribute `setfattr -n trusted.overlay.opaque -v y <TARGET>` for this directory. This way, the OverlayFS system will automatically replace the corresponding directory in the system (without changing the /system partition).
You can declare a variable named `REPLACE` in your `customize.sh` file, which includes a list of directories to be replaced, and KernelSU will automatically perform the corresponding operations in your module directory. For example:
```sh
REPLACE="
/system/app/YouTube
/system/app/Bloatware
"
```
This list will automatically create the directories `$MODPATH/system/app/YouTube` and `$MODPATH/system/app/Bloatware`, and then execute `setfattr -n trusted.overlay.opaque -v y $MODPATH/system/app/YouTube` and `setfattr -n trusted.overlay.opaque -v y $MODPATH/system/app/Bloatware`. After the module takes effect, `/system/app/YouTube` and `/system/app/Bloatware` will be replaced with empty directories.
::: tip DIFFERENCE WITH MAGISK
KernelSU's systemless mechanism is implemented through the kernel's OverlayFS, while Magisk currently uses magic mount (bind mount). These two implementation methods have significant differences, but the ultimate goal is the same: modifying /system files without physically modifying the /system partition.
:::
If you're interested in OverlayFS, it's recommended to read the Linux Kernel's [documentation on OverlayFS](https://docs.kernel.org/filesystems/overlayfs.html).
### system.prop
This file follows the same format as `build.prop`. Each line comprises of `[key]=[value]`.
### sepolicy.rule
If your module requires some additional sepolicy patches, please add those rules into this file. Each line in this file will be treated as a policy statement.
## Module installer
A KernelSU module installer is a KernelSU module packaged in a ZIP file that can be flashed in the KernelSU manager. The simplest KernelSU module installer is just a KernelSU module packed as a ZIP file.
```txt
module.zip
├── customize.sh <--- (Optional, more details later)
│ This script will be sourced by update-binary
├── ...
├── ... /* The rest of module's files */
```
::: warning
KernelSU module is **NOT** compatible for installation in a custom Recovery!
:::
### Customization
If you need to customize the module installation process, optionally you can create a script in the installer named `customize.sh`. This script will be **sourced** (not executed) by the module installer script after all files are extracted and default permissions and secontext are applied. This is very useful if your module requires additional setup based on the device ABI, or you need to set special permissions/secontext for some of your module files.
If you would like to fully control and customize the installation process, declare `SKIPUNZIP=1` in `customize.sh` to skip all default installation steps. By doing so, your `customize.sh` will be responsible to install everything by itself.
The `customize.sh` script runs in KernelSU's BusyBox `ash` shell with Standalone Mode enabled. The following variables and functions are available:
#### Variables
- `KSU` (bool): a variable to mark that the script is running in the KernelSU environment, and the value of this variable will always be true. You can use it to distinguish between KernelSU and Magisk.
- `KSU_VER` (string): the version string of currently installed KernelSU (e.g. `v0.4.0`).
- `KSU_VER_CODE` (int): the version code of currently installed KernelSU in userspace (e.g. `10672`).
- `KSU_KERNEL_VER_CODE` (int): the version code of currently installed KernelSU in kernel space (e.g. `10672`).
- `BOOTMODE` (bool): always be `true` in KernelSU.
- `MODPATH` (path): the path where your module files should be installed.
- `TMPDIR` (path): a place where you can temporarily store files.
- `ZIPFILE` (path): your module's installation ZIP.
- `ARCH` (string): the CPU architecture of the device. Value is either `arm`, `arm64`, `x86`, or `x64`.
- `IS64BIT` (bool): `true` if `$ARCH` is either `arm64` or `x64`.
- `API` (int): the API level (Android version) of the device (e.g., `23` for Android 6.0).
::: warning
In KernelSU, `MAGISK_VER_CODE` is always `25200`, and `MAGISK_VER` is always `v25.2`. Please don't use these two variables to determine whether KernelSU is running or not.
:::
#### Functions
```txt
ui_print <msg>
print <msg> to console
Avoid using 'echo' as it will not display in custom recovery's console
abort <msg>
print error message <msg> to console and terminate the installation
Avoid using 'exit' as it will skip the termination cleanup steps
set_perm <target> <owner> <group> <permission> [context]
if [context] is not set, the default is "u:object_r:system_file:s0"
this function is a shorthand for the following commands:
chown owner.group target
chmod permission target
chcon context target
set_perm_recursive <directory> <owner> <group> <dirpermission> <filepermission> [context]
if [context] is not set, the default is "u:object_r:system_file:s0"
for all files in <directory>, it will call:
set_perm file owner group filepermission context
for all directories in <directory> (including itself), it will call:
set_perm dir owner group dirpermission context
```
## Boot scripts
In KernelSU, scripts are divided into two types based on their running mode: post-fs-data mode and late_start service mode.
- post-fs-data mode
- This stage is BLOCKING. The boot process is paused before execution is done or after 10 seconds.
- Scripts run before any modules are mounted. This allows a module developer to dynamically adjust their modules before it gets mounted.
- This stage happens before Zygote is started, which pretty much means everything in Android.
- **WARNING:** Using `setprop` will deadlock the boot process! Please use `resetprop -n <prop_name> <prop_value>` instead.
- **Only run scripts in this mode if necessary**.
- late_start service mode
- This stage is NON-BLOCKING. Your script runs in parallel with the rest of the booting process.
- **This is the recommended stage to run most scripts**.
In KernelSU, startup scripts are divided into two types based on their storage location: general scripts and module scripts.
- General scripts
- Placed in `/data/adb/post-fs-data.d`, `/data/adb/service.d`, `/data/adb/post-mount.d` or `/data/adb/boot-completed.d.`
- Only executed if the script is set as executable (`chmod +x script.sh`)
- Scripts in `post-fs-data.d` runs in post-fs-data mode, and scripts in `service.d` runs in late_start service mode.
- Modules should **NOT** add general scripts during installation.
- Module scripts
- Placed in the module's own folder.
- Only executed if the module is enabled.
- `post-fs-data.sh` runs in post-fs-data mode, `service.sh` runs in late_start service mode, `boot-completed.sh` runs on boot completed, `post-mount.sh` runs on OverlayFS mounted.
All boot scripts will run in KernelSU's BusyBox `ash` shell with Standalone Mode enabled.
### Boot scripts process explanation
The following is the relevant boot process for Android (some parts are omitted), which includes the operation of KernelSU (with leading asterisks), and can help you better understand the purpose of these module scripts:
```txt
0. Bootloader (nothing on screen)
load patched boot.img
load kernel:
- GKI mode: GKI kernel with KernelSU integrated
- LKM mode: stock kernel
...
1. kernel exec init (OEM logo on screen):
- GKI mode: stock init
- LKM mode: exec ksuinit, insmod kernelsu.ko, exec stock init
mount /dev, /dev/pts, /proc, /sys, etc.
property-init -> read default props
read init.rc
...
early-init -> init -> late_init
early-fs
start vold
fs
mount /vendor, /system, /persist, etc.
post-fs-data
*safe mode check
*execute general scripts in post-fs-data.d/
*load sepolicy.rule
*mount tmpfs
*execute module scripts post-fs-data.sh
**(Zygisk)./bin/zygisk-ptrace64 monitor
*(pre)load system.prop (same as resetprop -n)
*remount modules /system
*execute general scripts in post-mount.d/
*execute module scripts post-mount.sh
zygote-start
load_all_props_action
*execute resetprop (actual set props for resetprop with -n option)
... -> boot
class_start core
start-service logd, console, vold, etc.
class_start main
start-service adb, netd (iptables), zygote, etc.
2. kernel2user init (ROM animation on screen, start by service bootanim)
*execute general scripts in service.d/
*execute module scripts service.sh
*set props for resetprop without -p option
**(Zygisk) hook zygote (start zygiskd)
**(Zygisk) mount zygisksu/module.prop
start system apps (autostart)
...
boot complete (broadcast ACTION_BOOT_COMPLETED event)
*execute general scripts in boot-completed.d/
*execute module scripts boot-completed.sh
3. User operable (lock screen)
input password to decrypt /data/data
*actual set props for resetprop with -p option
start user apps (autostart)
```
If you're interested in Android Init Language, it's recommended to read its [documentation](https://android.googlesource.com/platform/system/core/+/master/init/README.md).

View File

@@ -0,0 +1,50 @@
# Rescue from bootloop
When updating a device, situations may arise where the device becomes "bricked". In theory, if you only use fastboot to flash the boot partition or install incompatible modules that cause the device to fail during boot, it can be restored through appropriate operations. This document aims to provide emergency methods to help you recover a "bricked" device.
## Brick by flashing boot partition
In KernelSU, the following situations may cause boot brick when flashing the boot partition:
1. You flashed a boot image in the wrong format. For example, if your device's boot format is `gz`, but you flashed an image in `lz4` format, the device won't boot.
2. Your device needs to disable AVB verification to boot correctly, which usually requires wiping all data from the device.
3. Your kernel contains bugs or isn't compatible with your device's flash.
No matter the situation, you can recover by **flashing the stock boot image**. Therefore, at the beginning of the installation guide, we strongly recommend that you back up your stock boot before flashing. If you didn't back it up, you can obtain the original factory boot from other users with the same device or from the official firmware.
## Brick by modules
The installation of modules can be one of the most common causes of bricking your device, but we must seriously warn you: **DO NOT INSTALL MODULES FROM UNKNOWN SOURCES!** Since modules have root privileges, they can cause irreversible damage to your device!
### Normal modules
If you have flashed a module that has been proven to be safe but causes your device to fail to boot, then this situation is easily recoverable in KernelSU without any worries. KernelSU has built-in mechanisms to rescue your device, including the following:
1. AB update
2. Rescue by pressing Volume down button
#### AB update
KernelSU's module updates are based on the Android system's AB update mechanism used in OTA updates. When you install a new module or update an existing one, it won't directly modify the currently used module file. Instead, all modules are integrated into a new update image. After the system is restarted, it will attempt to boot using this new update image. If the Android system boots successfully, the modules will be effectively updated.
Therefore, the simplest and most commonly used method to rescue your device is to **force a reboot**. If you're unable to start your system after flashing a module, you can press and hold the power button for more than 10 seconds, and the system will automatically reboot. After rebooting, it will roll back to the state before the module update, and any previously updated modules will be automatically disabled.
#### Rescue by pressing Volume down button
If AB update hasn't yet resolved the issue, you can try using **Safe Mode**. In this mode, all modules are disabled.
There are two ways to enter Safe Mode:
1. The built-in Safe Mode of some systems: Some systems have a built-in Safe Mode that can be accessed by long-pressing the Volume down button. In other systems (such as HyperOS), Safe Mode can be activated from the Recovery. When entering the system's Safe Mode, KernelSU will also enter this mode and automatically disable the modules.
2. The built-in Safe Mode of KernelSU: In this case, the method is to **press the Volume down key continuously more than three times** after the first boot screen.
After entering Safe Mode, all modules on the Module page in the KernelSU manager will be disabled. However, you can still perform the "uninstall" operation to remove any modules that may be causing issues.
The built-in Safe Mode is implemented in the kernel, so there is no possibility of missing important events due to interception. However, for non-GKI kernels, manual code integration may be required. For this, refer to the official documentation for guidance.
### Malicious modules
If the above methods cannot rescue your device, it's highly likely that the module you installed has malicious operations or has damaged your device in some other way. In this case, there are only two suggestions:
1. Wipe the data and flash the official system.
2. Consult the after-sales service.

View File

@@ -0,0 +1,30 @@
# Unofficially supported devices
::: warning
In this page, there are kernels for non-GKI devices supporting KernelSU maintained by other developers.
:::
::: warning
This page is intended only to help you find the source code corresponding to your device. It **DOES NOT** mean that the source code has been reviewed by KernelSU developers. You should use it at your own risk.
:::
<script setup>
import data from '../repos.json'
</script>
<table>
<thead>
<tr>
<th>Maintainer</th>
<th>Repository</th>
<th>Support devices</th>
</tr>
</thead>
<tbody>
<tr v-for="repo in data" :key="repo.devices">
<td><a :href="repo.maintainer_link" target="_blank" rel="noreferrer">{{ repo.maintainer }}</a></td>
<td><a :href="repo.kernel_link" target="_blank" rel="noreferrer">{{ repo.kernel_name }}</a></td>
<td>{{ repo.devices }}</td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,21 @@
# What is KernelSU?
KernelSU is a root solution for Android GKI devices, it works in kernel mode and grants root permission to userspace apps directly in kernel space.
## Features
The main feature of KernelSU is that it's **kernel-based**. KernelSU works in kernel mode, enabling it to provide a kernel interface that we never had before. For example, it's possible to add hardware breakpoints to any process in kernel mode, access the physical memory of any process invisibly, intercept any system call (syscall) within the kernel space, among other functionalities.
Additionally, KernelSU provides a module system via OverlayFS, which allows you to load your custom plugin into system. It also provides a mechanism to modify files in `/system` partition.
## How to use KernelSU?
Please refer: [Installation](installation)
## How to build KernelSU?
Please refer: [How to build](how-to-build)
## Discussion
- Telegram: [@KernelSU](https://t.me/KernelSU)