中文 | English
A GitHub Actions workflow that integrates KernelSU (and its forks), SUSFS and the common kernel patches into an Android kernel, and produces a flashable AnyKernel3 package.
Assumes some familiarity with Android kernels.
If you are not the kernel author, please keep KernelSU builds made from someone else's work to yourself rather than redistributing them. It is a matter of respecting their effort.
| Kernel | Status |
|---|---|
4.9 4.14 4.19 5.4 |
Non-GKI, fully supported |
5.10 5.15 6.1 6.6 6.12 |
GKI source trees, built with make |
This builds a source-integrated (built-in) kernel. If all you want is the GKI loadable module (
kernelsu.ko), use upstream's DDK flow instead.
- Fork this repository.
- Edit
config.env— at minimumKERNEL_SOURCE,KERNEL_SOURCE_BRANCH,KERNEL_CONFIGandKERNEL_IMAGE_NAME. - Go to
Actions→Build Kernel→Run workflow. - Pick your KernelSU variant, whether to enable SUSFS, and so on, then run it.
- Download the AnyKernel3 artifact and flash it from a custom recovery.
The dropdowns all default to config, meaning "use whatever the config file says". They override the matching key in config.env only when you actively change them, so day-to-day tweaking needs no commits — and simply hitting Run always builds exactly what your profile describes, rather than silently switching off a feature you enabled because some checkbox defaulted to off.
To keep one profile per device, copy config.env to config/<device>.env and pass that path as Config file to build.
Selected with KSU_VARIANT:
| Value | Project | Notes |
|---|---|---|
none |
— | No root solution, plain kernel build |
kernelsu |
tiann/KernelSU | The original. Dropped non-GKI support at v1.0, so older kernels are pinned to v0.9.5 automatically |
kernelsu-next |
KernelSU-Next | Branches are dev (default), stable, legacy. Use legacy for older kernels |
sukisu-ultra |
SukiSU-Ultra | main is the modular v4 tree (supports KPM); builtin is the source-integrated tree and the only ref that ships SUSFS itself |
resukisu |
ReSukiSU | A re-fork of SukiSU-Ultra aimed at legacy/non-GKI kernels, with multi-manager support |
rsuntk |
rsuntk/KernelSU | Also known as RKSU |
backslashxx |
backslashxx/KernelSU | Manual-hook oriented |
KSU_REF takes a branch, tag or commit. Leave it blank to let the action pick a sensible ref for your kernel version.
Why the ref is validated
Every variant's
setup.shends its checkout withgit checkout "$1" || echo "[-] Checkout default branch". A ref that does not exist therefore does not fail — it quietly leaves you on the default branch. Following SukiSU-Ultra's own (stale) docs and passingsusfs-main, a branch that does not exist, gets you a "successful" build whose kernel has no SUSFS in it at all. This action validates the ref before invokingsetup.sh, and fails with the list of branches that do exist.
Set ENABLE_SUSFS=true. Patches come from susfs4ksu; the branch is chosen from your kernel version:
| Kernel | SUSFS branch |
|---|---|
| 4.9 / 4.14 / 4.19 / 5.4 | kernel-<version> |
| 5.10 | gki-android12-5.10 |
| 5.15 | gki-android13-5.15 |
| 6.1 | gki-android14-6.1 |
| 6.6 | gki-android15-6.6 |
| 6.12 | gki-android16-6.12 |
Override with SUSFS_BRANCH when the guess is wrong (for instance a 5.10 tree that is actually android13-based).
The sequence is: copy fs/susfs.c and include/linux/susfs*.h → apply the kernel-side 50_add_susfs_in_*.patch → apply the KernelSU-side 10_enable_susfs_for_ksu.patch. That last step is skipped automatically when the chosen variant already bundles SUSFS (for example SukiSU-Ultra's builtin).
The set of CONFIG_KSU_SUSFS_* options is read out of the Kconfig that was actually patched in rather than hardcoded, because it differs by branch: the GKI branches ship SUSFS v2.x (which has SUS_MAP and has dropped the AUTO_ADD_* knobs) while the non-GKI branches are still on v1.5.5 (which is the exact opposite).
Known rough edge: susfs4ksu's non-GKI branches have not been updated since early 2025 and still target KernelSU's old flat source layout. Most forks have since restructured into a modular
kernel/tree, so the KernelSU-side patch can fail for "old kernel + modern fork + SUSFS". The simplest fix isKSU_VARIANT=sukisu-ultrawithKSU_REF=builtin, which bundles SUSFS and does not need that patch. The build prints this advice when it hits the case.
path_umount() only arrived in Linux 5.9. KernelSU uses it to unmount its own mounts before an app checks for root, so older kernels need it backported or module unmounting silently does nothing.
Set ENABLE_PATH_UMOUNT=true. The code is upstream's, inserted into fs/namespace.c after do_umount(). It is skipped automatically on 5.9+ and on trees that already have the function.
| Option | Effect |
|---|---|
ENABLE_HIDE_STUFF |
Extra removal of KernelSU traces |
ENABLE_KPM |
SukiSU-Ultra's Kernel Patch Module support; runs patch_linux against the built Image. sukisu-ultra + arm64 only |
KSU_HOOK_MODE |
auto (kprobes on 5.10+, manual below) / kprobes / manual / tracepoint / syscall / none |
On older kernels, unreliable kprobes is the usual reason KernelSU installs but su does nothing — use manual there.
The AOSP prebuilt clang repository has a trap: every kernel-build branch lists all version directories, but only one or two actually contain a toolchain. The rest are empty placeholders — and an empty directory still produces a valid tarball that downloads with HTTP 200. So a wrong version does not 404; it fails forty minutes later with clang: not found.
Verified working pairs (2026-07):
CLANG_BRANCH |
CLANG_VERSION |
|---|---|
main-kernel |
r596125 (newest) |
main-kernel-2026 |
r584948c |
main-kernel-2025 |
r547379 |
main-kernel-build-2024 |
r510928 |
master-kernel-build-2022 |
r450784e |
Newer clang often fails to build 4.x trees; use r450784e for 4.9–4.19 and r547379 or newer for 5.10+. The build verifies that bin/clang really exists after extraction and warns about pairs outside this table.
Third-party toolchains work too: USE_CUSTOM_CLANG=true plus CUSTOM_CLANG_SOURCE (a git repo, or a direct zip/tar link).
Every key is documented inline in config.env. The ones people touch most:
| Option | Meaning |
|---|---|
KERNEL_IMAGE_NAME |
The kernel binary to flash; matches BOARD_KERNEL_IMAGE_NAME in your device tree. Usually Image.gz-dtb, Image.gz or Image |
EXTRA_CMDS / CUSTOM_CMDS |
Appended to every make; values may contain = |
USE_LLVM |
Full LLVM build (LLVM=1 LLVM_IAS=1), suitable for 5.10+ |
ADD_OVERLAYFS_CONFIG |
Needed for KernelSU modules and system read-write |
DISABLE_LTO |
LTO optimises the kernel but sometimes breaks the build |
DISABLE_CC_WERROR |
Fixes kernels that turn KernelSU's warnings into errors |
EXTRA_DEFCONFIG |
Arbitrary extra defconfig lines, e.g. CONFIG_TMPFS_XATTR=y |
BUILD_BOOT_IMG + SOURCE_BOOT_IMAGE |
Repack a boot.img; needs a direct link to a bootable image from the same device and ROM |
KSU_EXPECTED_SIZE / KSU_EXPECTED_HASH |
Custom manager signature, from ksud debug get-sign <apk> |
Existing config.env files keep working untouched. These keys are translated automatically, with a notice in the log:
| Old key | New key |
|---|---|
ENABLE_KERNELSU=true |
KSU_VARIANT=kernelsu |
KERNELSU_TAG |
KSU_REF |
APPLY_KSU_PATCH=true |
KSU_HOOK_MODE=manual |
DISABLE-LTO |
DISABLE_LTO |
.github/workflows/
build-kernel.yml build entry point (workflow_dispatch + workflow_call)
ci.yml shellcheck / actionlint / config validation / upstream link check
scripts/
lib.sh logging, retry, Kconfig read-write, patching, ref validation
config.sh config resolution, input overrides, validation
toolchain.sh clang / gcc / mkbootimg
source.sh kernel source checkout
kernelsu.sh variant registry and installation
patches.sh SUSFS / path_umount / hide_stuff / hooks / KPM
build.sh defconfig injection and compilation
package.sh AnyKernel3 / boot.img
patches/
legacy_ksu_hooks.sh the original sed-based hook script (fallback for manual mode)
build-kernel.yml is also reusable via workflow_call, so you can keep a very short per-device workflow.
| Symptom | Cause |
|---|---|
clang: not found, or an empty toolchain directory |
Invalid CLANG_BRANCH / CLANG_VERSION pair — see the table above |
ref '...' does not exist |
KSU_REF names a branch that is not there; the log lists the real ones |
| SUSFS kernel patch fails to apply | SUSFS_BRANCH does not match the kernel, or the tree was already modified |
KernelSU installs but su does nothing |
Unreliable kprobes on an old kernel — set KSU_HOOK_MODE=manual |
| Module mounts cannot be unmounted | Kernels below 5.9 need ENABLE_PATH_UMOUNT=true |
| defconfig not found | KERNEL_CONFIG is wrong; the log lists the available defconfigs |