Building a Kernel with SuSFS and KPM
Modifying the Kernel
TIP
The defconfig configuration file is located in the kernel_source_dir/arch/arm64/configs directory. There may be multiple files ending with defconfig. Choose the one that matches your phone model.
The following options need to be disabled in the defconfig file:
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 entries 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 final merge_hi3660_defconfig with your configuration file name.
Optional:
Change
# CONFIG_SECURITY_SELINUX_DEVELOP is not setto
CONFIG_SECURITY_SELINUX_DEVELOP=yThis will make the phone's SELinux status Permissive at boot.
Disable AVB Verification:
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_AVB=yChange to
# CONFIG_DM_VERITY is not set
# CONFIG_DM_VERITY_AVB is not setModifying hook.c to Fix Root Access Issues
diff -uNr 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-08-28 13:30:21.276759515 +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 areSuSFS
TIP
Currently: SuSFS v2.0.0 supports kernel v4.14.xxx (EMUI 10+) and v4.9.xxx (EMUI 9+). SuSFS v2.2.0 only supports kernel v4.9.xxx (EMUI 9+).
Compatible with ReSukiSU and SukiSU-Ultra (other KernelSU branches should also support it theoretically, please test on your own).
If you are using the SuSFS v2.0.0 patch for the 4.9 kernel, KPM is already integrated. You do not need to apply the patch again, but you need to add CONFIG_KPM=y to the defconfig file and patch the kernel to enable KPM.
WARNING
The new version of ReSukiSU has removed KPM support. If you still need to integrate KPM, please use an older version of ReSukiSU + SuSFS v2.0.0 patch, or use SukiSU-Ultra.
Patching for 4.9 Kernel
To use ReSukiSU, run the following command in the kernel source directory:
curl -LSs "https://raw.githubusercontent.com/ReSukiSU/ReSukiSU/main/kernel/setup.sh" | bashTo use SukiSU-Ultra, run the following command in the kernel source directory:
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s builtinNavigate to the SuSFS_Patches folder in this repository, then enter the v4.9.xxx folder.
Copy the patch to the root of the source code, then enter the following in the terminal:
patch -p1 < SuSFS_inline_hook_2.2.0.patchThe patch will be applied. If patching fails, you will see generated error files ending with .rej.
You can manually apply the patch based on the error locations indicated in the .rej files.
Legacy - Applying SuSFS v2.0.0 Patch for 4.9 Kernel
ReSukiSU needs to use an older version. Run the following commands in the kernel source directory:
curl -LSs "https://raw.githubusercontent.com/ReSukiSU/ReSukiSU/main/kernel/setup.sh" | bash
cd KernelSU
git reset --hard a13d71fNavigate to the SuSFS_Patches folder in this repository, then enter the v4.9.xxx/Legacy folder.
Copy the patch to the root of the source code, then enter the following in the terminal:
patch -p1 < SuSFS_KPM_inline_hook_2.0.0.patchThe patch will be applied. If patching fails, you will see generated error files ending with .rej.
You can manually apply the patch based on the error locations indicated in the .rej files.
Patching for 4.14 Kernel
Since the 4.14 kernel only has SuSFS v2.0.0, ReSukiSU also needs to use an older version. Run the following commands in the kernel source directory:
curl -LSs "https://raw.githubusercontent.com/ReSukiSU/ReSukiSU/main/kernel/setup.sh" | bash
cd KernelSU
git reset --hard a13d71fThen navigate to the SuSFS_Patches folder in this repository, and enter the v4.14.xxx folder.
Copy the patch to the root of the source code, then enter the following in the terminal:
patch -p1 < SuSFS_KPM_inline_hook_2.0.0.patchThe patch will be applied. If patching fails, you will see generated error files ending with .rej.
You can manually apply the patch based on the error locations indicated in the .rej files.
Then add the following to the defconfig:
# ReSukiSU - SuSFS
CONFIG_KSU=y
CONFIG_KSU_SUSFS=y
CONFIG_KSU_SUSFS_SUS_PATH=y
CONFIG_KSU_SUSFS_SUS_MOUNT=y
CONFIG_KSU_SUSFS_SUS_KSTAT=y
CONFIG_KSU_SUSFS_SPOOF_UNAME=y
CONFIG_KSU_SUSFS_ENABLE_LOG=y
CONFIG_KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS=y
CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG=y
CONFIG_KSU_SUSFS_OPEN_REDIRECT=y
CONFIG_KSU_SUSFS_SUS_MAP=yKPM
Pull Source Code
TIP
If you have already integrated SuSFS and pulled the source code, you can skip this step.
To use ReSukiSU, run the following commands in the kernel source directory:
curl -LSs "https://raw.githubusercontent.com/ReSukiSU/ReSukiSU/main/kernel/setup.sh" | bash
cd KernelSU
git reset --hard a13d71fTo use SukiSU-Ultra, run the following command in the kernel source directory:
curl -LSs "https://raw.githubusercontent.com/SukiSU-Ultra/SukiSU-Ultra/main/kernel/setup.sh" | bash -s builtinApplying KernelSU Patch
TIP
If you are using SuSFS, you can skip this step.
Patching for SukiSU-Ultra
You can revert path_umount via the KernelSU official website to obtain the module unload capability.
Add the following lines at the end of your device's defconfig file:
# KernelSU
CONFIG_KSU=y
CONFIG_KSU_MANUAL_HOOK=y
CONFIG_KSU_MANUAL_SU=yTo enable debug mode for SukiSU-Ultra, you also need to add:
CONFIG_KSU_DEBUG=yThen apply the following 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/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/Patching for ReSukiSU
Add the following lines at the end of your device's defconfig file:
# ReSukiSU
CONFIG_KSU=y
CONFIG_KSU_MANUAL_HOOK=yTo enable debug mode for KernelSU, you also need to add:
CONFIG_KSU_DEBUG=yThen refer to the ReSukiSU official website for modifications.
Applying KPM Patch
WARNING
KPM is currently only compatible with v4.9.xxx (EMUI 9+). Applying subsequent kernel patches may cause devices with v4.14.xxx (EMUI 10+) kernels to freeze.
This is presumably caused by EMUI 10 and above systems shielding USER LOCK.
TIP
If you are using the SuSFS v2.0.0 patch for the 4.9 kernel, KPM is already integrated and you do not need to apply the patch again.
WARNING
The new version of ReSukiSU has removed KPM support. If you need to integrate KPM, please use an older version of ReSukiSU or SukiSU-Ultra.
Then navigate to the SuSFS_Patches folder in this repository, and enter the v4.9.xxx folder.
Copy the KPM.patch to the root of the source code, then enter the following in the terminal:
patch -p1 < KPM.patchThe patch will be applied. If patching fails, you will see generated error files ending with .rej.
You can manually apply the patch based on the error locations indicated in the .rej files.
Then, you need to add the following to the kernel defconfig:
CONFIG_KPM=yThen compile the kernel, but do not package it. Follow the steps below to patch the kernel.
Patching the Kernel
Compile the kernel. At this point the kernel does not yet support KPM, so you need to patch the kernel to enable KPM.
Go to the Releases page of the SukiSU-Ultra/SukiSU's KernelPatch patch repository, find the latest release, download the patch_linux file, and place it in the kernel_source_dir/out/arch/arm64/boot directory. Then open a terminal in that directory and enter:
chmod +x patch_linux
patch_linux
rm -rf Image.gz
mv -f oImage Image
gzip -k ImageAt this point, a new Image.gz file will appear in this directory. Use this file for packaging.