How to Build
Thanks to the experts for their hard work; I'm just standing on the shoulders of giants.
The defconfig configuration file is located in the kernel source directory /arch/arm64/configs folder, and there may be multiple files ending in defconfig, depending on your phone model.
Install Dependencies
WARNING
Due to the global definition of yylloc in higher versions of Ubuntu/Debian, it is only recommended to use Ubuntu 20.04 or Ubuntu 18.04 (for Debian 13 and below, these two versions are recommended).
1. Install the packages required for compilation
Run:
sudo apt-get install libncurses5-dev libncurses-dev libssl-dev device-tree-compiler bc cpio lib32ncurses5-dev lib32z1 build-essential binutils bc bison build-essential ccache curl flex g++-multilib gcc-multilib git gnupg gperf imagemagick lib32ncurses5-dev lib32readline-dev lib32z1-dev liblz4-tool libncurses5 libncurses5-dev libsdl1.2-dev libssl-dev libxml2 libxml2-utils lzop pngcrush rsync schedtool squashfs-tools xsltproc zip zlib1g-dev git python22. Obtain GCC
git clone --depth=1 https://kkgithub.com/LineageOS/android_prebuilts_gcc_linux-x86_aarch64_aarch64-linux-android-4.9 aarch64-linux-android-4.9TIP
Huawei can only use the Aarch64 version
Obtaining the Source Code
Enter your device model code, download, and open the Code_opensource\kernel folder. This is your kernel source code; extract it.
WARNING
Due to encoding limitations, it can only be extracted to a non-NTFS/FAT partition in a Linux environment; otherwise, compilation will fail.
For other devices, you can find the kernel source code of third-party ROMs or search on the internet.
Modifying the Kernel
The following options of the defconfig configuration file need to be turned off:
CONFIG_HISI_PMALLOC=y
CONFIG_HIVIEW_SELINUX=y
CONFIG_HISI_SELINUX_EBITMAP_RO=y
CONFIG_HISI_SELINUX_PROT=y
CONFIG_HISI_RO_LSM_HOOKS=y
CONFIG_INTEGRITY=y
CONFIG_INTEGRITY_AUDIT=y
CONFIG_HUAWEI_CRYPTO_TEST_MDPP=y
CONFIG_HUAWEI_SELINUX_DSM=y
CONFIG_HUAWEI_HIDESYMS=y
CONFIG_HW_SLUB_SANITIZE=y
CONFIG_HUAWEI_ PROC_CHECK_ROOT=y
CONFIG_HW_ROOT_SCAN=y
CONFIG_HUAWEI_EIMA=y
CONFIG_HUAWEI_EIMA_ACCESS_CONTROL=y
CONFIG_HW_DOUBLE_FREE_DYNAMIC_CHECK=y
CONFIG_HKIP_ATKINFO=y
CONFIG_HW_KERNEL_STP=y
CONFIG_HISI_HHEE=y
CONFIG_HISI_HHEE_TOKEN=y
CONFIG_HISI_DIEID=y
CONFIG_HISI_SUBPMU=y
CONFIG_TEE_ANTIROOT_CLIENT=y
CONFIG_HWAA=yThese contents need to be changed to the following format:
# CONFIG_XXXXXX is not setAutomatic replacement command:
sed -i '/^CONFIG_HISI_PMALLOC=y$/c\# CONFIG_HISI_PMALLOC is not set
/^CONFIG_HIVIEW_SELINUX=y$/c\# CONFIG_HIVIEW_SELINUX is not set
/^CONFIG_HISI_SELINUX_EBITMAP_RO=y$/c\# CONFIG_HISI_SELINUX_EBITMAP_RO is not set
/^CONFIG_HISI_SELINUX_PROT=y$/c\# CONFIG_HISI_SELINUX_PROT is not set
/^CONFIG_HISI_RO_LSM_HOOKS=y$/c\# CONFIG_HISI_RO_LSM_HOOKS is not set
/^CONFIG_INTEGRITY=y$/c\# CONFIG_INTEGRITY is not set
/^CONFIG_INTEGRITY_AUDIT=y$/c\# CONFIG_INTEGRITY_AUDIT is not set
/^CONFIG_HUAWEI_CRYPTO_TEST_MDPP=y$/c\# CONFIG_HUAWEI_CRYPTO_TEST_MDPP is not set
/^CONFIG_HUAWEI_SELINUX_DSM=y$/c\# CONFIG_HUAWEI_SELINUX_DSM is not set
/^CONFIG_HUAWEI_HIDESYMS=y$/c\# CONFIG_HUAWEI_HIDESYMS is not set
/^CONFIG_HW_SLUB_SANITIZE=y$/c\# CONFIG_HW_SLUB_SANITIZE is not set
/^CONFIG_HUAWEI_PROC_CHECK_ROOT=y$/c\# CONFIG_HUAWEI_PROC_CHECK_ROOT is not set
/^CONFIG_HW_ROOT_SCAN=y$/c\# CONFIG_HW_ROOT_SCAN is not set
/^CONFIG_HUAWEI_EIMA=y$/c\# CONFIG_HUAWEI_EIMA is not set
/^CONFIG_HUAWEI_EIMA_ACCESS_CONTROL=y$/c\# CONFIG_HUAWEI_EIMA_ACCESS_CONTROL is not set
/^CONFIG_HW_DOUBLE_FREE_DYNAMIC_CHECK=y$/c\# CONFIG_HW_DOUBLE_FREE_DYNAMIC_CHECK is not set
/^CONFIG_HKIP_ATKINFO=y$/c\# CONFIG_HKIP_ATKINFO is not set
/^CONFIG_HW_KERNEL_STP=y$/c\# CONFIG_HW_KERNEL_STP is not set
/^CONFIG_HISI_HHEE=y$/c\# CONFIG_HISI_HHEE is not set
/^CONFIG_HISI_HHEE_TOKEN=y$/c\# CONFIG_HISI_HHEE_TOKEN is not set
/^CONFIG_HISI_DIEID=y$/c\# CONFIG_HISI_DIEID is not set
/^CONFIG_HISI_SUBPMU=y$/c\# CONFIG_HISI_SUBPMU is not set
/^CONFIG_TEE_ANTIROOT_CLIENT=y$/c\# CONFIG_TEE_ANTIROOT_CLIENT is not set
/^CONFIG_HWAA=y$/c\# CONFIG_HWAA is not set' merge_hi3660_defconfigReplace the last merge_hi3660_defconfig with your configuration file
Optional Part:
Change
# CONFIG_SECURITY_SELINUX_DEVELOP is not setto
CONFIG_SECURITY_SELINUX_DEVELOP=yThis will enable SELinux on the phone to be in Permissive state upon boot.
Disable AVB Verification:
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_AVB=yChange to
# CONFIG_DM_VERITY=y is not set
# CONFIG_DM_VERITY_AVB=y is not setIntegrating KernelSU
1. Pull Source Code
curl -LSs "https://raw.githubusercontent.com/tiann/KernelSU/main/kernel/setup.sh" | bash -s v0.9.2TIP
The official KernelSU v0.9.5 source code conflicts with the kernel code; you need to use version v0.9.2 to pull the source code.
2. Enable KernelSU
Add the following lines to the end of your device's defconfig configuration file:
# KernelSU
CONFIG_KSU=yTo enable KernelSU's debug mode, you also need to add:
CONFIG_KSU_DEBUG=y3. Apply the Patch
Refer to the KernelSU official website for modification.
WARNING
If your kernel does not have vfs_statx and do_faccessat, do not copy the general code above; use the code provided below. Do not ignore it!
4. Modify hooks.c to enable the module
Refer to this Github Commit
Integrating RKSU/KernelSU-Next
1. Pull the source code
curl -LSs "https://raw.githubusercontent.com/rsuntk/KernelSU/main/kernel/setup.sh" | bash -s maincurl -LSs "https://raw.githubusercontent.com/KernelSU-Next/KernelSU-Next/next/kernel/setup.sh" | bash -s legacy2.Enable RKSU/KernelSU-Next
Add the following lines to the end of your device's defconfig file:
# KernelSU
CONFIG_KSU=y
CONFIG_KSU_MANUAL_HOOK=yTo enable KernelSU debug mode, you also need to add:
CONFIG_KSU_DEBUG=y3.Apply patches
In addition, you can also backport path_umount via the KernelSU offical webside to enable the module unmount feature.
4.Modify hooks.c to enable modules
Refer to this GithubCommit
Integrate SukiSU-Ultra
1.Pull the Source Code
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s builtin2.Apply patches
diff -ruN a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c 2019-02-27 18:31:35.000000000 +0800
+++ b/fs/exec.c 2026-01-28 17:58:55.317129000 +0800
@@ -1907,11 +1907,21 @@
} while (cmpxchg(&mm->flags, old, new) != old);
}
+#ifdef CONFIG_KSU
+__attribute__((hot))
+extern int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
+ void *__never_use_argv, void *__never_use_envp,
+ int *__never_use_flags);
+#endif
+
SYSCALL_DEFINE3(execve,
const char __user *, filename,
const char __user *const __user *, argv,
const char __user *const __user *, envp)
{
+#ifdef CONFIG_KSU
+ ksu_handle_execve_sucompat((int *)AT_FDCWD, &filename, NULL, NULL, NULL);
+#endif
return do_execve(getname(filename), argv, envp);
}
@@ -1933,6 +1943,9 @@
const compat_uptr_t __user *, argv,
const compat_uptr_t __user *, envp)
{
+#ifdef CONFIG_KSU
+ ksu_handle_execve_sucompat((int *)AT_FDCWD, &filename, NULL, NULL, NULL);
+#endif
return compat_do_execve(getname(filename), argv, envp);
}diff -ruN a/fs/open.c b/fs/open.c
--- a/fs/open.c 2019-02-27 18:31:35.000000000 +0800
+++ b/fs/open.c 2026-01-28 17:58:55.473127000 +0800
@@ -360,6 +360,12 @@
* We do this by temporarily clearing all FS-related capabilities and
* switching the fsuid/fsgid around to the real ones.
*/
+#ifdef CONFIG_KSU
+__attribute__((hot))
+extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user,
+ int *mode, int *flags);
+#endif
+
SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
{
const struct cred *old_cred;
@@ -370,6 +376,9 @@
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 -ruN a/fs/read_write.c b/fs/read_write.c
--- a/fs/read_write.c 2019-02-27 18:31:35.000000000 +0800
+++ b/fs/read_write.c 2026-01-28 17:58:55.497126000 +0800
@@ -610,11 +610,22 @@
file->f_pos = pos;
}
+#ifdef CONFIG_KSU
+// extern bool ksu_vfs_read_hook __read_mostly;
+bool ksu_vfs_read_hook __read_mostly = true; // fix compiler ghost define
+extern __attribute__((cold)) int ksu_handle_sys_read(unsigned int fd,
+ char __user **buf_ptr, size_t *count_ptr);
+#endif
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
{
struct fd f = fdget_pos(fd);
ssize_t ret = -EBADF;
+
+#ifdef CONFIG_KSU
+ if (unlikely(ksu_vfs_read_hook))
+ ksu_handle_sys_read(fd, &buf, &count);
+#endif
if (f.file) {
loff_t pos = file_pos_read(f.file);
ret = vfs_read(f.file, buf, count, &pos);diff -ruN a/fs/stat.c b/fs/stat.c
--- a/fs/stat.c 2019-02-27 18:31:35.000000000 +0800
+++ b/fs/stat.c 2026-01-28 17:58:55.509126000 +0800
@@ -287,6 +287,12 @@
return cp_new_stat(&stat, statbuf);
}
+#ifdef CONFIG_KSU
+__attribute__((hot))
+extern int ksu_handle_stat(int *dfd, const char __user **filename_user,
+ int *flags);
+#endif
+
#if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
struct stat __user *, statbuf, int, flag)
@@ -294,6 +300,9 @@
struct kstat stat;
int error;
+#ifdef CONFIG_KSU
+ ksu_handle_stat(&dfd, &filename, &flag);
+#endif
error = vfs_fstatat(dfd, filename, &stat, flag);
if (error)
return error;
@@ -436,6 +445,9 @@
struct kstat stat;
int error;
+#ifdef CONFIG_KSU
+ ksu_handle_stat(&dfd, &filename, &flag);
+#endif
error = vfs_fstatat(dfd, filename, &stat, flag);
if (error)
return error;diff -ruN a/drivers/input/input.c b/drivers/input/input.c
--- a/drivers/input/input.c 2019-02-27 18:31:32.000000000 +0800
+++ b/drivers/input/input.c 2026-01-28 17:58:52.537176000 +0800
@@ -425,11 +425,21 @@
* to 'seed' initial state of a switch or initial position of absolute
* axis, etc.
*/
+#ifdef CONFIG_KSU
+extern bool ksu_input_hook __read_mostly;
+extern __attribute__((cold)) int ksu_handle_input_handle_event(
+ unsigned int *type, unsigned int *code, int *value);
+#endif
void input_event(struct input_dev *dev,
unsigned int type, unsigned int code, int value)
{
unsigned long flags;
+
+#ifdef CONFIG_KSU
+ if (unlikely(ksu_input_hook))
+ ksu_handle_input_handle_event(&type, &code, &value);
+#endif
if (is_event_supported(type, dev->evbit, EV_MAX)) {
spin_lock_irqsave(&dev->event_lock, flags);diff -ruN a/security/selinux/hooks.c b/security/selinux/hooks.c
--- a/security/selinux/hooks.c 2019-02-27 18:31:35.000000000 +0800
+++ b/security/selinux/hooks.c 2026-01-28 17:58:56.593108000 +0800
@@ -2291,16 +2291,37 @@
const struct task_security_struct *old_tsec,
const struct task_security_struct *new_tsec)
{
+#ifdef CONFIG_KSU
+ static u32 ksu_sid;
+ char *secdata;
+#endif
int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
int rc;
+#ifdef CONFIG_KSU
+ int error;
+ u32 seclen;
+#endif
if (!nnp && !nosuid)
return 0; /* neither NNP nor nosuid */
if (new_tsec->sid == old_tsec->sid)
return 0; /* No change in credentials */
+#ifdef CONFIG_KSU
+ if (!ksu_sid)
+ security_secctx_to_secid("u:r:su:s0", strlen("u:r:su:s0"), &ksu_sid);
+
+ error = security_secid_to_secctx(old_tsec->sid, &secdata, &seclen);
+ if (!error) {
+ rc = strcmp("u:r:init:s0", secdata);
+ security_release_secctx(secdata, seclen);
+ if (rc == 0 && new_tsec->sid == ksu_sid)
+ return 0;
+ }
+#endif
+
/*
* The only transitions we permit under NNP or nosuid
* are transitions to bounded SIDs, i.e. SIDs that arediff -ruN a/kernel/reboot.c b/kernel/reboot.c
--- a/kernel/reboot.c 2019-02-27 18:31:34.000000000 +0800
+++ b/kernel/reboot.c 2026-01-28 17:58:56.149115000 +0800
@@ -277,12 +277,19 @@
*
* reboot doesn't sync: do that yourself before calling this.
*/
+#ifdef CONFIG_KSU
+extern int ksu_handle_sys_reboot(int magic1, int magic2, unsigned int cmd, void __user **arg);
+#endif
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
void __user *, arg)
{
struct pid_namespace *pid_ns = task_active_pid_ns(current);
char buffer[256];
int ret = 0;
+#ifdef CONFIG_KSU
+ ksu_handle_sys_reboot(magic1, magic2, cmd, &arg);
+#endif
+
/* We only trust the superuser with rebooting the system. */
if (!ns_capable(pid_ns->user_ns, CAP_SYS_BOOT))diff -ruN a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c 2019-02-27 18:31:34.000000000 +0800
+++ b/kernel/sys.c 2026-01-28 17:58:56.161115000 +0800
@@ -609,6 +609,10 @@
* This function implements a generic ability to update ruid, euid,
* and suid. This allows you to implement the 4.4 compatible seteuid().
*/
+#ifdef CONFIG_KSU
+extern int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid);
+#endif
+
SYSCALL_DEFINE3(setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
{
struct user_namespace *ns = current_user_ns();
@@ -621,6 +625,11 @@
keuid = make_kuid(ns, euid);
ksuid = make_kuid(ns, suid);
+#ifdef CONFIG_KSU_SUSFS
+ if (ksu_handle_setresuid(ruid, euid, suid)) {
+ pr_info("Something wrong with ksu_handle_setresuid()\\n");
+ }
+#endif
if ((ruid != (uid_t) -1) && !uid_valid(kruid))
return -EINVAL;diff -ruN a/security/Kconfig b/security/Kconfig
--- a/security/Kconfig 2019-02-27 18:31:35.000000000 +0800
+++ b/security/Kconfig 2026-01-28 17:58:56.577108000 +0800
@@ -237,13 +237,5 @@
help
Protects the security huulks from further modifications, after init.
-source security/mdpp_selftest/Kconfig
-source security/hwselinux/Kconfig
-source security/kernel_harden/Kconfig
-source security/check_root/Kconfig
-source security/hw_root_scan/Kconfig
-source security/check_double_free/Kconfig
-source security/hkip_atkinfo/Kconfig
-source security/kernel_stp/Kconfig
endmenudiff -ruN a/security/Makefile b/security/Makefile
--- a/security/Makefile 2019-02-27 18:31:35.000000000 +0800
+++ b/security/Makefile 2026-01-28 17:58:56.577108000 +0800
@@ -9,7 +9,6 @@
subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
subdir-$(CONFIG_SECURITY_YAMA) += yama
subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin
-subdir-$(CONFIG_HKIP_ATKINFO) += hkip_atkinfo
# always enable default capabilities
obj-y += commoncap.o
@@ -26,18 +25,10 @@
obj-$(CONFIG_SECURITY_YAMA) += yama/
obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
-obj-$(CONFIG_HKIP_ATKINFO) += hkip_atkinfo/
# Object integrity file lists
subdir-$(CONFIG_INTEGRITY) += integrity
obj-$(CONFIG_INTEGRITY) += integrity/
# HW Object
-subdir-$(CONFIG_HUAWEI_SELINUX_DSM) += hwselinux
-obj-$(CONFIG_HUAWEI_SELINUX_DSM) += hwselinux/
-obj-$(CONFIG_HUAWEI_PROC_CHECK_ROOT) += check_root/
-obj-$(CONFIG_HUAWEI_CRYPTO_TEST_MDPP) += mdpp_selftest/
-obj-$(CONFIG_HW_ROOT_SCAN) += hw_root_scan/
-obj-$(CONFIG_HW_DOUBLE_FREE_DYNAMIC_CHECK) += check_double_free/
-obj-$(CONFIG_HW_KERNEL_STP) += kernel_stp/
include security/kernel_harden/Makefile--- a 2026-01-28 21:33:24.492017000 +0800
+++ b 2026-01-28 21:34:12.088802416 +0800
@@ -214,4 +214,4 @@
obj-$(CONFIG_HW_MEMORY_MONITOR) += allocpages_delayacct/
obj-y += cfi/
obj-$(CONFIG_HUAWEI_DUBAI) += dubai/
-obj-$(CONFIG_KSU) += kernelsu/
+obj-y += kernelsu/In addition, you can also backport path_umount via the KernelSU offical webside to enable the module unmount feature.
3.Enable SukiSU-Ultra
Add the following lines to the end of your device's defconfig file:
# KernelSU
CONFIG_KSU=y
CONFIG_KSU_MANUAL_HOOK=y
CONFIG_KSU_MANUAL_SU=y
# CONFIG_KSU_SUSFS is not setTo enable SukiSU-Ultra debug mode, you also need to add:
CONFIG_KSU_DEBUG=yCONFIG_KSU_DEBUG=yIntegrate ReSukiSU
1.Pull the Sources Code
curl -LSs "https://raw.githubusercontent.com/ReSukiSU/ReSukiSU/main/kernel/setup.sh" | bash2.Enable ReSukiSU
Add the following lines to the end of your device's defconfig file:
# KernelSU
CONFIG_KSU=y
CONFIG_KSU_MANUAL_HOOK=yTo enable KernelSU debug mode, you also need to add:
CONFIG_KSU_DEBUG=y3.Apply Patches
Refer to the ReSukiSU offical webside to modify.
Even if your kernel version is lower than 4.19, you still need to use the version of the sys_read hook intended for 4.19+.
Build
1.Set up default Python2
sudo ln -sf /usr/bin/python2.7 /usr/bin/python2.Set environment variables.
export ARCH=arm64
export PATH=$PATH:<Path to your GCC>
export CROSS_COMPILE=aarch64-linux-android-3.Build
Run this command on your kernel root:
make ARCH=arm64 O=out <defconfig>(Only name,not path)
make ARCH=arm64 O=out -j8Here, -j8 specifies the number of CPU cores to use for compilation; it should be set to your CPU core count × 2.
4.Package after compilation.
After compilation, there will be an Image.gz file in the out/arch/arm64/boot/ path. Copy it to the tools folder in the root directory of the kernel.
Modify pack_kernerimage_cmd.sh file
Change --kernel kernel to --kernel Image.gz to fix file name problem.
If your SELinux is in permissive mode, change androidboot.selinux=enforcing to androidboot.selinux=permissive
Change--os_patch_level 2020-01-01 to update the kernel build timestamp.
Pack up
Run:
bash pack_kernerimage_cmd.shThen a kernel.img file will appear in the current directory. Flash it to the kernel partition using fastboot.