11# Integrate for non-GKI devices
22
3- KernelSU Next can be integrated into non-GKI kernels and was backported to 5.4 and earlier versions.
3+ KernelSU Next can be integrated into non-GKI kernels and was backported to 4.14 and earlier versions.
44
55Due to the fragmentation of non-GKI kernels, we don't have a universal way to build them; therefore, we cannot provide a non-GKI boot.img. However, you can build the kernel with KernelSU Next integrated on your own.
66
@@ -42,7 +42,7 @@ Comment out `ksu_sucompat_init()` and `ksu_ksud_init()` in `KernelSU/kernel/ksu.
4242
4343## Manually modify the kernel source
4444
45- If kprobe doesn't work on your kernel—either because of an upstream bug or because your kernel is older than 5.4 you can try the following approach:
45+ If kprobe doesn't work on your kernel—either because of an upstream bug or because your kernel is older than 4.14 you can try the following approach:
4646
4747First, add KernelSU Next to your kernel source tree:
4848
@@ -65,36 +65,39 @@ Next, add KernelSU Next calls to the kernel source. Below are some patches for r
6565diff --git a/fs/exec.c b/fs/exec.c
6666--- a/fs/exec.c
6767+++ b/fs/exec.c
68- --- a/fs/exec.c
69- +++ b/fs/exec.c
70- /*
71- * sys_execve() executes a new program.
72- */
68+ @@ -1886,12 +1886,26 @@ static int do_execveat_common(int fd, struct filename *filename,
69+ return retval;
70+ }
71+
7372+#ifdef CONFIG_KSU
7473+__attribute__((hot))
75- +extern int ksu_handle_execveat(int *fd,
76- + struct filename **filename_ptr,
77- + void *argv, void *envp, int *flags);
74+ +extern int ksu_handle_execveat(int *fd, struct filename **filename_ptr,
75+ + void *argv, void *envp, int *flags);
7876+#endif
7977+
80- static int do_execve_common(struct filename *filename,
81- struct user_arg_ptr argv,
82- struct user_arg_ptr envp)
83- {
84- struct linux_binprm *bprm;
85- struct file *file;
86- struct files_struct *displaced;
87- int retval;
88-
89- if (IS_ERR(filename))
90- return PTR_ERR(filename);
91-
78+ int do_execve(struct filename *filename,
79+ const char __user *const __user *__argv,
80+ const char __user *const __user *__envp)
81+ {
82+ struct user_arg_ptr argv = { .ptr.native = __argv };
83+ struct user_arg_ptr envp = { .ptr.native = __envp };
9284+#ifdef CONFIG_KSU
9385+ ksu_handle_execveat((int *)AT_FDCWD, &filename, &argv, &envp, 0);
9486+#endif
95- /*
96- * We move the actual failure in case of RLIMIT_NPROC excess from
97- * set*uid() to execve() because too many poorly written programs
87+ return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
88+ }
89+
90+ @@ -1919,6 +1933,10 @@
91+ static int compat_do_execve(struct filename *filename,
92+ .is_compat = true,
93+ .ptr.compat = __envp,
94+ };
95+ +#ifdef CONFIG_KSU // 32-bit ksud and 32-on-64 support
96+ + ksu_handle_execveat((int *)AT_FDCWD, &filename, &argv, &envp, 0);
97+ +#endif
98+ return do_execveat_common(AT_FDCWD, filename, argv, envp, 0);
99+ }
100+
98101```
99102``` diff[open.c]
100103diff --git a/fs/open.c b/fs/open.c
@@ -130,69 +133,60 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
130133``` diff[read_write.c]
131134--- a/fs/read_write.c
132135+++ b/fs/read_write.c
133- @@ -429,10 +429,19 @@ ssize_t kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
136+ @@ -568,11 +568,21 @@ static inline void file_pos_write(struct file *file, loff_t pos)
137+ file->f_pos = pos;
134138 }
135- EXPORT_SYMBOL(kernel_read);
136139
137140+#ifdef CONFIG_KSU
138141+extern bool ksu_vfs_read_hook __read_mostly;
139- +extern int ksu_handle_vfs_read(struct file **file_ptr, char __user **buf_ptr ,
140- + size_t *count_ptr, loff_t **pos );
142+ +extern __attribute__((cold)) int ksu_handle_sys_read(unsigned int fd ,
143+ + char __user **buf_ptr, size_t *count_ptr );
141144+#endif
142- ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
145+ +
146+ SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count)
143147 {
144- ssize_t ret;
148+ struct fd f = fdget_pos(fd);
149+ ssize_t ret = -EBADF;
145150
146- +#ifdef CONFIG_KSU
147- + if (unlikely(ksu_vfs_read_hook))
148- + ksu_handle_vfs_read(&file , &buf, &count, &pos );
151+ +#ifdef CONFIG_KSU
152+ + if (unlikely(ksu_vfs_read_hook))
153+ + ksu_handle_sys_read(fd , &buf, &count);
149154+#endif
150- if (!( file->f_mode & FMODE_READ))
151- return -EBADF ;
152- if (!( file->f_mode & FMODE_CAN_READ)))
155+ if (f. file) {
156+ loff_t pos = file_pos_read(f.file) ;
157+ ret = vfs_read(f. file, buf, count, &pos);
153158```
154159``` diff[stat.c]
155160diff --git a/fs/stat.c b/fs/stat.c
156161--- a/fs/stat.c
157162+++ b/fs/stat.c
158- @@ -364,X +364,XX @@
163+ @@ -353,6 +353,10 @@ SYSCALL_DEFINE2(newlstat, const char __user *, filename,
164+ return cp_new_stat(&stat, statbuf);
165+ }
166+
159167+#ifdef CONFIG_KSU
160- +extern void ksu_handle_newfstat_ret(unsigned int *fd, struct stat __user **statbuf_ptr);
161- +#if defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_COMPAT_STAT64)
162- +extern void ksu_handle_fstat64_ret(unsigned long *fd, struct stat64 __user **statbuf_ptr); // optional
163- +#endif
168+ +__attribute__((hot))
169+ +extern int ksu_handle_stat(int *dfd, const char __user **filename_user,
170+ + int *flags);
164171+#endif
165172+
166- SYSCALL_DEFINE2(newfstat, unsigned int, fd, struct stat __user *, statbuf)
167- {
168- struct kstat stat;
169- int error = vfs_fstat(fd, &stat);
170-
171- if (!error)
172- error = cp_new_stat(&stat, statbuf);
173173
174- +#ifdef CONFIG_KSU
175- + ksu_handle_newfstat_ret(&fd, &statbuf);
176- +#endif
177- return error;
178-
179-
180- @@ -490,X +497,X @@
181- SYSCALL_DEFINE2(fstat64, unsigned long, fd, struct stat64 __user *, statbuf)
174+ #if !defined(__ARCH_WANT_STAT64) || defined(__ARCH_WANT_SYS_NEWFSTATAT)
175+ SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename,
176+ struct stat __user *, statbuf, int, flag)
182177{
183178 struct kstat stat;
184- int error = vfs_fstat(fd, &stat);
185-
186- if (!error)
187- error = cp_new_stat64(&stat, statbuf);
179+ int error;
188180
189- +#ifdef CONFIG_KSU // for 32-bit
190- + ksu_handle_fstat64_ret(&fd , &statbuf );
181+ +#ifdef CONFIG_KSU
182+ + ksu_handle_stat(&dfd , &filename, &flag );
191183+#endif
192- return error;
193- }
184+ error = vfs_fstatat(dfd, filename, &stat, flag);
185+ if (error)
186+ return error;
194187```
195188``` diff[reboot.c]
189+ diff --git a/kernel/reboot.c b/kernel/reboot.c
196190--- a/kernel/reboot.c
197191+++ b/kernel/reboot.c
198192@@ -277,6 +277,11 @@
@@ -222,70 +216,11 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
222216
223217You should find the five functions in kernel source:
224218
225- 1 . ` do_faccessat ` , usually in ` fs/open .c `
226- 2 . ` do_execveat_common ` , usually in ` fs/exec .c `
219+ 1 . ` do_execve ` , usually in ` fs/exec .c `
220+ 2 . ` SYSCALL_DEFINE3 ` , usually in ` fs/open .c `
2272213 . ` vfs_read ` , usually in ` fs/read_write.c `
228- 4 . ` vfs_statx ` , usually in ` fs/stat.c `
229- 5 . ` sys_reboot ` , usually in ` kernel/reboot.c `
230-
231- If your kernel doesn't have the ` vfs_statx ` function, use ` vfs_fstatat ` instead:
232-
233- ``` diff
234- diff --git a/fs/stat.c b/fs/stat.c
235- index 068fdbcc9e26..5348b7bb9db2 100644
236- --- a/fs/stat.c
237- +++ b/fs/stat.c
238- @@ -87,6 +87,8 @@ int vfs_fstat(unsigned int fd, struct kstat *stat)
239- }
240- EXPORT_SYMBOL(vfs_fstat);
241-
242- + #ifdef CONFIG_KSU
243- + extern int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags);
244- + #endif
245- int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
246- int flag)
247- {
248- @@ -94,6 +96,8 @@ int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat,
249- int error = -EINVAL;
250- unsigned int lookup_flags = 0;
251- + #ifdef CONFIG_KSU
252- + ksu_handle_stat(&dfd, &filename, &flag);
253- + #endif
254- +
255- if ((flag & ~(AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT |
256- AT_EMPTY_PATH)) != 0)
257- goto out;
258- ```
259-
260- 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:
261-
262- ``` diff
263- diff --git a/fs/open.c b/fs/open.c
264- index 2ff887661237..e758d7db7663 100644
265- --- a/fs/open.c
266- +++ b/fs/open.c
267- @@ -355,6 +355,9 @@ SYSCALL_DEFINE4(fallocate, int, fd, int, mode, loff_t, offset, loff_t, len)
268- return error;
269- }
270-
271- + #ifdef CONFIG_KSU
272- + extern int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
273- + int *flags);
274- + #endif
275- +
276- /*
277- * access() needs to use the real uid/gid, not the effective uid/gid.
278- * We do this by temporarily clearing all FS-related capabilities and
279- @@ -370,6 +373,8 @@ SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode)
280- int res;
281- unsigned int lookup_flags = LOOKUP_FOLLOW;
282- + #ifdef CONFIG_KSU
283- + ksu_handle_faccessat(&dfd, &filename, &mode, NULL);
284- + #endif
285- +
286- if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
287- return -EINVAL;
288- ```
222+ 4 . ` SYSCALL_DEFINE4 ` , usually in ` fs/stat.c `
223+ 5 . ` SYSCALL_DEFINE4 ` , usually in ` kernel/reboot.c `
289224
290225Finally, build your kernel again, and KernelSU Next should work correctly.
291226
0 commit comments