首页
社区
课程
招聘
[原创]meizu note6编译lineageOS18和集成KernelSU
发表于: 2025-8-19 18:37 1255

[原创]meizu note6编译lineageOS18和集成KernelSU

2025-8-19 18:37
1255

编译系统

操作系统:archlinux

手机型号:meizu note6(m1721)

编译系统:lineageOS18.1

内核,设备树,vendor:MeizuCustoms OSC (MeizuSucks)

JDK环境:open-jdk11

python环境:python3

tips:以下联网操作需要有个稳定的科学上网工具。

只记录使用arch系统编译的过程,其他系统参考 lineageos 官方编译步骤。

下载依赖

下载repo工具

sudo pacman -S repo

对于其他操作系统下载repo工具

mkdir ~/bin
PATH=~/bin:$PATH
curl <53dK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6N6r3!0J5j5h3N6W2i4K6u0W2k6$3!0G2k6$3I4W2j5i4m8A6M7#2)9J5k6h3y4G2L8g2)9J5c8X3N6A6N6q4)9J5k6s2u0W2M7r3!0Q4x3X3c8V1L8%4N6F1L8r3!0S2k6s2y4Q4x3V1k6J5k6i4m8G2i4K6t1$3k6%4c8Q4x3@1u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7i4K6t1$3k6%4c8Q4x3@1u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7i4K6N6q4i4K6u0r3j5X3W2F1i4K6u0r3M7X3g2H3L8H3`.`.
chmod a+x ~/bin/repo

下载构建包

paru -S lineageos-devel

同步代码

建立工作目录

mkdir lineageos-workspace
cd linageos-workspace

初始化代码仓库(使用清华镜像源)

repo init -u <18aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0K9i4u0J5L8%4u0K6i4K6u0W2N6s2g2F1j5g2)9J5k6i4c8K6K9h3&6Y4K9s2g2S2i4K6u0W2k6h3c8#2i4K6u0W2j5$3&6Q4x3V1k6Y4K9i4c8Q4x3V1k6D9K9h3&6W2j5h3N6W2e0#2y4Q4x3V1k6x3K9h3&6W2j5h3N6W2e0#2y4Q4x3V1k6S2L8X3c8J5L8$3W2V1i4K6u0W2k6$3W2@1i4K6t1$3k6%4c8Q4x3@1u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7i4K6u0V1j5W2)9J5y4X3&6T1M7%4m8Q4x3@1u0D9K9h3&6W2j5h3N6W2i4K6u0V1x3U0q4Q4x3X3f1H3i4K6t1$3L8X3u0K6M7q4)9K6b7W2)9J5k6q4)9J5k6r3N6A6N6q4)9J5k6r3I4X3M7H3`.`.

更换为清华镜像源,打开.repo/manifests/default.xml,将

<remote  name="github"
  fetch=".."
  review="review.lineageos.org" />

改成

<remote  name="github"
  fetch="<9e7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6Q4x3U0k6Y4N6q4)9K6b7W2)9J5y4Y4q4#2L8%4c8Q4x3@1u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7i4K6u0r3i4K6t1$3k6%4c8Q4x3@1t1`.

<remote  name="lineage"
  fetch="<326K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0K9i4u0J5L8%4u0K6i4K6u0W2N6s2g2F1j5g2)9J5k6i4c8K6K9h3&6Y4K9s2g2S2i4K6u0W2k6h3c8#2i4K6u0W2j5$3&6Q4x3V1k6Y4K9i4c8Q4x3V1k6D9K9h3&6W2j5h3N6W2e0#2y4Q4x3V1k6Q4x3U0k6Y4N6q4)9K6b7W2)9J5y4Y4q4#2L8%4c8Q4x3@1t1`.
  review="review.lineageos.org" />

或则直接修改~/.gitconfig配置文件,添加以下配置

[url "<4d6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0K9i4u0J5L8%4u0K6i4K6u0W2N6s2g2F1j5g2)9J5k6i4c8K6K9h3&6Y4K9s2g2S2i4K6u0W2k6h3c8#2i4K6u0W2j5$3&6Q4x3V1k6Y4K9i4c8Q4x3V1k6Y4K9i4c8Q4x3X3c8J5k6i4m8G2i4K6t1$3k6%4c8Q4x3@1u0Q4x3U0k6I4N6h3!0@1i4K6y4n7i4K6g2p5
    insteadof = <2b9K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4k6i4u0J5K9i4c8Q4x3X3g2Y4L8$3!0Y4L8r3g2K6L8%4g2J5j5$3g2Q4x3X3g2U0L8$3#2Q4x3V1k6Y4K9i4c8Q4x3X3c8J5k6i4m8G2i4K6t1$3k6%4c8Q4x3@1t1`.
[url "<479K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0K9i4u0J5L8%4u0K6i4K6u0W2N6s2g2F1j5g2)9J5k6i4c8K6K9h3&6Y4K9s2g2S2i4K6u0W2k6h3c8#2i4K6u0W2j5$3&6Q4x3V1k6Y4K9i4c8Q4x3V1k6D9K9h3&6W2j5h3N6W2e0#2y4Q4x3V1k6Q4x3U0k6Y4N6q4)9K6b7W2)9J5y4Y4q4#2L8%4c8Q4x3@1u0Q4y4f1b7`.
    insteadof = <079K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5k6i4k6A6k6i4N6Q4x3X3g2D9K9h3&6W2j5h3N6W2L8%4y4Q4x3X3g2G2M7X3N6Q4x3V1k6Q4x3U0k6Y4N6q4)9K6b7R3`.`.
[url "<a21K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0K9i4u0J5L8%4u0K6i4K6u0W2N6s2g2F1j5g2)9J5k6i4c8K6K9h3&6Y4K9s2g2S2i4K6u0W2k6h3c8#2i4K6u0W2j5$3&6Q4x3V1k6Y4K9i4c8Q4x3V1k6m8e0#2y4b7i4K6u0r3i4K6t1$3k6%4c8Q4x3@1u0Q4x3U0k6I4N6h3!0@1i4K6y4n7i4K6g2p5
    insteadof = <8ebK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6S2L8X3c8J5L8$3W2V1i4K6u0W2k6$3!0G2k6$3I4W2M7$3!0#2M7X3y4W2i4K6u0W2j5$3!0E0i4K6u0r3i4K6t1$3k6%4c8Q4x3@1t1`.
[url "<6b4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6E0K9i4u0J5L8%4u0K6i4K6u0W2N6s2g2F1j5g2)9J5k6i4c8K6K9h3&6Y4K9s2g2S2i4K6u0W2k6h3c8#2i4K6u0W2j5$3&6Q4x3V1k6Y4K9i4c8Q4x3V1k6D9K9h3&6W2j5h3N6W2e0#2y4Q4x3V1k6x3K9h3&6W2j5h3N6W2e0#2y4Q4x3V1k6Q4x3U0k6Y4N6q4)9K6b7W2)9J5y4Y4q4#2L8%4c8Q4x3@1u0Q4y4f1b7`.
    insteadof = <9a7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6x3K9h3&6W2j5h3N6W2e0#2y4Q4x3V1k6Q4x3U0k6Y4N6q4)9K6b7R3`.`.

同步代码

repo sync

添加对应型号的kernel、device、vendor

这里我使用的 meizucustoms 社区提供。

方式1:配置文件同步。

.repo/local_manifests创建mzlocal_r.xml文件,添加内容如下。

<?xml version="1.0" encoding="UTF-8"?>
<manifest>
  <project name="meizucustoms/android_device_meizu_m1721" path="device/meizu/m1721" remote="github" revision="lineage-18.1" />
  <project name="meizucustoms/proprietary_vendor_meizu" path="vendor/meizu" remote="github" revision="lineage-18.1" />
  <project name="meizucustoms/android_kernel_meizu_m1721" path="kernel/meizu/m1721" remote="github" revision="lineage-18.1" />
</manifest>

再次使用repo sync命令同步代码。

方式2:手动同步代码。

在工作目录,拉取kernel仓库代码。(内核源码)

git clone <095K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6E0k6h3W2*7N6h3y4#2M7%4c8G2L8i4y4Q4x3V1k6S2L8X3c8J5L8$3W2V1i4K6g2X3K9$3g2J5L8X3g2D9i4K6g2X3L8h3g2A6P5Y4g2Q4y4h3k6E0x3e0M7J5x3g2)9J5y4X3N6@1i4K6y4n7i4K6t1$3L8X3u0K6M7q4)9K6b7W2)9J5k6r3u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7L8r3W2F1k6h3q4Y4k6g2)9J5k6o6p5^5i4K6u0W2x3g2)9J5y4X3&6T1M7%4m8Q4x3@1u0C8k6i4u0F1k6h3I4Q4x3V1k6E0k6h3W2*7N6g2)9J5c8X3@1I4y4K6t1I4

拉去device仓库代码。(设备树)

git clone <bccK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6E0k6h3W2*7N6h3y4#2M7%4c8G2L8i4y4Q4x3V1k6S2L8X3c8J5L8$3W2V1i4K6g2X3k6r3g2$3K9h3y4W2i4K6g2X3L8h3g2A6P5Y4g2Q4y4h3k6E0x3e0M7J5x3g2)9J5y4X3N6@1i4K6y4n7i4K6t1$3L8X3u0K6M7q4)9K6b7W2)9J5k6r3u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7L8r3W2F1k6h3q4Y4k6g2)9J5k6o6p5^5i4K6u0W2x3g2)9J5y4X3&6T1M7%4m8Q4x3@1u0V1k6i4k6A6j5$3g2Q4x3V1k6E0k6h3W2*7N6g2)9J5c8X3@1I4y4K6t1I4

拉去vendor仓库代码。(供应商文件)

git clone <bf6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6E0k6h3W2*7N6h3y4#2M7%4c8G2L8i4y4Q4x3V1k6S2L8X3c8J5L8$3W2V1i4K6g2X3N6X3g2F1k6r3!0J5i4K6g2X3L8h3g2A6P5Y4g2Q4y4h3k6E0x3e0M7J5x3g2)9J5y4X3N6@1i4K6y4n7i4K6t1$3L8X3u0K6M7q4)9K6b7W2)9J5k6r3u0Q4x3U0k6F1j5Y4y4H3i4K6y4n7L8r3W2F1k6h3q4Y4k6g2)9J5k6o6p5^5i4K6u0W2x3g2)9J5y4X3&6T1M7%4m8Q4x3@1u0$3k6h3&6V1L8%4u0Q4x3V1k6E0k6h3W2*7N6g2)9J5c8X3@1I4y4K6t1I4

编译源码

开启缓存以加快构建速度

export USE_CCACHE=1
ccache -M 50G

初始化构建环境

cd lineageos-workspace
source build/envsetup.sh
breakfast m1721
brunch bacon

编译问题汇总

webview.apk编译失败

删除external/chromium-webview文件。

rm -rf external/chromium-webview

重新拉去代码。

git clone <cdeK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6x3K9h3&6W2j5h3N6W2e0#2y4Q4x3V1k6S2L8X3c8J5L8$3W2V1i4K6g2X3k6i4S2@1k6i4u0F1j5h3I4Q4y4h3k6U0K9s2u0G2L8h3W2#2L8g2)9J5k6s2N6W2j5Y4k6A6k6i4N6Q4x3U0k6Y4N6q4)9K6b7W2)9J5y4X3&6T1M7%4m8Q4x3@1u0W2P5s2c8W2M7X3&6S2L8q4)9J5c8X3y4Z5M7X3!0E0K9i4g2E0i4K6u0V1N6$3g2T1N6X3W2W2N6H3`.`.

mke2fs命令报错Invalid filesystem option set: has_journal, extent,......

该命令依赖于e2fsprogs包。当前系统的包版本为1.47.2-1,编译时使用的是1.45.4。编译系统时,如果系统存在这个包则会依赖,导致编译失败。

修复方法降级e2fsprogs包到1.46.1

集成KernelSU

meizu note6是非GKI(generic kernel image)内核,官方没有支持和编译好的镜像,官方提供了非GKI内核的集成kernelSU的方法。

  1. 借助kprobe自动集成。
  2. 手动修改内核源码。

两种方式我都进行了测试,第一种方法kernelSU管理器显示已经工作中,但是没法使用su不存在。然后进行第二种方法的测试,可以正常使用root权限。具体修改代码如下。

添加内核补丁

添加kernelSU到内核源码树,进入内核根目录执行命令。

cd kernel/meizu/m1721
curl -LSs "<4d6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5j5i4N6Q4x3X3g2Y4K9i4c8Z5N6h3u0#2M7$3g2J5j5$3!0F1N6r3g2F1N6q4)9J5k6h3y4G2L8g2)9J5c8Y4c8A6j5h3&6F1i4K6u0r3d9$3g2J5L8X3g2D9f1#2g2Q4x3V1k6E0j5h3W2F1i4K6u0r3K9$3g2J5L8X3g2D9i4K6u0r3M7$3g2@1N6i4m8Q4x3X3g2K6K9q4)9J5y4X3N6@1i4K6y4n7i4K6t1$3M7i4g2G2N6q4)9K6b7W2)9J5y4X3&6T1M7%4m8Q4x3@1u0Q4y4@1y4Q4x3U0k6F1j5Y4y4H3i4K6y4n7j5X3q4K6K9q4)9J5y4X3&6T1M7%4m8Q4x3@1u0Q4x3X3c8K6i4K6t1$3L8X3u0K6M7q4)9K6b7Y4j5H3i4K6u0W2z5g2)9J5k6e0f1`.

找到设备代号_defconfig文件,这里我是meizu note6设备代号是m1721m1721_defconfigarch/arm64/configs文件夹找到,不同设备的deconfig文件也可能存在arch/arm64/configs/vendor。在m1721_defconfig启用kernelSU

+# KernelSU
+CONFIG_KSU=y

对内核源代码进打补丁如下:

修改kernel/meizu/m1721/fs/exec.c

+#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);
 }

修改kernel/meizu/m1721/fs/open.c,有些内核可能没有do_faccessat方法,找到access()方法注释的进行补丁即可。

@@ -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;

对于meizu note6的内核就没有do_faccessat方法,添加补丁如下:

+#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
 * switching the fsuid/fsgid around to the real ones.
 */
SYSCALL_DEFINE3(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);
+  #endi

修改kernel/meizu/m1721/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))

修改kernel/meizu/m1721/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;

对内核中没有vfs_statx方法,使用vfs_fsstatat方法代替。当前编译的meizu note6内核没有vfs_statx方法,具体补丁代码如下:

+#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)
{
	struct path path;
	int error = -EINVAL;
	unsigned int lookup_flags = 0;
+  #ifdef CONFIG_KSU
+   ksu_handle_stat(&dfd, &filename, &flag);
+  #endif

安全模式

要使用 KernelSU 内置的安全模式,你还需要修改 drivers/input/input.c 中的 input_handle_event 方法:

**TIP:**强烈建议开启此功能,对用户救砖会非常有帮助!

莫名其妙进入安全模式?

如果你采用手动集成的方式,并且没有禁用CONFIG_KPROBES,那么用户在开机之后按音量下,也可能触发安全模式!因此如果使用手动集成,你需要关闭 CONFIG_KPROBES

@@ -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);

pm 命令执行失败?

你需要同时修改 fs/devpts/inode.c,补丁如下:

@@ -602,6 +602,8 @@ struct dentry *devpts_pty_new(struct pts_fs_info *fsi, int index, void *priv)
        return dentry;
 }

+extern int ksu_handle_devpts(struct inode*);
+
 /**
  * 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)
 {
+       ksu_handle_devpts(dentry->d_inode);
        if (dentry->d_sb->s_magic != DEVPTS_SUPER_MAGIC)
                return NULL;
        return dentry->d_fsdata;

path_umount

你可以通过从 K5.9 向旧版本移植 path_umount,在 GKI 之前的内核上获得卸载模块的功能。你可以通过以下补丁作为参考:

@@ -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.

补丁改完后,可以进行内核编译了。

手动修补boot.img

编译内核查看下面的教程进行编译。编译好后,查看out/arch/arm64/boot是文件是否如下图所示:

安装magiskboot进行boot.img的解包和打包。

paru -S magiskboot-git

首先提取rom里面的boot.img到一个空的目录,使用magiskboot unpack boot.img进行解包得到kernel文件。使用上面编译好的Image替换:mv -f Image kernel。最后使用magisk repack boot.img打包得到new-boot.img文件。

刷入new-boot.img文件。

adb reboot bootloader
fastboot flash boot new-boot.img
fastboot reboot

刷入之后安装kernel.apk文件查看kernelSU是否工作中。这里需要安装或卸载一个软件,kernelSU才会显示工作中。此时可以挂载shell为超级用户。使用adb shell才看是否存在su命令。

kernelSU编译bugs

make menuconfig报错requires the ncurses libraries

arch系统下,使用命令make menuconfig报错requires the ncurses libraries

修改scripts/kconfig/lxdialog/check-lxdialog.shmain方法前面加int

集成kernelSU-Next

添加内核补丁

kernelSU步骤一样,只需更改下载代码。

curl -LSs "<794K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5j5i4N6Q4x3X3g2Y4K9i4c8Z5N6h3u0#2M7$3g2J5j5$3!0F1N6r3g2F1N6q4)9J5k6h3y4G2L8g2)9J5c8Y4u0A6k6Y4y4^5k6q4)9J5c8V1E0W2M7X3&6W2L8q4y4g2i4K6u0V1e0X3g2^5N6q4)9J5c8X3&6W2P5s2c8Q4x3V1k6C8k6i4u0F1k6h3I4Q4x3V1k6K6k6i4c8#2M7q4)9J5k6i4y4Z5i4K6t1$3k6%4c8Q4x3@1u0Q4x3U0k6I4N6h3!0@1i4K6y4n7i4K6t1$3L8X3u0K6M7q4)9K6b7W2)9%4b7#2)9J5y4X3&6T1M7%4m8Q4x3@1u0T1j5i4y4Z5i4K6t1$3L8X3u0K6M7q4)9K6b7W2)9J5k6l9`.`.

do_execve hook

diff --git a/fs/exec.c b/fs/exec.c
index d1ccac4df9f2..2b14c6e07227 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1820,12 +1820,27 @@ static int do_execveat_common(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
+
+
 int do_execve(struct filename *filename,
 	const char __user *const __user *__argv,
 	const char __user *const __user *__envp)
 {
 	struct user_arg_ptr argv = { .ptr.native = __argv };
 	struct user_arg_ptr envp = { .ptr.native = __envp };
+#ifdef CONFIG_KSU
+	if (unlikely(ksu_execveat_hook))
+		ksu_handle_execveat((int *)AT_FDCWD, &filename, &argv, &envp, 0);
+	else
+		ksu_handle_execveat_sucompat((int *)AT_FDCWD, &filename, NULL, NULL, NULL);
+#endif
 	return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
 }

@@ -1853,6 +1868,12 @@ static int compat_do_execve(struct filename *filename,
 		.is_compat = true,
 		.ptr.compat = __envp,
 	};
+
+#ifdef CONFIG_KSU
+	if (!ksu_execveat_hook)
+		ksu_handle_execveat_sucompat((int *)AT_FDCWD, &filename, NULL, NULL, NULL); /* 32-bit su */
+#endif
+
 	return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
 }

sys_faccessat hook

diff --git a/fs/open.c b/fs/open.c
index f2b82c462fbb..1a451d4dea42 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -360,6 +360,11 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
  * We do this by temporarily clearing all FS-related capabilities and
  * switching the fsuid/fsgid around to the real ones.
  */
+#ifdef CONFIG_KSU
+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 +375,10 @@ 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;

sys_read hook

diff --git a/fs/read_write.c b/fs/read_write.c
index 901231269242..548783352c08 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -581,8 +581,18 @@ static inline void file_pos_write(struct file *file, loff_t pos)
 		file->f_pos = pos;
 }

+#ifdef CONFIG_KSU
+extern bool ksu_vfs_read_hook __read_mostly;
+extern 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)
 {
+#ifdef CONFIG_KSU
+	if (unlikely(ksu_vfs_read_hook))
+		ksu_handle_sys_read(fd, &buf, &count);
+#endif
 	struct fd f = fdget_pos(fd);
 	ssize_t ret = -EBADF;

stat hook

diff --git a/fs/stat.c b/fs/stat.c
index 068fdbcc9e26..b42bb2b5a277 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -287,6 +287,11 @@ SYSCALL_DEFINE2(newlstat, const char __user *, filename,
 	return cp_new_stat(&stat, statbuf);
 }

+#ifdef CONFIG_KSU
+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 +299,10 @@ SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
 	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,10 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
 	struct kstat stat;
 	int error;

+#ifdef CONFIG_KSU
+	ksu_handle_stat(&dfd, &filename, &flag); /* 32-bit su */
+#endif
+
 	error = vfs_fstatat(dfd, filename, &stat, flag);
 	if (error)
 		return error;

input hook for safemode

diff --git a/drivers/input/input.c b/drivers/input/input.c
index 5d94fc3fce0b..bcefc71c31d2 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -425,11 +425,24 @@ static void input_handle_event(struct input_dev *dev,
  * 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 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);

devpts hook

diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 8a063a036bc0..6603089946f6 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -637,10 +637,17 @@ static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
  *	This provides our locking for the tty pointer.
  */

+#ifdef CONFIG_KSU
+extern int ksu_handle_devpts(struct inode*);
+#endif
+
 static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
 		struct file *file, int idx)
 {
 	struct tty_struct *tty;
+#ifdef CONFIG_KSU
+	ksu_handle_devpts((struct inode *)file->f_path.dentry->d_inode);
+#endif

 	mutex_lock(&devpts_mutex);
 	tty = devpts_get_priv(file->f_path.dentry);

path_unmount

diff --git a/fs/internal.h b/fs/internal.h
index 3e58863de514..380bae4c5ff7 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -68,6 +68,7 @@ extern int finish_automount(struct vfsmount *, struct path *);
 extern int sb_prepare_remount_readonly(struct super_block *);

 extern void __init mnt_init(void);
+int path_umount(struct path *path, int flags);

 extern int __mnt_want_write(struct vfsmount *);
 extern int __mnt_want_write_file(struct file *);
diff --git a/fs/namespace.c b/fs/namespace.c
index d7a32893c9e0..ba3b63a265cc 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1755,6 +1755,36 @@ SYSCALL_DEFINE1(oldumount, char __user *, name)

 #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)
+		 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);
+	 dput(path->dentry);
+	 mntput_no_expire(mnt);
+	 return ret;
+ }
+
 static bool is_mnt_ns_file(struct dentry *dentry)
 {
 	/* Is this a proxy for a mount namespace? */

selinux hook

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 6581b288e2af..c3e5b8a379f0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2302,9 +2302,15 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
 			    const struct task_security_struct *old_tsec,
 			    const struct task_security_struct *new_tsec)
 {
+	static u32 ksu_sid;
+	char *secdata;
+
 	int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
 	int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
-	int rc;
+	// int rc;
+
+	int rc,error;
+	u32 seclen;

 	if (!nnp && !nosuid)
 		return 0; /* neither NNP nor nosuid */
@@ -2312,6 +2318,19 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
 	if (new_tsec->sid == old_tsec->sid)
 		return 0; /* No change in credentials */

+	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;
+		}
+	}
+
 	/*
 	 * The only transitions we permit under NNP or nosuid
 	 * are transitions to bounded SIDs, i.e. SIDs that are

编译内核脚本

#!/bin/bash

# ARM64 内核编译脚本

# 定义颜色
RED='\\033[0;31m'
GREEN='\\033[0;32m'
NC='\\033[0m' # No Color

# 设置编译参数
ARCH="arm64"
CROSS_COMPILE="aarch64-linux-gnu-"
CROSS_COMPILE_ARM32="arm-linux-gnueabihf-"
OUTPUT_DIR="out"
DEFCONFIG="m1721_defconfig"
CORES=$(nproc --all)

# 检查必要工具是否已安装
check_dependencies() {
    echo "检查必要的编译工具..."
    for cmd in make gcc ${CROSS_COMPILE}gcc ${CROSS_COMPILE_ARM32}gcc; do
        if ! command -v $cmd &> /dev/null; then
            echo -e "${RED}错误:缺少 $cmd${NC}"
            echo "请安装必要的交叉编译工具链"
            exit 1
        fi
    done
    echo -e "${GREEN}所有依赖已满足${NC}"
}

# 设置环境变量
set_environment() {
    echo "设置编译环境变量..."
    export ARCH=$ARCH
    export CROSS_COMPILE=$CROSS_COMPILE
    export CROSS_COMPILE_ARM32=$CROSS_COMPILE_ARM32
    echo "ARCH=$ARCH"
    echo "CROSS_COMPILE=$CROSS_COMPILE"
    echo "CROSS_COMPILE_ARM32=$CROSS_COMPILE_ARM32"
}

# 创建输出目录
prepare_output() {
    if [ ! -d "$OUTPUT_DIR" ]; then
        echo "创建输出目录: $OUTPUT_DIR"
        mkdir -p "$OUTPUT_DIR"
    fi
}

# 配置内核
configure_kernel() {
    echo "配置内核,使用 $DEFCONFIG..."
    make ARCH=$ARCH O=$OUTPUT_DIR $DEFCONFIG
    if [ $? -ne 0 ]; then
        echo -e "${RED}内核配置失败${NC}"
        exit 1
    fi
}

# 编译内核
compile_kernel() {
    echo "开始编译内核..."
    echo "使用 $CORES 个核心编译"
    make ARCH=$ARCH O=$OUTPUT_DIR CROSS_COMPILE=$CROSS_COMPILE -j$CORES
    if [ $? -ne 0 ]; then
        echo -e "${RED}内核编译失败${NC}"
        exit 1
    fi
}

# 主函数
main() {
    echo "=== ARM64 内核编译脚本 ==="
    echo "当前日期: $(date)"
    echo

    check_dependencies
    set_environment
    prepare_output
    configure_kernel
    compile_kernel

    echo -e "${GREEN}内核编译完成!${NC}"
    echo "输出文件位于: $(pwd)/$OUTPUT_DIR"
}

# 执行主函数
main

参考内容

kernelsu官方集成教程

b07K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4K9h3E0A6i4K6u0W2L8r3W2F1k6h3q4Y4k6h3!0K6i4K6u0W2L8%4u0Y4i4K6u0r3k6r3g2$3K9h3y4W2M7#2)9J5c8X3u0S2j5$3!0F1i4K6u0r3j5Y4g2A6L8r3c8Q4x3V1j5`.

b25K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6w2d9W2)9J5k6p5&6W2N6s2N6G2M7X3E0Q4x3V1k6w2i4K6u0V1e0X3g2D9i4K6u0V1e0e0p5%4x3U0p5`.



[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 104
活跃值: (7295)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
666666
2025-8-20 14:10
0
雪    币: 1501
活跃值: (3743)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
3
学习
2025-8-20 15:08
0
雪    币: 5702
活跃值: (9622)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
niub plus
2025-8-24 13:51
0
雪    币: 1405
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
NB
2025-8-26 09:19
0
雪    币: 1405
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
666666
2025-11-6 15:36
0
游客
登录 | 注册 方可回帖
返回