From 9d5c6ab3fd2414d33a61f90711ea516ec1a01346 Mon Sep 17 00:00:00 2001 From: TwinbornPlate75 <42514046+TwinbornPlate75@users.noreply.github.com> Date: Mon, 17 Nov 2025 20:10:06 +0800 Subject: [PATCH] kernel: Fix compilation for non-gki kernels (#593) --- kernel/allowlist.c | 5 +--- kernel/file_wrapper.c | 4 +-- kernel/kernel_compat.c | 54 ----------------------------------- kernel/kernel_compat.h | 30 +++++++------------ kernel/kernel_umount.c | 6 ++-- kernel/ksud.c | 9 +++--- kernel/setuid_hook.c | 9 +++--- kernel/sucompat.c | 10 +++---- kernel/supercalls.c | 5 ++-- kernel/syscall_hook_manager.c | 4 ++- 10 files changed, 36 insertions(+), 100 deletions(-) diff --git a/kernel/allowlist.c b/kernel/allowlist.c index 4c2e7e24..ef49bfca 100644 --- a/kernel/allowlist.c +++ b/kernel/allowlist.c @@ -19,6 +19,7 @@ #include "klog.h" // IWYU pragma: keep #include "ksud.h" +#include "kernel_compat.h" #include "selinux/selinux.h" #include "allowlist.h" #include "manager.h" @@ -431,11 +432,7 @@ void persistent_allow_list() goto put_task; } cb->func = do_persistent_allow_list; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 7, 0) task_work_add(tsk, cb, TWA_RESUME); -#else - task_work_add(tsk, cb, true); -#endif put_task: put_task_struct(tsk); diff --git a/kernel/file_wrapper.c b/kernel/file_wrapper.c index 5931b682..66546b94 100644 --- a/kernel/file_wrapper.c +++ b/kernel/file_wrapper.c @@ -279,7 +279,7 @@ static int ksu_wrapper_fadvise(struct file *fp, loff_t off1, loff_t off2, int fl static int ksu_wrapper_clone_file_range(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, u64 len) { // TODO: determine which file to use - struct ksu_file_proxy* data = file_in->private_data; + struct ksu_file_wrapper* data = file_in->private_data; struct file* orig = data->orig; if (orig->f_op->clone_file_range) { return orig->f_op->clone_file_range(orig, pos_in, file_out, pos_out, len); @@ -290,7 +290,7 @@ static int ksu_wrapper_clone_file_range(struct file *file_in, loff_t pos_in, static ssize_t ksu_wrapper_dedupe_file_range(struct file *src_file, u64 loff, u64 len, struct file *dst_file, u64 dst_loff) { // TODO: determine which file to use - struct ksu_file_proxy* data = src_file->private_data; + struct ksu_file_wrapper* data = src_file->private_data; struct file* orig = data->orig; if (orig->f_op->dedupe_file_range) { return orig->f_op->dedupe_file_range(orig, loff, len, dst_file, dst_loff); diff --git a/kernel/kernel_compat.c b/kernel/kernel_compat.c index 00df8d67..85bac87c 100644 --- a/kernel/kernel_compat.c +++ b/kernel/kernel_compat.c @@ -78,57 +78,3 @@ long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, return ret; } #endif - -long ksu_strncpy_from_user_retry(char *dst, const void __user *unsafe_addr, - long count) -{ - long ret; - - ret = ksu_strncpy_from_user_nofault(dst, unsafe_addr, count); - if (likely(ret >= 0)) - return ret; - - // we faulted! fallback to slow path - if (unlikely(!ksu_access_ok(unsafe_addr, count))) { -#ifdef CONFIG_KSU_DEBUG - pr_err("%s: faulted!\n", __func__); -#endif - return -EFAULT; - } - - // why we don't do like how strncpy_from_user_nofault? - ret = strncpy_from_user(dst, unsafe_addr, count); - - if (ret >= count) { - ret = count; - dst[ret - 1] = '\0'; - } else if (likely(ret >= 0)) { - ret++; - } - - return ret; -} - -long ksu_copy_from_user_nofault(void *dst, const void __user *src, size_t size) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0) - return copy_from_user_nofault(dst, src, size); -#else - // https://elixir.bootlin.com/linux/v5.8/source/mm/maccess.c#L205 - long ret = -EFAULT; - mm_segment_t old_fs = get_fs(); - - set_fs(USER_DS); - // tweaked to use ksu_access_ok - if (ksu_access_ok(src, size)) { - pagefault_disable(); - ret = __copy_from_user_inatomic(dst, src, size); - pagefault_enable(); - } - set_fs(old_fs); - - if (ret) - return -EFAULT; - return 0; -#endif -} diff --git a/kernel/kernel_compat.h b/kernel/kernel_compat.h index 3f5e48ff..0b65a7b0 100644 --- a/kernel/kernel_compat.h +++ b/kernel/kernel_compat.h @@ -15,32 +15,12 @@ extern long ksu_strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr, long count); -extern long ksu_strncpy_from_user_retry(char *dst, - const void __user *unsafe_addr, - long count); #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || \ defined(CONFIG_IS_HW_HISI) || \ defined(CONFIG_KSU_ALLOWLIST_WORKAROUND) extern struct key *init_session_keyring; #endif -/* - * ksu_copy_from_user_retry - * try nofault copy first, if it fails, try with plain - * paramters are the same as copy_from_user - * 0 = success - */ -extern long ksu_copy_from_user_nofault(void *dst, const void __user *src, size_t size); -static long ksu_copy_from_user_retry(void *to, - const void __user *from, unsigned long count) -{ - long ret = ksu_copy_from_user_nofault(to, from, count); - if (likely(!ret)) - return ret; - - // we faulted! fallback to slow path - return copy_from_user(to, from, count); -} #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) #define ksu_access_ok(addr, size) access_ok(addr, size) @@ -48,4 +28,14 @@ static long ksu_copy_from_user_retry(void *to, #define ksu_access_ok(addr, size) access_ok(VERIFY_READ, addr, size) #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 7, 0) +#define TWA_RESUME true +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) +#define ksu_force_sig(sig) force_sig(sig); +#else +#define ksu_force_sig(sig) force_sig(sig, current); +#endif + #endif diff --git a/kernel/kernel_umount.c b/kernel/kernel_umount.c index 7bcac827..be58b5f4 100644 --- a/kernel/kernel_umount.c +++ b/kernel/kernel_umount.c @@ -10,10 +10,12 @@ #include #include #include +#include #include "manager.h" #include "kernel_umount.h" #include "klog.h" // IWYU pragma: keep +#include "kernel_compat.h" #include "allowlist.h" #include "selinux/selinux.h" #include "feature.h" @@ -245,11 +247,7 @@ int ksu_handle_umount(uid_t old_uid, uid_t new_uid) tw->old_cred = get_current_cred(); tw->cb.func = umount_tw_func; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) int err = task_work_add(current, &tw->cb, TWA_RESUME); -#else - int err = task_work_add(current, &tw->cb, true); -#endif if (err) { if (tw->old_cred) { put_cred(tw->old_cred); diff --git a/kernel/ksud.c b/kernel/ksud.c index ba07ea4e..f494e7fe 100644 --- a/kernel/ksud.c +++ b/kernel/ksud.c @@ -32,6 +32,7 @@ #include "arch.h" #include "klog.h" // IWYU pragma: keep #include "ksud.h" +#include "kernel_compat.h" #include "selinux/selinux.h" #include "throne_tracker.h" @@ -254,7 +255,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr, const char __user *p = get_user_arg_ptr(*argv, 1); if (p && !IS_ERR(p)) { char first_arg[16]; - strncpy_from_user_nofault(first_arg, p, sizeof(first_arg)); + ksu_strncpy_from_user_nofault(first_arg, p, sizeof(first_arg)); pr_info("/system/bin/init first arg: %s\n", first_arg); if (!strcmp(first_arg, "second_stage")) { pr_info("/system/bin/init second_stage executed\n"); @@ -276,7 +277,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr, const char __user *p = get_user_arg_ptr(*argv, 1); if (p && !IS_ERR(p)) { char first_arg[16]; - strncpy_from_user_nofault(first_arg, p, sizeof(first_arg)); + ksu_strncpy_from_user_nofault(first_arg, p, sizeof(first_arg)); pr_info("/init first arg: %s\n", first_arg); if (!strcmp(first_arg, "--second-stage")) { pr_info("/init second_stage executed\n"); @@ -298,7 +299,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr, } char env[256]; // Reading environment variable strings from user space - if (strncpy_from_user_nofault(env, p, sizeof(env)) < 0) + if (ksu_strncpy_from_user_nofault(env, p, sizeof(env)) < 0) continue; // Parsing environment variable names and values char *env_name = env; @@ -543,7 +544,7 @@ static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs) return 0; memset(path, 0, sizeof(path)); - strncpy_from_user_nofault(path, *filename_user, 32); + ksu_strncpy_from_user_nofault(path, *filename_user, 32); filename_in.name = path; filename_p = &filename_in; diff --git a/kernel/setuid_hook.c b/kernel/setuid_hook.c index ecdc3736..1eb1a76f 100644 --- a/kernel/setuid_hook.c +++ b/kernel/setuid_hook.c @@ -52,6 +52,7 @@ #include "setuid_hook.h" #include "feature.h" #include "klog.h" // IWYU pragma: keep +#include "kernel_compat.h" #include "ksu.h" #include "manager.h" #include "selinux/selinux.h" @@ -147,7 +148,7 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid) if (!is_ksu_domain()) { pr_warn("find suspicious EoP: %d %s, from %d to %d\n", current->pid, current->comm, old_uid, new_uid); - force_sig(SIGKILL); + ksu_force_sig(SIGKILL); return 0; } } @@ -156,7 +157,7 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid) if (euid < current_euid().val && !ksu_is_allow_uid_for_current(old_uid)) { pr_warn("find suspicious EoP: %d %s, from %d to %d\n", current->pid, current->comm, old_uid, new_uid); - force_sig(SIGKILL); + ksu_force_sig(SIGKILL); return 0; } } @@ -227,7 +228,7 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid){ if (!is_ksu_domain()) { pr_warn("find suspicious EoP: %d %s, from %d to %d\n", current->pid, current->comm, old_uid, new_uid); - force_sig(SIGKILL); + ksu_force_sig(SIGKILL); return 0; } } @@ -236,7 +237,7 @@ int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid){ if (euid < current_euid().val && !ksu_is_allow_uid_for_current(old_uid)) { pr_warn("find suspicious EoP: %d %s, from %d to %d\n", current->pid, current->comm, old_uid, new_uid); - force_sig(SIGKILL); + ksu_force_sig(SIGKILL); return 0; } } diff --git a/kernel/sucompat.c b/kernel/sucompat.c index 595217c2..696e2343 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -97,7 +97,7 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, char path[sizeof(su) + 1]; memset(path, 0, sizeof(path)); - strncpy_from_user_nofault(path, *filename_user, sizeof(path)); + ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); if (unlikely(!memcmp(path, su, sizeof(su)))) { #if __SULOG_GATE @@ -144,7 +144,7 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags) pr_info("vfs_statx su->sh!\n"); memcpy((void *)filename->name, sh, sizeof(sh)); #else - strncpy_from_user_nofault(path, *filename_user, sizeof(path)); + ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); if (unlikely(!memcmp(path, su, sizeof(su)))) { #if __SULOG_GATE @@ -174,7 +174,7 @@ int ksu_handle_execve_sucompat(const char __user **filename_user, return 0; memset(path, 0, sizeof(path)); - strncpy_from_user_nofault(path, *filename_user, sizeof(path)); + ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); if (likely(memcmp(path, su, sizeof(su)))) return 0; @@ -260,7 +260,7 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, return 0; } - strncpy_from_user_nofault(path, *filename_user, sizeof(path)); + ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); if (unlikely(!memcmp(path, su_path, sizeof(su_path)))) { #if __SULOG_GATE @@ -316,7 +316,7 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags) pr_info("ksu_handle_stat: su->sh!\n"); memcpy((void *)filename->name, sh_path, sizeof(sh_path)); #else - strncpy_from_user_nofault(path, *filename_user, sizeof(path)); + ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); if (unlikely(!memcmp(path, su_path, sizeof(su_path)))) { #if __SULOG_GATE diff --git a/kernel/supercalls.c b/kernel/supercalls.c index bc867c44..32b48d04 100644 --- a/kernel/supercalls.c +++ b/kernel/supercalls.c @@ -19,6 +19,7 @@ #include "feature.h" #include "klog.h" // IWYU pragma: keep #include "ksud.h" +#include "kernel_compat.h" #include "manager.h" #include "sulog.h" #include "selinux/selinux.h" @@ -812,10 +813,10 @@ static void ksu_install_fd_tw_func(struct callback_head *cb) if (copy_to_user(tw->outp, &fd, sizeof(fd))) { pr_err("install ksu fd reply err\n"); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 11, 0) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0) close_fd(fd); #else - ksys_close(fd); + __close_fd(current->files, fd); #endif } diff --git a/kernel/syscall_hook_manager.c b/kernel/syscall_hook_manager.c index 5fdf9608..c0c63fa0 100644 --- a/kernel/syscall_hook_manager.c +++ b/kernel/syscall_hook_manager.c @@ -235,7 +235,9 @@ static inline bool check_syscall_fastpath(int nr) case __NR_execve: case __NR_setresuid: case __NR_clone: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 2, 0) case __NR_clone3: +#endif return true; default: return false; @@ -251,7 +253,7 @@ int ksu_handle_init_mark_tracker(const char __user **filename_user) return 0; memset(path, 0, sizeof(path)); - strncpy_from_user_nofault(path, *filename_user, sizeof(path)); + ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); if (likely(strstr(path, "/app_process") == NULL && strstr(path, "/adbd") == NULL && strstr(path, "/ksud") == NULL)) { pr_info("hook_manager: unmark %d exec %s", current->pid, path);