From 8c2d2ae91fdff4c0fc366d141e0a2f12f2248fa8 Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 8 Apr 2024 19:42:44 +0800 Subject: [PATCH 01/71] sucompat: change to inlinehook, skip calculate sizeof pt_regs --- kernel/base/predata.c | 1 + kernel/include/preset.h | 9 ++ kernel/patch/android/sucompat.c | 201 ++++++++++++++++++++++++++++++++ kernel/patch/common/syscall.c | 2 +- kernel/patch/common/utils.c | 2 +- kernel/patch/patch.c | 4 +- tools/symbol.c | 21 ++++ version | 2 +- 8 files changed, 237 insertions(+), 5 deletions(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 6f1d8daa..0950039e 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -52,6 +52,7 @@ void reset_superkey(const char *key) { lib_strncpy(superkey, key, SUPER_KEY_LEN - 1); superkey[SUPER_KEY_LEN - 1] = '\0'; + dsb(ish); } void enable_auth_root_key(int enable) diff --git a/kernel/include/preset.h b/kernel/include/preset.h index 1970d33e..af5921f9 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -117,6 +117,15 @@ struct patch_symbol uint64_t __cfi_slowpath; uint64_t copy_process; uint64_t cgroup_post_fork; + uint64_t do_execveat_common; + uint64_t __do_execve_file; + uint64_t do_execve_common; + uint64_t do_faccessat; + uint64_t sys_faccessat; + uint64_t sys_faccessat2; + uint64_t sys_newfstatat; + uint64_t vfs_statx; + uint64_t vfs_fstatat; uint64_t avc_denied; uint64_t slow_avc_audit; uint64_t input_handle_event; diff --git a/kernel/patch/android/sucompat.c b/kernel/patch/android/sucompat.c index 36eba046..16c5637a 100644 --- a/kernel/patch/android/sucompat.c +++ b/kernel/patch/android/sucompat.c @@ -250,8 +250,159 @@ static uid_t current_uid() return uid; } +// #define SU_COMPAT_HOOK_SYSCALL // #define TRY_DIRECT_MODIFY_USER +#ifndef SU_COMPAT_HOOK_SYSCALL + +// int do_execveat_common(int fd, struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp, int flags) +// int __do_execve_file(int fd, struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp, int flags, +// struct file *file); +// static int do_execve_common(struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp) +static void before_do_execve(hook_fargs8_t *args, void *udata) +{ + struct filename *filename; + int filename_index = 1; + + if (udata && (((uintptr_t)args->arg0) & 0xF000000000000000) == 0xF000000000000000) { + // int, AT_FDCWD(ffffff9c) or fd + filename_index = 0; + } + + filename = (struct filename *)args->args[filename_index]; + if (!filename || IS_ERR(filename)) return; + + if (!strcmp(current_su_path, filename->name)) { + uid_t uid = current_uid(); + if (!is_su_allow_uid(uid)) return; + struct su_profile profile = profile_su_allow_uid(uid); + + uid_t to_uid = profile.to_uid; + const char *sctx = profile.scontext; + commit_su(to_uid, sctx); + + struct file *filp = filp_open(apd_path, O_RDONLY, 0); + if (!filp || IS_ERR(filp)) { + logkfi("call su uid: %d, to_uid: %d, sctx: %s\n", uid, to_uid, sctx); + strcpy((char *)filename->name, sh_path); + } else { + filp_close(filp, 0); + strcpy((char *)filename->name, apd_path); + int cplen = 0; + if (strcmp(legacy_su_path, filename->name)) { + const char *__user p0 = + get_user_arg_ptr((void *)args->args[filename_index + 1], (void *)args->args[filename_index + 2], 0); + cplen = compat_copy_to_user((char *__user)p0, legacy_su_path, sizeof(legacy_su_path)); + } + logkfi("call apd uid: %d, to_uid: %d, sctx: %s, cplen: %d\n", uid, to_uid, sctx, cplen); + } + } else if (!strcmp(SUPERCMD, filename->name)) { + void *ua0 = (void *)args->args[filename_index + 1]; + void *ua1 = (void *)args->args[filename_index + 2]; + + // key + const char __user *p1 = get_user_arg_ptr(ua0, ua1, 1); + if (IS_ERR(p1)) return; + + // auth skey + char arg1[SUPER_KEY_LEN]; + arg1[0] = '\0'; + if (compat_strncpy_from_user(arg1, p1, sizeof(arg1)) <= 0) return; + if (auth_superkey(arg1)) return; + + commit_su(0, 0); + + // real command +#define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(*filename) - 128) // enough + + const char __user *p2 = get_user_arg_ptr(ua0, ua1, 2); + if (!p2 || IS_ERR(p2)) { + strcpy((char *)filename->name, sh_path); + } else { + compat_strncpy_from_user((char *)filename->name, p2, EMBEDDED_NAME_MAX); + } + logkfi("supercmd %s\n", filename->name); + + // shift args + args->args[filename_index + (has_config_compat ? 2 : 1)] += 2 * ((has_config_compat && ua0) ? 4 : 8); + } + return; +} + +// static long do_faccessat(int dfd, const char __user *filename, int mode, int flags) +// SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) +// SYSCALL_DEFINE4(faccessat2, int, dfd, const char __user *, filename, int, mode, int, flags) +static void before_faccessat(hook_fargs4_t *args, void *udata) +{ + uid_t uid = current_uid(); + if (!is_su_allow_uid(uid)) return; + + char __user *filename = (char __user *)args->arg1; + + int is_syscall = (uint64_t)udata; + if (is_syscall) filename = (char __user *)syscall_argn(args, 1); + + char buf[SU_PATH_MAX_LEN]; + buf[0] = '\0'; + compat_strncpy_from_user(buf, filename, sizeof(buf)); + if (strcmp(current_su_path, buf)) return; + + logkfd("uid: %d\n", uid); + args->ret = 0; + args->skip_origin = 1; +} + +// SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename, struct stat __user *, statbuf, int, flag) +static void before_sysfstatat(hook_fargs4_t *args, void *udata) +{ + uid_t uid = current_uid(); + if (!is_su_allow_uid(uid)) return; + + char *__user filename = (char *__user)syscall_argn(args, 1); + + char buf[SU_PATH_MAX_LEN]; + buf[0] = '\0'; + compat_strncpy_from_user(buf, filename, sizeof(buf)); + if (!strcmp(current_su_path, buf)) { + void *__user uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); + if (uptr && !IS_ERR(uptr)) set_syscall_argn(args, 1, (uint64_t)uptr); + logkfd("uid: %d, %llx\n", uid, uptr); + } + return; +} + +// int vfs_statx(int dfd, struct filename *filename, int flags, struct kstat *stat, u32 request_mask) +// int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, int flags) +// int vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat, u32 request_mask) +static void before_stat(hook_fargs8_t *args, void *udata) +{ + uid_t uid = current_uid(); + if (!is_su_allow_uid(uid)) return; + + if ((args->arg1 & 0xF000000000000000) == 0xF000000000000000) { + struct filename *filename = (struct filename *)args->arg1; + if (IS_ERR(filename)) return; + if (!strcmp(current_su_path, filename->name)) { + logkfd("0 uid: %d\n", uid); + strcpy((char *)filename->name, sh_path); + return; + } + } else { + char __user *filename = (char __user *)args->arg1; + char buf[SU_PATH_MAX_LEN]; + buf[0] = '\0'; + compat_strncpy_from_user(buf, filename, sizeof(buf)); + if (!strcmp(current_su_path, buf)) { + void *__user uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); + args->arg1 = (uint64_t)uptr; + logkfd("1 uid: %d, %llx\n", uid, uptr); + } + return; + } +} + +#else // SU_COMPAT_HOOK_SYSCALL + static void handle_before_execve(hook_local_t *hook_local, char **__user u_filename_p, char **__user uargv, void *udata) { // copy to user len @@ -481,6 +632,8 @@ static void su_handler_arg1_ufilename_after(hook_fargs6_t *args, void *udata) #define su_handler_arg1_ufilename_after 0 #endif +#endif // SU_COMPAT_HOOK_SYSCALL + int su_compat_init() { current_su_path = default_su_path; @@ -502,6 +655,52 @@ int su_compat_init() hook_err_t rc = HOOK_NO_ERR; +#ifndef SU_COMPAT_HOOK_SYSCALL + + struct patch_symbol *symbol = get_preset_patch_sym(); + + if (symbol->do_execveat_common) { // [5.9.0, ) or [3.19, 4.19] + rc = hook_wrap8((void *)symbol->do_execveat_common, (void *)before_do_execve, 0, 0); + log_boot("hook do_execveat_common rc: %d\n", rc); + } else if (symbol->__do_execve_file) { // [4.19, 5.9) + rc = hook_wrap8((void *)symbol->__do_execve_file, (void *)before_do_execve, 0, 0); + log_boot("hook __do_execve_file rc: %d\n", rc); + } else if (symbol->do_execve_common) { // (, 3.19) + rc = hook_wrap8((void *)symbol->do_execve_common, (void *)before_do_execve, 0, (void *)1); + log_boot("hook do_execve_common rc: %d\n", rc); + } + + if (symbol->do_faccessat) { + rc = hook_wrap4((void *)symbol->do_faccessat, (void *)before_faccessat, 0, 0); + log_boot("hook do_faccessat rc: %d\n", rc); + } else { + if (symbol->sys_faccessat) { + rc = hook_wrap4((void *)symbol->sys_faccessat, (void *)before_faccessat, 0, (void *)1); + log_boot("hook sys_faccessat rc: %d\n", rc); + } + if (symbol->sys_faccessat2) { + rc = hook_wrap4((void *)symbol->sys_faccessat2, (void *)before_faccessat, 0, (void *)1); + log_boot("hook sys_faccessat2 rc: %d\n", rc); + } + } + + if (symbol->sys_newfstatat) { + rc = hook_wrap4((void *)symbol->sys_newfstatat, (void *)before_sysfstatat, 0, (void *)1); + log_boot("hook sys_newfstatat rc: %d\n", rc); + } else { // never reach + if (symbol->vfs_statx) { + rc = hook_wrap8((void *)symbol->vfs_statx, (void *)before_stat, 0, (void *)0); + log_boot("hook vfs_statx rc: %d\n", rc); + } + + if (symbol->vfs_fstatat) { + rc = hook_wrap8((void *)symbol->vfs_fstatat, (void *)before_stat, 0, (void *)0); + log_boot("hook vfs_fstatat rc: %d\n", rc); + } + } + +#else + rc = fp_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)__NR_execve); log_boot("hook __NR_execve rc: %d\n", rc); @@ -520,5 +719,7 @@ int su_compat_init() (void *)__NR_faccessat2); log_boot("hook __NR_faccessat2 rc: %d\n", rc); +#endif + return rc; } \ No newline at end of file diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index 7388cb9e..5b3efa5f 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -46,7 +46,7 @@ struct user_arg_ptr_compat } ptr; }; -// actually, a0 is true if it is compact +// actually, a0 is true if it is compat const char __user *get_user_arg_ptr(void *a0, void *a1, int nr) { char __user *const __user *native = (char __user *const __user *)a0; diff --git a/kernel/patch/common/utils.c b/kernel/patch/common/utils.c index 6ae68dc3..33779e50 100644 --- a/kernel/patch/common/utils.c +++ b/kernel/patch/common/utils.c @@ -118,7 +118,7 @@ struct pt_regs *_task_pt_reg(struct task_struct *task) { unsigned long stack = (unsigned long)task_stack_page(task); uintptr_t addr = (uintptr_t)(thread_size + stack); - if (likely(pt_regs_offset > 0)) { + if (pt_regs_offset > 0) { addr -= pt_regs_offset; } else { #ifndef ANDROID diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 6681566b..77a9a009 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -80,8 +80,8 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) rc = supercall_install(); log_boot("supercall_install done: %d\n", rc); - rc = resolve_pt_regs(); - log_boot("resolve_pt_regs done: %d\n", rc); + // rc = resolve_pt_regs(); + // log_boot("resolve_pt_regs done: %d\n", rc); #ifdef ANDROID rc = su_compat_init(); diff --git a/tools/symbol.c b/tools/symbol.c index d3787b90..4513a9cc 100644 --- a/tools/symbol.c +++ b/tools/symbol.c @@ -120,6 +120,27 @@ int fillin_patch_symbol(kallsym_t *kallsym, char *img_buf, int imglen, patch_sym if (!symbol->copy_process) symbol->cgroup_post_fork = get_symbol_offset_zero(kallsym, img_buf, "cgroup_post_fork"); if (!symbol->copy_process && !symbol->cgroup_post_fork) tools_loge_exit("no symbol copy_process"); + symbol->do_execveat_common = try_get_symbol_offset_zero(kallsym, img_buf, "do_execveat_common"); + symbol->__do_execve_file = try_get_symbol_offset_zero(kallsym, img_buf, "__do_execve_file"); + symbol->do_execve_common = try_get_symbol_offset_zero(kallsym, img_buf, "do_execve_common"); + if (!symbol->do_execveat_common && !symbol->__do_execve_file && !symbol->do_execve_common) + tools_loge_exit("no symbol do_execveat_common, __do_execve_file and do_execve_common"); + + symbol->do_faccessat = try_get_symbol_offset_zero(kallsym, img_buf, "do_faccessat"); + symbol->sys_faccessat = get_symbol_offset_zero(kallsym, img_buf, "__arm64_sys_faccessat"); + if (!symbol->sys_faccessat) symbol->sys_faccessat = get_symbol_offset_zero(kallsym, img_buf, "sys_faccessat"); + symbol->sys_faccessat2 = get_symbol_offset_zero(kallsym, img_buf, "__arm64_sys_faccessat2"); + if (!symbol->sys_faccessat2) symbol->sys_faccessat2 = get_symbol_offset_zero(kallsym, img_buf, "sys_faccessat2"); + if (!symbol->do_faccessat && !symbol->sys_faccessat && !symbol->sys_faccessat) + tools_loge_exit("no symbol do_faccessat, sys_faccessat and sys_faccessat2"); + + symbol->sys_newfstatat = get_symbol_offset_zero(kallsym, img_buf, "__arm64_sys_newfstatat"); + if (!symbol->sys_newfstatat) symbol->sys_newfstatat = get_symbol_offset_zero(kallsym, img_buf, "sys_newfstatat"); + symbol->vfs_statx = try_get_symbol_offset_zero(kallsym, img_buf, "vfs_statx"); + symbol->vfs_fstatat = try_get_symbol_offset_zero(kallsym, img_buf, "vfs_fstatat"); + if (!symbol->sys_newfstatat && !symbol->vfs_fstatat && !symbol->vfs_statx) + tools_loge_exit("no symbol vfs_statx and vfs_fstatat"); + // gcc -fipa-sra eg: avc_denied.isra.5 symbol->avc_denied = try_get_symbol_offset_zero(kallsym, img_buf, "avc_denied"); if (!symbol->avc_denied && is_android) tools_loge_exit("no symbol avc_denied"); diff --git a/version b/version index 44ea3065..06fc6597 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ #define MAJOR 0 #define MINOR 10 -#define PATCH 5 +#define PATCH 6 From decaf80c02ccbdbc4addf1d897f5ae358e33d2e1 Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 8 Apr 2024 19:45:40 +0800 Subject: [PATCH 02/71] skip calculate sizeof struct pt_regs --- kernel/patch/common/utils.c | 26 ++++++++++----------- kernel/patch/ksyms/{execv.c => execv.c.bak} | 0 2 files changed, 13 insertions(+), 13 deletions(-) rename kernel/patch/ksyms/{execv.c => execv.c.bak} (100%) diff --git a/kernel/patch/common/utils.c b/kernel/patch/common/utils.c index 33779e50..d831abe0 100644 --- a/kernel/patch/common/utils.c +++ b/kernel/patch/common/utils.c @@ -118,22 +118,22 @@ struct pt_regs *_task_pt_reg(struct task_struct *task) { unsigned long stack = (unsigned long)task_stack_page(task); uintptr_t addr = (uintptr_t)(thread_size + stack); - if (pt_regs_offset > 0) { - addr -= pt_regs_offset; - } else { + // if (pt_regs_offset > 0) { + // addr -= pt_regs_offset; + // } else { #ifndef ANDROID - if (kver < VERSION(4, 4, 19)) { - addr -= sizeof(struct pt_regs_lt4419); - } else + if (kver < VERSION(4, 4, 19)) { + addr -= sizeof(struct pt_regs_lt4419); + } else #endif - if (kver < VERSION(4, 14, 0)) { - addr -= sizeof(struct pt_regs_lt4140); - } else if (kver < VERSION(5, 10, 0)) { - addr -= sizeof(struct pt_regs_lt5100); - } else { - addr -= sizeof(struct pt_regs); - } + if (kver < VERSION(4, 14, 0)) { + addr -= sizeof(struct pt_regs_lt4140); + } else if (kver < VERSION(5, 10, 0)) { + addr -= sizeof(struct pt_regs_lt5100); + } else { + addr -= sizeof(struct pt_regs); } + // } return (struct pt_regs *)(addr); } diff --git a/kernel/patch/ksyms/execv.c b/kernel/patch/ksyms/execv.c.bak similarity index 100% rename from kernel/patch/ksyms/execv.c rename to kernel/patch/ksyms/execv.c.bak From 3d9bdeb0c458d8f50e43340365e9e0b401fc78e5 Mon Sep 17 00:00:00 2001 From: bmax Date: Tue, 9 Apr 2024 15:43:18 +0800 Subject: [PATCH 03/71] su command: fuck compat compat-syscall for 32-bits --- kernel/linux/arch/arm64/include/asm/ptrace.h | 2 +- kernel/patch/android/sucompat.c | 184 +++++++++++-------- kernel/patch/android/userd.c | 2 - kernel/patch/common/syscall.c | 15 +- kernel/patch/common/utils.c | 26 +-- kernel/patch/include/syscall.h | 31 ++++ kernel/patch/ksyms/{execv.c.bak => execv.c} | 0 kernel/patch/patch.c | 4 +- tools/patch.c | 2 +- 9 files changed, 167 insertions(+), 99 deletions(-) rename kernel/patch/ksyms/{execv.c.bak => execv.c} (100%) diff --git a/kernel/linux/arch/arm64/include/asm/ptrace.h b/kernel/linux/arch/arm64/include/asm/ptrace.h index 63caef6c..fc98797e 100644 --- a/kernel/linux/arch/arm64/include/asm/ptrace.h +++ b/kernel/linux/arch/arm64/include/asm/ptrace.h @@ -276,7 +276,7 @@ static inline void forget_syscall(struct pt_regs *regs) static inline unsigned long user_stack_pointer(struct pt_regs *regs) { - // if (compat_user_mode(regs)) return regs->compat_sp; + if (compat_user_mode(regs)) return regs->compat_sp; return regs->sp; } diff --git a/kernel/patch/android/sucompat.c b/kernel/patch/android/sucompat.c index 16c5637a..28dccbf6 100644 --- a/kernel/patch/android/sucompat.c +++ b/kernel/patch/android/sucompat.c @@ -250,10 +250,9 @@ static uid_t current_uid() return uid; } -// #define SU_COMPAT_HOOK_SYSCALL -// #define TRY_DIRECT_MODIFY_USER +// #define SU_COMPAT_INLINE_HOOK -#ifndef SU_COMPAT_HOOK_SYSCALL +#ifdef SU_COMPAT_INLINE_HOOK // int do_execveat_common(int fd, struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp, int flags) // int __do_execve_file(int fd, struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp, int flags, @@ -306,7 +305,6 @@ static void before_do_execve(hook_fargs8_t *args, void *udata) // auth skey char arg1[SUPER_KEY_LEN]; - arg1[0] = '\0'; if (compat_strncpy_from_user(arg1, p1, sizeof(arg1)) <= 0) return; if (auth_superkey(arg1)) return; @@ -329,7 +327,6 @@ static void before_do_execve(hook_fargs8_t *args, void *udata) return; } -// static long do_faccessat(int dfd, const char __user *filename, int mode, int flags) // SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) // SYSCALL_DEFINE4(faccessat2, int, dfd, const char __user *, filename, int, mode, int, flags) static void before_faccessat(hook_fargs4_t *args, void *udata) @@ -337,13 +334,9 @@ static void before_faccessat(hook_fargs4_t *args, void *udata) uid_t uid = current_uid(); if (!is_su_allow_uid(uid)) return; - char __user *filename = (char __user *)args->arg1; - - int is_syscall = (uint64_t)udata; - if (is_syscall) filename = (char __user *)syscall_argn(args, 1); + char __user *filename = (char __user *)syscall_argn(args, 1); char buf[SU_PATH_MAX_LEN]; - buf[0] = '\0'; compat_strncpy_from_user(buf, filename, sizeof(buf)); if (strcmp(current_su_path, buf)) return; @@ -361,7 +354,6 @@ static void before_sysfstatat(hook_fargs4_t *args, void *udata) char *__user filename = (char *__user)syscall_argn(args, 1); char buf[SU_PATH_MAX_LEN]; - buf[0] = '\0'; compat_strncpy_from_user(buf, filename, sizeof(buf)); if (!strcmp(current_su_path, buf)) { void *__user uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); @@ -374,39 +366,44 @@ static void before_sysfstatat(hook_fargs4_t *args, void *udata) // int vfs_statx(int dfd, struct filename *filename, int flags, struct kstat *stat, u32 request_mask) // int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, int flags) // int vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat, u32 request_mask) -static void before_stat(hook_fargs8_t *args, void *udata) -{ - uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; - - if ((args->arg1 & 0xF000000000000000) == 0xF000000000000000) { - struct filename *filename = (struct filename *)args->arg1; - if (IS_ERR(filename)) return; - if (!strcmp(current_su_path, filename->name)) { - logkfd("0 uid: %d\n", uid); - strcpy((char *)filename->name, sh_path); - return; - } - } else { - char __user *filename = (char __user *)args->arg1; - char buf[SU_PATH_MAX_LEN]; - buf[0] = '\0'; - compat_strncpy_from_user(buf, filename, sizeof(buf)); - if (!strcmp(current_su_path, buf)) { - void *__user uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); - args->arg1 = (uint64_t)uptr; - logkfd("1 uid: %d, %llx\n", uid, uptr); - } - return; - } -} +// static void before_stat(hook_fargs8_t *args, void *udata) +// { +// uid_t uid = current_uid(); +// if (!is_su_allow_uid(uid)) return; + +// if ((args->arg1 & 0xF000000000000000) == 0xF000000000000000) { +// struct filename *filename = (struct filename *)args->arg1; +// if (IS_ERR(filename)) return; +// if (!strcmp(current_su_path, filename->name)) { +// logkfd("0 uid: %d\n", uid); +// strcpy((char *)filename->name, sh_path); +// return; +// } +// } else { +// char __user *filename = (char __user *)args->arg1; +// char buf[SU_PATH_MAX_LEN]; +// compat_strncpy_from_user(buf, filename, sizeof(buf)); +// if (!strcmp(current_su_path, buf)) { +// void *__user uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); +// args->arg1 = (uint64_t)uptr; +// logkfd("1 uid: %d, %llx\n", uid, uptr); +// } +// return; +// } +// } + +#else // SU_COMPAT_INLINE_HOOK -#else // SU_COMPAT_HOOK_SYSCALL +// #define TRY_DIRECT_MODIFY_USER static void handle_before_execve(hook_local_t *hook_local, char **__user u_filename_p, char **__user uargv, void *udata) { +#ifdef TRY_DIRECT_MODIFY_USER // copy to user len hook_local->data0 = 0; +#endif + + void *is_compact = udata; char __user *ufilename = *u_filename_p; char filename[SU_PATH_MAX_LEN]; @@ -427,12 +424,13 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen int cplen = 0; #ifdef TRY_DIRECT_MODIFY_USER cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); -#endif if (cplen > 0) { hook_local->data0 = cplen; hook_local->data1 = (uint64_t)u_filename_p; logkfi("call su uid: %d, to_uid: %d, sctx: %s, cplen: %d\n", uid, to_uid, sctx, cplen); - } else { + } +#endif + if (cplen <= 0) { void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); if (uptr && !IS_ERR(uptr)) { *u_filename_p = (char *__user)uptr; @@ -446,12 +444,13 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen int cplen = 0; #ifdef TRY_DIRECT_MODIFY_USER cplen = compat_copy_to_user(*u_filename_p, apd_path, sizeof(apd_path)); -#endif - uint64_t sp = 0; if (cplen > 0) { hook_local->data0 = cplen; hook_local->data1 = (uint64_t)u_filename_p; - } else { + } +#endif + uint64_t sp = 0; + if (cplen <= 0) { sp = current_user_stack_pointer(); sp -= sizeof(apd_path); sp &= 0xFFFFFFFFFFFFFFF8; @@ -465,7 +464,7 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen int argv_cplen = 0; if (strcmp(legacy_su_path, filename)) { #ifdef TRY_DIRECT_MODIFY_USER - const char __user *p1 = get_user_arg_ptr(0, *uargv, 0); + const char __user *p1 = get_user_arg_ptr(is_compact, *uargv, 0); argv_cplen = compat_copy_to_user((void *__user)p1, legacy_su_path, sizeof(legacy_su_path)); #endif if (argv_cplen <= 0) { @@ -474,7 +473,7 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen sp &= 0xFFFFFFFFFFFFFFF8; argv_cplen = compat_copy_to_user((void *)sp, legacy_su_path, sizeof(legacy_su_path)); if (argv_cplen > 0) { - int rc = set_user_arg_ptr(0, *uargv, 0, sp); + int rc = set_user_arg_ptr(is_compact, *uargv, 0, sp); if (rc < 0) { // todo: modify entire argv logkfi("call apd argv error, uid: %d, to_uid: %d, sctx: %s, rc: %d\n", uid, to_uid, sctx, rc); @@ -487,7 +486,7 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen } else if (!strcmp(SUPERCMD, filename)) { // key - const char __user *p1 = get_user_arg_ptr(0, *uargv, 1); + const char __user *p1 = get_user_arg_ptr(is_compact, *uargv, 1); if (!p1 || IS_ERR(p1)) return; // auth key @@ -502,7 +501,7 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen const char *exec = sh_path; int exec_len = sizeof(sh_path); - const char __user *p2 = get_user_arg_ptr(0, *uargv, 2); + const char __user *p2 = get_user_arg_ptr(is_compact, *uargv, 2); if (p1 && !IS_ERR(p2)) { char buffer[EMBEDDED_NAME_MAX]; @@ -520,7 +519,7 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen if (cplen <= 0) *u_filename_p = copy_to_user_stack(exec, exec_len); // shift args - *uargv += 2 * 8; + *uargv += 2 * (is_compact ? 4 : 8); } } @@ -535,6 +534,11 @@ static void handle_after_execve(hook_local_t *hook_local) } #endif +// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2107 +// COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename, +// const compat_uptr_t __user *, argv, +// const compat_uptr_t __user *, envp) + // https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2087 // SYSCALL_DEFINE3(execve, const char __user *, filename, const char __user *const __user *, argv, // const char __user *const __user *, envp) @@ -554,6 +558,13 @@ static void after_execve(hook_fargs3_t *args, void *udata) #define after_execve 0 #endif +// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2114 +// COMPAT_SYSCALL_DEFINE5(execveat, int, fd, +// const char __user *, filename, +// const compat_uptr_t __user *, argv, +// const compat_uptr_t __user *, envp, +// int, flags) + // https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2095 // SYSCALL_DEFINE5(execveat, int, fd, const char __user *, filename, const char __user *const __user *, argv, // const char __user *const __user *, envp, int, flags) @@ -632,7 +643,7 @@ static void su_handler_arg1_ufilename_after(hook_fargs6_t *args, void *udata) #define su_handler_arg1_ufilename_after 0 #endif -#endif // SU_COMPAT_HOOK_SYSCALL +#endif // SU_COMPAT_INLINE_HOOK int su_compat_init() { @@ -655,7 +666,7 @@ int su_compat_init() hook_err_t rc = HOOK_NO_ERR; -#ifndef SU_COMPAT_HOOK_SYSCALL +#ifdef SU_COMPAT_INLINE_HOOK struct patch_symbol *symbol = get_preset_patch_sym(); @@ -670,55 +681,74 @@ int su_compat_init() log_boot("hook do_execve_common rc: %d\n", rc); } - if (symbol->do_faccessat) { - rc = hook_wrap4((void *)symbol->do_faccessat, (void *)before_faccessat, 0, 0); - log_boot("hook do_faccessat rc: %d\n", rc); - } else { - if (symbol->sys_faccessat) { - rc = hook_wrap4((void *)symbol->sys_faccessat, (void *)before_faccessat, 0, (void *)1); - log_boot("hook sys_faccessat rc: %d\n", rc); - } - if (symbol->sys_faccessat2) { - rc = hook_wrap4((void *)symbol->sys_faccessat2, (void *)before_faccessat, 0, (void *)1); - log_boot("hook sys_faccessat2 rc: %d\n", rc); - } + if (symbol->sys_faccessat) { + rc = hook_wrap4((void *)symbol->sys_faccessat, (void *)before_faccessat, 0, (void *)1); + log_boot("hook sys_faccessat rc: %d\n", rc); + } + if (symbol->sys_faccessat2) { + rc = hook_wrap4((void *)symbol->sys_faccessat2, (void *)before_faccessat, 0, (void *)1); + log_boot("hook sys_faccessat2 rc: %d\n", rc); } if (symbol->sys_newfstatat) { rc = hook_wrap4((void *)symbol->sys_newfstatat, (void *)before_sysfstatat, 0, (void *)1); log_boot("hook sys_newfstatat rc: %d\n", rc); - } else { // never reach - if (symbol->vfs_statx) { - rc = hook_wrap8((void *)symbol->vfs_statx, (void *)before_stat, 0, (void *)0); - log_boot("hook vfs_statx rc: %d\n", rc); - } - - if (symbol->vfs_fstatat) { - rc = hook_wrap8((void *)symbol->vfs_fstatat, (void *)before_stat, 0, (void *)0); - log_boot("hook vfs_fstatat rc: %d\n", rc); - } } #else - rc = fp_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)__NR_execve); + rc = fp_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)0); log_boot("hook __NR_execve rc: %d\n", rc); - rc = fp_hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)__NR_execveat); + rc = fp_hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)0); log_boot("hook __NR_execveat rc: %d\n", rc); rc = fp_hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)__NR3264_fstatat); + (void *)0); log_boot("hook __NR3264_fstatat rc: %d\n", rc); + rc = fp_hook_syscalln(__NR_statx, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + log_boot("hook __NR_statx rc: %d\n", rc); + rc = fp_hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)__NR_faccessat); + (void *)0); log_boot("hook __NR_faccessat rc: %d\n", rc); rc = fp_hook_syscalln(__NR_faccessat2, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)__NR_faccessat2); + (void *)0); log_boot("hook __NR_faccessat2 rc: %d\n", rc); + // #include + + // __NR_execve 11 + rc = fp_hook_compat_syscalln(11, 3, before_execve, after_execve, (void *)1); + log_boot("hook 32 __NR_execve rc: %d\n", rc); + + // __NR_execveat 387 + rc = fp_hook_compat_syscalln(387, 5, before_execveat, after_execveat, (void *)1); + log_boot("hook 32 __NR_execveat rc: %d\n", rc); + + // __NR_statx 397 + rc = fp_hook_compat_syscalln(397, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + log_boot("hook 32 __NR_statx rc: %d\n", rc); + + // #define __NR_stat 106 + // #define __NR_lstat 107 + // #define __NR_stat64 195 + // #define __NR_lstat64 196 + + // __NR_fstatat64 327 + rc = fp_hook_compat_syscalln(327, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + log_boot("hook 32 __NR_fstatat64 rc: %d\n", rc); + + // __NR_faccessat 334 + rc = fp_hook_compat_syscalln(334, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + log_boot("hook 32 __NR_faccessat rc: %d\n", rc); + + // __NR_faccessat2 439 + rc = fp_hook_compat_syscalln(439, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + log_boot("hook 32 __NR_faccessat2 rc: %d\n", rc); + #endif return rc; diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 38d6e5eb..fe9f3c9f 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -128,8 +128,6 @@ static void on_first_app_process() { } -#define TRY_DIRECT_MODIFY_USER - static void handle_before_execve(hook_local_t *hook_local, char **__user u_filename_p, char **__user uargv, char **__user uenvp, void *udata) { diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index 5b3efa5f..c83130b0 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -22,6 +22,9 @@ uintptr_t *sys_call_table = 0; KP_EXPORT_SYMBOL(sys_call_table); +uintptr_t *compat_sys_call_table = 0; +KP_EXPORT_SYMBOL(compat_sys_call_table); + int has_syscall_wrapper = 0; KP_EXPORT_SYMBOL(has_syscall_wrapper); @@ -71,15 +74,18 @@ const char __user *get_user_arg_ptr(void *a0, void *a1, int nr) int set_user_arg_ptr(void *a0, void *a1, int nr, uintptr_t val) { + uintptr_t valp = (uintptr_t)&val; char __user *const __user *native = (char __user *const __user *)a0; int size = 8; if (has_config_compat) { native = (char __user *const __user *)a1; - if (a0) size = 4; // compat + if (a0) { + size = 4; // compat + valp += 4; + } } native = (char __user *const __user *)((unsigned long)native + nr * size); - uintptr_t valarr[1] = { val }; - int cplen = compat_copy_to_user((void *)native, (void *)valarr, size); + int cplen = compat_copy_to_user((void *)native, (void *)valp, size); return cplen == size ? 0 : cplen; } @@ -257,6 +263,9 @@ int syscall_init() } log_boot("sys_call_table addr: %llx\n", sys_call_table); + compat_sys_call_table = (typeof(compat_sys_call_table))kallsyms_lookup_name("compat_sys_call_table"); + log_boot("compat_sys_call_table addr: %llx\n", compat_sys_call_table); + has_config_compat = 0; has_syscall_wrapper = 0; diff --git a/kernel/patch/common/utils.c b/kernel/patch/common/utils.c index d831abe0..33779e50 100644 --- a/kernel/patch/common/utils.c +++ b/kernel/patch/common/utils.c @@ -118,22 +118,22 @@ struct pt_regs *_task_pt_reg(struct task_struct *task) { unsigned long stack = (unsigned long)task_stack_page(task); uintptr_t addr = (uintptr_t)(thread_size + stack); - // if (pt_regs_offset > 0) { - // addr -= pt_regs_offset; - // } else { + if (pt_regs_offset > 0) { + addr -= pt_regs_offset; + } else { #ifndef ANDROID - if (kver < VERSION(4, 4, 19)) { - addr -= sizeof(struct pt_regs_lt4419); - } else + if (kver < VERSION(4, 4, 19)) { + addr -= sizeof(struct pt_regs_lt4419); + } else #endif - if (kver < VERSION(4, 14, 0)) { - addr -= sizeof(struct pt_regs_lt4140); - } else if (kver < VERSION(5, 10, 0)) { - addr -= sizeof(struct pt_regs_lt5100); - } else { - addr -= sizeof(struct pt_regs); + if (kver < VERSION(4, 14, 0)) { + addr -= sizeof(struct pt_regs_lt4140); + } else if (kver < VERSION(5, 10, 0)) { + addr -= sizeof(struct pt_regs_lt5100); + } else { + addr -= sizeof(struct pt_regs); + } } - // } return (struct pt_regs *)(addr); } diff --git a/kernel/patch/include/syscall.h b/kernel/patch/include/syscall.h index c49223e9..af024ea7 100644 --- a/kernel/patch/include/syscall.h +++ b/kernel/patch/include/syscall.h @@ -13,6 +13,7 @@ #include extern uintptr_t *sys_call_table; +extern uintptr_t *compat_sys_call_table; extern int has_syscall_wrapper; const char __user *get_user_arg_ptr(void *a0, void *a1, int nr); @@ -68,6 +69,21 @@ static inline void fp_unhook_syscall(int nr, void *before, void *after) fp_hook_unwrap(fp_addr, before, after); } +static inline hook_err_t fp_hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) +{ + if (!compat_sys_call_table) return HOOK_BAD_ADDRESS; + uintptr_t fp_addr = (uintptr_t)(compat_sys_call_table + nr); + if (has_syscall_wrapper) narg = 1; + return fp_hook_wrap(fp_addr, narg, before, after, udata); +} + +static inline void fp_unhook_compat_syscall(int nr, void *before, void *after) +{ + if (!compat_sys_call_table) return; + uintptr_t fp_addr = (uintptr_t)(compat_sys_call_table + nr); + fp_hook_unwrap(fp_addr, before, after); +} + /* xxx.cfi_jt example: hint #0x22 @@ -86,6 +102,21 @@ static inline void inline_unhook_syscall(int nr, void *before, void *after) hook_unwrap((void *)fp, before, after); } +static inline hook_err_t inline_hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) +{ + if (!compat_sys_call_table) return HOOK_BAD_ADDRESS; + uintptr_t fp = compat_sys_call_table[nr]; + if (has_syscall_wrapper) narg = 1; + return hook_wrap((void *)fp, narg, before, after, udata); +} + +static inline void inline_unhook_compat_syscall(int nr, void *before, void *after) +{ + if (!compat_sys_call_table) return; + uintptr_t fp = compat_sys_call_table[nr]; + hook_unwrap((void *)fp, before, after); +} + int syscall_init(); #endif \ No newline at end of file diff --git a/kernel/patch/ksyms/execv.c.bak b/kernel/patch/ksyms/execv.c similarity index 100% rename from kernel/patch/ksyms/execv.c.bak rename to kernel/patch/ksyms/execv.c diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 77a9a009..6681566b 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -80,8 +80,8 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) rc = supercall_install(); log_boot("supercall_install done: %d\n", rc); - // rc = resolve_pt_regs(); - // log_boot("resolve_pt_regs done: %d\n", rc); + rc = resolve_pt_regs(); + log_boot("resolve_pt_regs done: %d\n", rc); #ifdef ANDROID rc = su_compat_init(); diff --git a/tools/patch.c b/tools/patch.c index cc887a89..f9a5ba5f 100644 --- a/tools/patch.c +++ b/tools/patch.c @@ -475,7 +475,7 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * start_offset = align_ceil(out_all_len, SZ_4K); tools_logi("patch overlap, move start from 0x%x to 0x%x\n", align_kernel_size, start_offset); } - tools_logi("layout kimg: 0x0-0x%x, kpimg: 0x%x,0x%x, extra: 0x%x,0x%x, end: 0x%x, start: 0x%x\n", ori_kimg_len, + tools_logi("layout kimg: 0x0,0x%x, kpimg: 0x%x,0x%x, extra: 0x%x,0x%x, end: 0x%x, start: 0x%x\n", ori_kimg_len, align_kimg_len, kpimg_len, out_img_len, extra_size, out_all_len, start_offset); kernel_file_t out_kernel_file; From 6f1781a4ff6c30896b7c88ec098188a5018eae07 Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 1 May 2024 08:48:45 +0800 Subject: [PATCH 04/71] fix: hook input_handle_event --- .github/workflows/build.yml | 2 +- .github/workflows/build_dev.yml | 2 +- kernel/patch/android/userd.c | 2 +- version | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e5dbd28b..54be42af 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -149,7 +149,7 @@ jobs: uses: nttld/setup-ndk@v1 id: setup-ndk with: - ndk-version: r25b + ndk-version: r26b add-to-path: true - name: Make hdr diff --git a/.github/workflows/build_dev.yml b/.github/workflows/build_dev.yml index 2f6ba868..725be0df 100644 --- a/.github/workflows/build_dev.yml +++ b/.github/workflows/build_dev.yml @@ -158,7 +158,7 @@ jobs: uses: nttld/setup-ndk@v1 id: setup-ndk with: - ndk-version: r25b + ndk-version: r26b add-to-path: true - name: Make hdr diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index fe9f3c9f..feb174c9 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -404,7 +404,7 @@ int kpuserd_init() ret |= rc; unsigned long input_handle_event_addr = get_preset_patch_sym()->input_handle_event; - if (!input_handle_event_addr) { + if (input_handle_event_addr) { rc = hook_wrap4((void *)input_handle_event_addr, before_input_handle_event, 0, 0); ret |= rc; log_boot("hook input_handle_event rc: %d\n", rc); diff --git a/version b/version index 06fc6597..462caf73 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ #define MAJOR 0 #define MINOR 10 -#define PATCH 6 +#define PATCH 7 From cbd6d6d9d8397efcfb7bf0ab428020065d0ff10b Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 1 May 2024 09:09:18 +0800 Subject: [PATCH 05/71] maintain pt_regs offset --- kernel/patch/common/utils.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/kernel/patch/common/utils.c b/kernel/patch/common/utils.c index 33779e50..beff9dde 100644 --- a/kernel/patch/common/utils.c +++ b/kernel/patch/common/utils.c @@ -124,11 +124,11 @@ struct pt_regs *_task_pt_reg(struct task_struct *task) #ifndef ANDROID if (kver < VERSION(4, 4, 19)) { addr -= sizeof(struct pt_regs_lt4419); + } else if (kver < VERSION(4, 14, 0)) { + addr -= sizeof(struct pt_regs_lt4140); } else #endif - if (kver < VERSION(4, 14, 0)) { - addr -= sizeof(struct pt_regs_lt4140); - } else if (kver < VERSION(5, 10, 0)) { + if (kver < VERSION(5, 10, 0)) { addr -= sizeof(struct pt_regs_lt5100); } else { addr -= sizeof(struct pt_regs); From 221a3d550c4b6e542b452fc7c7408a027d3d600e Mon Sep 17 00:00:00 2001 From: bmax121 Date: Thu, 16 May 2024 19:02:08 +0800 Subject: [PATCH 06/71] 1. kpatch is deprecated, instead is supercmd 2. hook imporvoed 3. add thread local interface for module 4. doc (#91) Co-authored-by: bmax --- .github/workflows/build.yml | 29 +- .github/workflows/build_dev.yml | 28 +- doc/.gitignore | 1 + doxyfile | 18 + kernel/base/fphook.c | 11 +- kernel/base/hook.c | 84 ++- kernel/{patch/common => base}/hotpatch.c | 4 + kernel/base/map.c | 2 +- kernel/base/setup.h | 1 + kernel/base/start.c | 46 +- kernel/base/symbol.c | 7 +- kernel/include/hook.h | 116 ++- kernel/include/hotpatch.h | 13 + kernel/include/predata.h | 2 +- kernel/include/preset.h | 9 - kernel/include/stdbool.h | 3 +- kernel/include/symbol.h | 8 +- .../linux/arch/arm64/include/asm/processor.h | 2 - kernel/linux/include/linux/cred.h | 7 +- kernel/linux/include/linux/fs.h | 1 - kernel/linux/include/linux/security.h | 11 +- kernel/linux/include/linux/string.h | 24 +- kernel/linux/include/linux/uaccess.h | 2 - kernel/patch/android/supercall.c | 85 --- kernel/patch/android/userd.c | 82 +- kernel/patch/common/accctl.c | 173 ++++- .../{selinuxhook.c => selinuxhook.c.bak} | 24 +- kernel/patch/{android => common}/sucompat.c | 411 +++------- kernel/patch/common/supercall.c | 140 +++- kernel/patch/common/supercmd.c | 405 ++++++++++ kernel/patch/common/syscall.c | 79 +- kernel/patch/common/sysname.c | 712 ++++++++++++++++++ kernel/patch/common/taskob.c | 57 +- kernel/patch/common/test.c | 17 + kernel/patch/common/utils.c | 23 +- kernel/patch/include/accctl.h | 41 +- kernel/patch/include/kputils.h | 4 +- kernel/patch/include/module.h | 2 - kernel/patch/include/sucompat.h | 8 + kernel/patch/include/syscall.h | 71 +- kernel/patch/include/taskext.h | 83 +- kernel/patch/include/uapi/scdefs.h | 46 +- kernel/patch/ksyms/execv.c | 10 +- kernel/patch/ksyms/libs.c | 13 +- kernel/patch/ksyms/misc.c | 19 +- kernel/patch/module/module.c | 11 +- kernel/patch/patch.c | 82 +- kernel/patch/patch.h | 6 - kpms/demo-syscallhook/syscallhook.c | 7 +- tools/kptools.c | 11 +- tools/patch.c | 15 +- tools/patch.h | 3 +- tools/symbol.c | 21 - user/.gitignore | 40 +- user/supercall.h | 335 ++++++-- user_deprecated/.gitignore | 39 + {user => user_deprecated}/CMakeLists.txt | 0 {user => user_deprecated}/Makefile | 0 .../android/android_user.c | 8 +- .../android/android_user.h | 0 {user => user_deprecated}/android/apjni.cpp | 0 {user => user_deprecated}/android/sumgr.c | 2 +- {user => user_deprecated}/android/sumgr.h | 0 {user => user_deprecated}/kpatch.c | 0 {user => user_deprecated}/kpatch.h | 0 {user => user_deprecated}/kpm.c | 0 {user => user_deprecated}/kpm.h | 0 {user => user_deprecated}/main.c | 0 {user => user_deprecated}/su.c | 4 +- {user => user_deprecated}/su.h | 0 user_deprecated/supercall.h | 411 ++++++++++ {user => user_deprecated}/supercall_ge0a04.h | 17 +- version | 4 +- 73 files changed, 2905 insertions(+), 1045 deletions(-) create mode 100644 doc/.gitignore create mode 100644 doxyfile rename kernel/{patch/common => base}/hotpatch.c (97%) create mode 100644 kernel/include/hotpatch.h delete mode 100644 kernel/patch/android/supercall.c rename kernel/patch/common/{selinuxhook.c => selinuxhook.c.bak} (94%) rename kernel/patch/{android => common}/sucompat.c (50%) create mode 100644 kernel/patch/common/supercmd.c create mode 100644 kernel/patch/common/sysname.c create mode 100644 kernel/patch/common/test.c delete mode 100644 kernel/patch/patch.h create mode 100644 user_deprecated/.gitignore rename {user => user_deprecated}/CMakeLists.txt (100%) rename {user => user_deprecated}/Makefile (100%) rename {user => user_deprecated}/android/android_user.c (97%) rename {user => user_deprecated}/android/android_user.h (100%) rename {user => user_deprecated}/android/apjni.cpp (100%) rename {user => user_deprecated}/android/sumgr.c (98%) rename {user => user_deprecated}/android/sumgr.h (100%) rename {user => user_deprecated}/kpatch.c (100%) rename {user => user_deprecated}/kpatch.h (100%) rename {user => user_deprecated}/kpm.c (100%) rename {user => user_deprecated}/kpm.h (100%) rename {user => user_deprecated}/main.c (100%) rename {user => user_deprecated}/su.c (99%) rename {user => user_deprecated}/su.h (100%) create mode 100644 user_deprecated/supercall.h rename {user => user_deprecated}/supercall_ge0a04.h (95%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 54be42af..2de32c87 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -38,17 +38,19 @@ jobs: - name: Build kpimg run: | export TARGET_COMPILE=`pwd`/arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-elf/bin/aarch64-none-elf- - cd kernel - make - mv kpimg kpimg-linux - mv kpimg.elf kpimg.elf-linux - make clean + export ANDROID=1 make mv kpimg kpimg-android mv kpimg.elf kpimg.elf-android + unset ANDROID + make + mv kpimg kpimg-linux + mv kpimg.elf kpimg.elf-linux + make clean + cd .. cd kpms @@ -125,7 +127,7 @@ jobs: replacesArtifacts: true omitBodyDuringUpdate: true - Build-android-kpatch-kptools: + Build-android-kptools: runs-on: ubuntu-latest permissions: contents: write @@ -158,21 +160,6 @@ jobs: cd kernel make hdr - - name: Build kpatch-android - run: | - cd user - export ANDROID=1 - mkdir -p build/android && cd build/android - echo ${{ steps.setup-ndk.outputs.ndk-path }} - cmake \ - -DCMAKE_TOOLCHAIN_FILE=${{ steps.setup-ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DANDROID_PLATFORM=android-33 \ - -DANDROID_ABI=arm64-v8a ../.. - cmake --build . - unset ANDROID - mv kpatch kpatch-android - - name: Build kptools-android run: | cd tools diff --git a/.github/workflows/build_dev.yml b/.github/workflows/build_dev.yml index 725be0df..c99057c7 100644 --- a/.github/workflows/build_dev.yml +++ b/.github/workflows/build_dev.yml @@ -48,15 +48,18 @@ jobs: run: | export TARGET_COMPILE=`pwd`/arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-elf/bin/aarch64-none-elf- cd kernel - make - mv kpimg kpimg-linux - mv kpimg.elf kpimg.elf-linux - make clean + export ANDROID=1 make mv kpimg kpimg-android mv kpimg.elf kpimg.elf-android + unset ANDROID + make + mv kpimg kpimg-linux + mv kpimg.elf kpimg.elf-linux + make clean + cd .. cd kpms @@ -134,7 +137,7 @@ jobs: replacesArtifacts: true prerelease: true - Build-android-kpatch-kptools: + Build-android-kptools: runs-on: ubuntu-latest permissions: contents: write @@ -167,21 +170,6 @@ jobs: cd kernel make hdr - - name: Build kpatch-android - run: | - cd user - export ANDROID=1 - mkdir -p build/android && cd build/android - echo ${{ steps.setup-ndk.outputs.ndk-path }} - cmake \ - -DCMAKE_TOOLCHAIN_FILE=${{ steps.setup-ndk.outputs.ndk-path }}/build/cmake/android.toolchain.cmake \ - -DCMAKE_BUILD_TYPE=Release \ - -DANDROID_PLATFORM=android-33 \ - -DANDROID_ABI=arm64-v8a ../.. - cmake --build . - unset ANDROID - mv kpatch kpatch-android - - name: Build kptools-android run: | cd tools diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 00000000..9e5bfb42 --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1 @@ +api \ No newline at end of file diff --git a/doxyfile b/doxyfile new file mode 100644 index 00000000..af3a3966 --- /dev/null +++ b/doxyfile @@ -0,0 +1,18 @@ +PROJECT_NAME = "KernelPatch Document" +OUTPUT_DIRECTORY = ./doc/api + +INPUT = \ + ./user/supercall.h \ + ./kernel/include/hook.h \ + ./kernel/patch/include/accctl.h \ + ./kernel/patch/include/taskext.h \ + ./kernel/patch/include/uapi/scdefs.h \ + +FILE_PATTERNS = *.h *.md + +RECURSIVE = YES +GENERATE_LATEX = NO +SOURCE_BROWSER = YES +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES diff --git a/kernel/base/fphook.c b/kernel/base/fphook.c index 6f8bba4d..620bdf29 100644 --- a/kernel/base/fphook.c +++ b/kernel/base/fphook.c @@ -19,6 +19,7 @@ uint64_t __attribute__((section(".fp.transit0.text"))) __attribute__((__noinline uint32_t *vptr = (uint32_t *)this_va; while (*--vptr != ARM64_NOP) { }; + vptr--; fp_hook_chain_t *hook_chain = local_container_of((uint64_t)vptr, fp_hook_chain_t, transit); hook_fargs0_t fargs; fargs.skip_origin = 0; @@ -52,6 +53,7 @@ _fp_transit4(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3) uint32_t *vptr = (uint32_t *)this_va; while (*--vptr != ARM64_NOP) { }; + vptr--; fp_hook_chain_t *hook_chain = local_container_of((uint64_t)vptr, fp_hook_chain_t, transit); hook_fargs4_t fargs; fargs.skip_origin = 0; @@ -91,6 +93,7 @@ _fp_transit8(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_ uint32_t *vptr = (uint32_t *)this_va; while (*--vptr != ARM64_NOP) { }; + vptr--; fp_hook_chain_t *hook_chain = local_container_of((uint64_t)vptr, fp_hook_chain_t, transit); hook_fargs8_t fargs; fargs.skip_origin = 0; @@ -136,6 +139,7 @@ _fp_transit12(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64 uint32_t *vptr = (uint32_t *)this_va; while (*--vptr != ARM64_NOP) { }; + vptr--; fp_hook_chain_t *hook_chain = local_container_of((uint64_t)vptr, fp_hook_chain_t, transit); hook_fargs12_t fargs; fargs.skip_origin = 0; @@ -205,9 +209,10 @@ static hook_err_t hook_chain_prepare(uint32_t *transit, int32_t argno) // todo: assert if (transit_num >= TRANSIT_INST_NUM) return -HOOK_TRANSIT_NO_MEM; - transit[0] = ARM64_NOP; + transit[0] = ARM64_BTI_JC; + transit[1] = ARM64_NOP; for (int i = 0; i < transit_num; i++) { - transit[i + 1] = ((uint32_t *)transit_start)[i]; + transit[i + 2] = ((uint32_t *)transit_start)[i]; } return HOOK_NO_ERR; } @@ -258,6 +263,8 @@ hook_err_t fp_hook_wrap(uintptr_t fp_addr, int32_t argno, void *before, void *af } for (int i = 0; i < FP_HOOK_CHAIN_NUM; i++) { + if ((before && chain->befores[i] == before) || (after && chain->afters[i] == after)) return -HOOK_DUPLICATED; + // todo: atomic or lock if (chain->states[i] == CHAIN_ITEM_STATE_EMPTY) { chain->states[i] = CHAIN_ITEM_STATE_BUSY; diff --git a/kernel/base/hook.c b/kernel/base/hook.c index 049a6931..3bf0cab4 100644 --- a/kernel/base/hook.c +++ b/kernel/base/hook.c @@ -82,7 +82,7 @@ static int32_t relo_len[] = { 6, 8, 6, 4, 4, 6, 6, 6, 8, 8, 8, 8, 6, 6, 6, 6, 2 static int is_in_tramp(hook_t *hook, uint64_t addr) { uint64_t tramp_start = hook->origin_addr; - uint64_t tramp_end = tramp_start + hook->tramp_insts_len * 4; + uint64_t tramp_end = tramp_start + hook->tramp_insts_num * 4; if (addr >= tramp_start && addr < tramp_end) { return 1; } @@ -92,7 +92,7 @@ static int is_in_tramp(hook_t *hook, uint64_t addr) static uint64_t relo_in_tramp(hook_t *hook, uint64_t addr) { uint64_t tramp_start = hook->origin_addr; - uint64_t tramp_end = tramp_start + hook->tramp_insts_len * 4; + uint64_t tramp_end = tramp_start + hook->tramp_insts_num * 4; if (!(addr >= tramp_start && addr < tramp_end)) return addr; uint32_t addr_inst_index = (addr - tramp_start) / 4; uint64_t fix_addr = hook->relo_addr; @@ -118,14 +118,9 @@ static uint64_t branch_func_addr_once(uint64_t addr) uint64_t imm26 = bits32(inst, 25, 0); uint64_t imm64 = sign64_extend(imm26 << 2u, 28u); ret = addr + imm64; + } else if (inst == ARM64_BTI_C || inst == ARM64_BTI_J || inst == ARM64_BTI_JC) { + ret = addr + 4; } else { - addr += 4; - uint32_t inst1 = *(uint32_t *)addr; - if (((inst & MASK_HINT) == INST_HINT) && ((inst1 & MASK_B) == INST_B)) { - uint64_t imm26 = bits32(inst1, 25, 0); - uint64_t imm64 = sign64_extend(imm26 << 2u, 28u); - ret = addr + imm64; - } } return ret; } @@ -143,9 +138,9 @@ uint64_t branch_func_addr(uint64_t addr) #endif -hook_err_t relo_b(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) +static __noinline hook_err_t relo_b(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) { - uint32_t *buf = hook->relo_insts + hook->relo_insts_len; + uint32_t *buf = hook->relo_insts + hook->relo_insts_num; uint64_t imm64; if (type == INST_BC) { uint64_t imm19 = bits32(inst, 23, 5); @@ -175,9 +170,9 @@ hook_err_t relo_b(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t t return HOOK_NO_ERR; } -hook_err_t relo_adr(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) +static __noinline hook_err_t relo_adr(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) { - uint32_t *buf = hook->relo_insts + hook->relo_insts_len; + uint32_t *buf = hook->relo_insts + hook->relo_insts_num; uint32_t xd = bits32(inst, 4, 0); uint64_t immlo = bits32(inst, 30, 29); @@ -197,9 +192,9 @@ hook_err_t relo_adr(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t return HOOK_NO_ERR; } -hook_err_t relo_ldr(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) +static __noinline hook_err_t relo_ldr(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) { - uint32_t *buf = hook->relo_insts + hook->relo_insts_len; + uint32_t *buf = hook->relo_insts + hook->relo_insts_num; uint32_t rt = bits32(inst, 4, 0); uint64_t imm19 = bits32(inst, 23, 5); @@ -246,9 +241,9 @@ hook_err_t relo_ldr(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t return HOOK_NO_ERR; } -hook_err_t relo_cb(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) +static __noinline hook_err_t relo_cb(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) { - uint32_t *buf = hook->relo_insts + hook->relo_insts_len; + uint32_t *buf = hook->relo_insts + hook->relo_insts_num; uint64_t imm19 = bits32(inst, 23, 5); uint64_t offset = sign64_extend((imm19 << 2u), 21u); @@ -264,9 +259,9 @@ hook_err_t relo_cb(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t return HOOK_NO_ERR; } -hook_err_t relo_tb(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) +static __noinline hook_err_t relo_tb(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) { - uint32_t *buf = hook->relo_insts + hook->relo_insts_len; + uint32_t *buf = hook->relo_insts + hook->relo_insts_num; uint64_t imm14 = bits32(inst, 18, 5); uint64_t offset = sign64_extend((imm14 << 2u), 16u); @@ -282,9 +277,9 @@ hook_err_t relo_tb(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t return HOOK_NO_ERR; } -hook_err_t relo_ignore(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) +static __noinline hook_err_t relo_ignore(hook_t *hook, uint64_t inst_addr, uint32_t inst, inst_type_t type) { - uint32_t *buf = hook->relo_insts + hook->relo_insts_len; + uint32_t *buf = hook->relo_insts + hook->relo_insts_num; buf[0] = inst; buf[1] = ARM64_NOP; return HOOK_NO_ERR; @@ -333,11 +328,14 @@ int32_t branch_from_to(uint32_t *tramp_buf, uint64_t src_addr, uint64_t dst_addr #if 0 uint32_t len = branch_relative(tramp_buf, src_addr, dst_addr); if (len) return len; -#endif - // return branch_absolute(tramp_buf, dst_addr); +#else +#if 0 + return branch_absolute(tramp_buf, dst_addr); +#else return ret_absolute(tramp_buf, dst_addr); +#endif +#endif } -KP_EXPORT_SYMBOL(branch_from_to); // transit0 typedef uint64_t (*transit0_func_t)(); @@ -349,6 +347,7 @@ uint64_t __attribute__((section(".transit0.text"))) __attribute__((__noinline__) uint32_t *vptr = (uint32_t *)this_va; while (*--vptr != ARM64_NOP) { }; + vptr--; hook_chain_t *hook_chain = local_container_of((uint64_t)vptr, hook_chain_t, transit); hook_fargs0_t fargs; fargs.skip_origin = 0; @@ -382,6 +381,7 @@ _transit4(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3) uint32_t *vptr = (uint32_t *)this_va; while (*--vptr != ARM64_NOP) { }; + vptr--; hook_chain_t *hook_chain = local_container_of((uint64_t)vptr, hook_chain_t, transit); hook_fargs4_t fargs; fargs.skip_origin = 0; @@ -421,6 +421,7 @@ _transit8(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t a uint32_t *vptr = (uint32_t *)this_va; while (*--vptr != ARM64_NOP) { }; + vptr--; hook_chain_t *hook_chain = local_container_of((uint64_t)vptr, hook_chain_t, transit); hook_fargs8_t fargs; fargs.skip_origin = 0; @@ -466,6 +467,7 @@ _transit12(uint64_t arg0, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t uint32_t *vptr = (uint32_t *)this_va; while (*--vptr != ARM64_NOP) { }; + vptr--; hook_chain_t *hook_chain = local_container_of((uint64_t)vptr, hook_chain_t, transit); hook_fargs12_t fargs; fargs.skip_origin = 0; @@ -549,7 +551,7 @@ static __noinline hook_err_t relocate_inst(hook_t *hook, uint64_t inst_addr, uin break; } - hook->relo_insts_len += len; + hook->relo_insts_num += len; return rc; } @@ -566,14 +568,19 @@ hook_err_t hook_prepare(hook_t *hook) hook->origin_insts[i] = *((uint32_t *)hook->origin_addr + i); } // trampline to replace_addr - hook->tramp_insts_len = branch_from_to(hook->tramp_insts, hook->origin_addr, hook->replace_addr); + hook->tramp_insts_num = branch_from_to(hook->tramp_insts, hook->origin_addr, hook->replace_addr); // relocate for (int i = 0; i < sizeof(hook->relo_insts) / sizeof(hook->relo_insts[0]); i++) { hook->relo_insts[i] = ARM64_NOP; } - for (int i = 0; i < hook->tramp_insts_len; i++) { + uint32_t *bti = hook->relo_insts + hook->relo_insts_num; + bti[0] = ARM64_BTI_JC; + bti[1] = ARM64_NOP; + hook->relo_insts_num += 2; + + for (int i = 0; i < hook->tramp_insts_num; i++) { uint64_t inst_addr = hook->origin_addr + i * 4; uint32_t inst = hook->origin_insts[i]; hook_err_t relo_res = relocate_inst(hook, inst_addr, inst); @@ -583,10 +590,10 @@ hook_err_t hook_prepare(hook_t *hook) } // jump back - uint64_t back_src_addr = hook->relo_addr + hook->relo_insts_len * 4; - uint64_t back_dst_addr = hook->origin_addr + hook->tramp_insts_len * 4; - uint32_t *buf = hook->relo_insts + hook->relo_insts_len; - hook->relo_insts_len += branch_from_to(buf, back_src_addr, back_dst_addr); + uint64_t back_src_addr = hook->relo_addr + hook->relo_insts_num * 4; + uint64_t back_dst_addr = hook->origin_addr + hook->tramp_insts_num * 4; + uint32_t *buf = hook->relo_insts + hook->relo_insts_num; + hook->relo_insts_num += branch_from_to(buf, back_src_addr, back_dst_addr); return HOOK_NO_ERR; } KP_EXPORT_SYMBOL(hook_prepare); @@ -597,11 +604,11 @@ void hook_install(hook_t *hook) uint64_t va = hook->origin_addr; uint64_t *entry = pgtable_entry_kernel(va); uint64_t ori_prot = *entry; - *entry = (ori_prot | PTE_DBM) & ~PTE_RDONLY & 0xFFFBFFFFFFFFFFFF; + *entry = (ori_prot | PTE_DBM) & ~PTE_RDONLY; flush_tlb_kernel_page(va); - // todo: + // todo: cpu_stop_machine // todo: can use aarch64_insn_patch_text_nosync, aarch64_insn_patch_text directly? - for (int32_t i = 0; i < hook->tramp_insts_len; i++) { + for (int32_t i = 0; i < hook->tramp_insts_num; i++) { *((uint32_t *)hook->origin_addr + i) = hook->tramp_insts[i]; } flush_icache_all(); @@ -617,7 +624,7 @@ void hook_uninstall(hook_t *hook) uint64_t ori_prot = *entry; *entry = (ori_prot | PTE_DBM) & ~PTE_RDONLY; flush_tlb_kernel_page(va); - for (int32_t i = 0; i < hook->tramp_insts_len; i++) { + for (int32_t i = 0; i < hook->tramp_insts_num; i++) { *((uint32_t *)hook->origin_addr + i) = hook->origin_insts[i]; } flush_icache_all(); @@ -697,9 +704,10 @@ static hook_err_t hook_chain_prepare(uint32_t *transit, int32_t argno) // todo:assert if (transit_num >= TRANSIT_INST_NUM) return -HOOK_TRANSIT_NO_MEM; - transit[0] = ARM64_NOP; + transit[0] = ARM64_BTI_JC; + transit[1] = ARM64_NOP; for (int i = 0; i < transit_num; i++) { - transit[i + 1] = ((uint32_t *)transit_start)[i]; + transit[i + 2] = ((uint32_t *)transit_start)[i]; } return HOOK_NO_ERR; } @@ -707,6 +715,8 @@ static hook_err_t hook_chain_prepare(uint32_t *transit, int32_t argno) hook_err_t hook_chain_add(hook_chain_t *chain, void *before, void *after, void *udata) { for (int i = 0; i < HOOK_CHAIN_NUM; i++) { + if ((before && chain->befores[i] == before) || (after && chain->afters[i] == after)) return -HOOK_DUPLICATED; + // todo: atomic or lock if (chain->states[i] == CHAIN_ITEM_STATE_EMPTY) { chain->states[i] = CHAIN_ITEM_STATE_BUSY; diff --git a/kernel/patch/common/hotpatch.c b/kernel/base/hotpatch.c similarity index 97% rename from kernel/patch/common/hotpatch.c rename to kernel/base/hotpatch.c index 0cc30405..356b3901 100644 --- a/kernel/patch/common/hotpatch.c +++ b/kernel/base/hotpatch.c @@ -84,3 +84,7 @@ int hot_patch_text() // logkd("stop_machine rc: %d\n", rc); return 0; } + +int kp_insn_patch_text(void *addrs[], uint32_t insn[], int cnt) +{ +} \ No newline at end of file diff --git a/kernel/base/map.c b/kernel/base/map.c index 6e669a26..97898041 100644 --- a/kernel/base/map.c +++ b/kernel/base/map.c @@ -126,7 +126,7 @@ static uint64_t __noinline get_or_create_pte(map_data_t *data, uint64_t va, uint uint64_t baddr = ttbr1_el1 & 0xFFFFFFFFFFFE; uint64_t page_size = 1 << page_shift; uint64_t page_size_mask = ~(page_size - 1); - uint64_t attr_prot = 0xC0000000000703 | attr_indx; + uint64_t attr_prot = 0x40000000000703 | attr_indx; uint64_t pxd_pa = baddr & page_size_mask; uint64_t pxd_va = phys_to_lm(data, pxd_pa); diff --git a/kernel/base/setup.h b/kernel/base/setup.h index e17e1c79..c5de937e 100644 --- a/kernel/base/setup.h +++ b/kernel/base/setup.h @@ -17,6 +17,7 @@ #define __section(s) __attribute__((section(#s))) #define __noinline __attribute__((__noinline__)) #define __aligned(x) __attribute__((aligned(x))) +#define __bti_c __attribute__((target("branch-protection=bti"))) #endif diff --git a/kernel/base/start.c b/kernel/base/start.c index 4a901b84..cb03cfbc 100644 --- a/kernel/base/start.c +++ b/kernel/base/start.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -20,6 +19,7 @@ #include "hook.h" #include "tlsf.h" #include "hmem.h" +#include "setup.h" #define bits(n, high, low) (((n) << (63u - (high))) >> (63u - (high) + (low))) #define align_floor(x, align) ((uint64_t)(x) & ~((uint64_t)(align)-1)) @@ -41,7 +41,7 @@ KP_EXPORT_SYMBOL(lookup_symbol_attrs); void (*printk)(const char *fmt, ...) = 0; KP_EXPORT_SYMBOL(printk); -int (*vsprintf)(char *buf, const char *fmt, va_list args) = 0; +int (*vsnprintf)(char *buf, size_t size, const char *fmt, va_list args); static struct vm_struct { @@ -78,6 +78,9 @@ uint64_t _kp_rw_end = 0; uint64_t _kp_region_start = 0; uint64_t _kp_region_end = 0; +uint64_t link_base_addr = (uint64_t)_link_base; +uint64_t runtime_base_addr = 0; + uint64_t kimage_voffset = 0; uint64_t linear_voffset = 0; uint64_t kernel_va = 0; @@ -116,7 +119,7 @@ void log_boot(const char *fmt, ...) { va_list va; va_start(va, fmt); - int ret = vsprintf(boot_log + boot_log_offset, fmt, va); + int ret = vsnprintf(boot_log + boot_log_offset, sizeof(boot_log) - boot_log_offset, fmt, va); va_end(va); printk("KP %s", boot_log + boot_log_offset); boot_log_offset += ret; @@ -178,7 +181,8 @@ static void prot_myself() log_boot("Kernel stext prot: %llx\n", *kpte); _kp_region_start = (uint64_t)_kp_text_start; - _kp_region_end = (uint64_t)_kp_end + HOOK_ALLOC_SIZE + MEMORY_ROX_SIZE + MEMORY_RW_SIZE; + _kp_region_end = (uint64_t)_kp_end + align_ceil(start_preset.extra_size, page_size) + HOOK_ALLOC_SIZE + + MEMORY_ROX_SIZE + MEMORY_RW_SIZE; log_boot("Region: %llx, %llx\n", _kp_region_start, _kp_region_end); uint64_t *kppte = pgtable_entry_kernel(_kp_region_start); @@ -192,11 +196,9 @@ static void prot_myself() for (uint64_t i = text_start; i < align_text_end; i += page_size) { uint64_t *pte = pgtable_entry_kernel(i); - *pte |= PTE_SHARED; - *pte = *pte & ~PTE_PXN; + *pte = (*pte | PTE_SHARED) & ~PTE_PXN & ~PTE_GP; if (has_vmalloc_area()) { - *pte |= PTE_RDONLY; - *pte &= ~PTE_DBM; + *pte = (*pte | PTE_RDONLY) & ~PTE_DBM; } } flush_tlb_kernel_range(text_start, align_text_end); @@ -238,7 +240,7 @@ static void prot_myself() for (uint64_t i = _kp_hook_start; i < _kp_hook_end; i += page_size) { uint64_t *pte = pgtable_entry_kernel(i); - *pte = (*pte & ~PTE_PXN & ~PTE_RDONLY) | PTE_DBM | PTE_SHARED; + *pte = (*pte | PTE_DBM | PTE_SHARED) & ~PTE_PXN & ~PTE_RDONLY & ~PTE_GP; } flush_tlb_kernel_range(_kp_hook_start, _kp_hook_end); hook_mem_add(_kp_hook_start, HOOK_ALLOC_SIZE); @@ -270,8 +272,7 @@ static void prot_myself() for (uint64_t i = _kp_rox_start; i < _kp_rox_end; i += page_size) { uint64_t *pte = pgtable_entry_kernel(i); - *pte |= PTE_SHARED; - *pte = *pte & ~PTE_PXN; + *pte = (*pte | PTE_SHARED) & ~PTE_PXN & ~PTE_GP; // todo: tlsf malloc block_split will write to alloced memory // if (has_vmalloc_area()) { // *pte |= PTE_RDONLY; @@ -382,6 +383,7 @@ static void start_init(uint64_t kimage_voff, uint64_t linear_voff) kernel_pa = start_preset.kernel_pa; kernel_va = kimage_voff + kernel_pa; kernel_size = start_preset.kernel_size; + runtime_base_addr = (uint64_t)_link_base; uint64_t kallsym_addr = kernel_va + start_preset.kallsyms_lookup_name_offset; kallsyms_lookup_name = (typeof(kallsyms_lookup_name))(kallsym_addr); @@ -389,7 +391,7 @@ static void start_init(uint64_t kimage_voff, uint64_t linear_voff) printk = (typeof(printk))kallsyms_lookup_name("printk"); if (!printk) printk = (typeof(printk))kallsyms_lookup_name("_printk"); - vsprintf = (typeof(vsprintf))kallsyms_lookup_name("vsprintf"); + vsnprintf = (typeof(vsnprintf))kallsyms_lookup_name("vsnprintf"); log_boot(KERNEL_PATCH_BANNER); @@ -403,9 +405,11 @@ static void start_init(uint64_t kimage_voff, uint64_t linear_voff) log_boot("Kernel va: %llx\n", kernel_va); log_boot("Kernel Version: %x\n", kver); - log_boot("Kernel Patch Version: %x\n", kpver); - log_boot("Kernel Patch Config: %llx\n", header->config_flags); - log_boot("Kernel Patch Compile Time: %s\n", (uint64_t)header->compile_time); + log_boot("KernelPatch Version: %x\n", kpver); + log_boot("KernelPatch Config: %llx\n", header->config_flags); + log_boot("KernelPatch Compile Time: %s\n", (uint64_t)header->compile_time); + + log_boot("KernelPatch link base: %llx, runtime base: %llx\n", link_base_addr, runtime_base_addr); kallsyms_on_each_symbol = (typeof(kallsyms_on_each_symbol))kallsyms_lookup_name("kallsyms_on_each_symbol"); lookup_symbol_attrs = (typeof(lookup_symbol_attrs))kallsyms_lookup_name("lookup_symbol_attrs"); @@ -434,14 +438,8 @@ static void start_init(uint64_t kimage_voff, uint64_t linear_voff) pgd_va = phys_to_virt(pgd_pa); } -static int nice_zone() -{ - int err = 0; - - err = patch(); - - return err; -} +void symbol_init(); +int patch(); int __attribute__((section(".start.text"))) __noinline start(uint64_t kimage_voff, uint64_t linear_voff) { @@ -452,6 +450,6 @@ int __attribute__((section(".start.text"))) __noinline start(uint64_t kimage_vof log_regs(); predata_init(); symbol_init(); - rc = nice_zone(); + rc = patch(); return rc; } diff --git a/kernel/base/symbol.c b/kernel/base/symbol.c index 0f2c9ca5..e34b7dca 100644 --- a/kernel/base/symbol.c +++ b/kernel/base/symbol.c @@ -14,8 +14,6 @@ extern void _kp_symbol_start(); extern void _kp_symbol_end(); static uint64_t symbol_start = 0; static uint64_t symbol_end = 0; -static unsigned long link_base_addr = (unsigned long)_link_base; -static unsigned long runtime_base_addr = 0; // DJB2 static unsigned long sym_hash(const char *str) @@ -53,17 +51,14 @@ unsigned long symbol_lookup_name(const char *name) return 0; } -int symbol_init() +void symbol_init() { - runtime_base_addr = (unsigned long)_link_base; symbol_start = (uint64_t)_kp_symbol_start; symbol_end = (uint64_t)_kp_symbol_end; log_boot("Symbol: %llx, %llx\n", symbol_start, symbol_end); - log_boot("Symbol link: %llx, runtime: %llx\n", link_base_addr, runtime_base_addr); for (uint64_t addr = symbol_start; addr < symbol_end; addr += sizeof(kp_symbol_t)) { kp_symbol_t *symbol = (kp_symbol_t *)addr; symbol->addr = symbol->addr - link_base_addr + runtime_base_addr; symbol->hash = sym_hash(symbol->name); } - return 0; } \ No newline at end of file diff --git a/kernel/include/hook.h b/kernel/include/hook.h index 0d028c41..d29cbd87 100644 --- a/kernel/include/hook.h +++ b/kernel/include/hook.h @@ -14,13 +14,12 @@ typedef enum { HOOK_NO_ERR = 0, - HOOK_BAD_ADDRESS = 4089, - HOOK_NO_MEM = 4090, - HOOK_BAD_RELO = 4091, - HOOK_TRANSIT_NO_MEM = 4092, - HOOK_CHAIN_FULL = 4093, - HOOK_NOT_HOOK = 4094, - HOOK_INST_BUSY = 4095, + HOOK_BAD_ADDRESS = 4095, + HOOK_DUPLICATED = 4094, + HOOK_NO_MEM = 4093, + HOOK_BAD_RELO = 4092, + HOOK_TRANSIT_NO_MEM = 4091, + HOOK_CHAIN_FULL = 4090, } hook_err_t; enum hook_type @@ -50,6 +49,9 @@ typedef int8_t chain_item_state; #define FP_HOOK_CHAIN_NUM 0x20 #define ARM64_NOP 0xd503201f +#define ARM64_BTI_C 0xd503245f +#define ARM64_BTI_J 0xd503249f +#define ARM64_BTI_JC 0xd50324df typedef struct { @@ -59,8 +61,8 @@ typedef struct uint64_t replace_addr; uint64_t relo_addr; // out - int32_t tramp_insts_len; - int32_t relo_insts_len; + int32_t tramp_insts_num; + int32_t relo_insts_num; uint32_t origin_insts[TRAMPOLINE_NUM] __attribute__((aligned(8))); uint32_t tramp_insts[TRAMPOLINE_NUM] __attribute__((aligned(8))); uint32_t relo_insts[RELOCATE_INST_NUM] __attribute__((aligned(8))); @@ -242,13 +244,74 @@ int32_t ret_absolute(uint32_t *buf, uint64_t addr); hook_err_t hook_prepare(hook_t *hook); void hook_install(hook_t *hook); void hook_uninstall(hook_t *hook); + +/** + * @brief Inline-hook function which address is @param func with function @param replace, + * after hook, original @param func is backuped in @param backup. + * + * @note If multiple modules hook this function simultaneously, + * it will cause abnormality when unload the modules. Please use hook_wrap instead + * + * @see hook_wrap + * + * @param func + * @param replace + * @param backup + * @return hook_err_t + */ hook_err_t hook(void *func, void *replace, void **backup); + +/** + * @brief unhook of hooked function + * + * @param func + */ void unhook(void *func); -// todo: hook priority +/** + * @brief + * + * @param chain + * @param before + * @param after + * @param udata + * @return hook_err_t + */ hook_err_t hook_chain_add(hook_chain_t *chain, void *before, void *after, void *udata); +/** + * @brief + * + * @param chain + * @param before + * @param after + */ void hook_chain_remove(hook_chain_t *chain, void *before, void *after); + +/** + * @brief Wrap a function with before and after function. + * The same function can do hook and unhook multiple times + * + * @see hook_chain0_callback + * @see hook_fargs0_t + * + * @param func The address of function + * @param argno The number of method arguments + * @param before This function will be called before hooked function, + * the type of before is hook_chain{n}_callback which n is equal to argno. + * @param after The same as before but will be call after hooked function + * @param udata + * @return hook_err_t + */ hook_err_t hook_wrap(void *func, int32_t argno, void *before, void *after, void *udata); + +/** + * @brief + * + * @param func + * @param before + * @param after + * @param remove + */ void hook_unwrap_remove(void *func, void *before, void *after, int remove); static inline void hook_unwrap(void *func, void *before, void *after) @@ -263,9 +326,42 @@ static inline void *hook_chain_origin_func(void *hook_args) return (void *)chain->hook.relo_addr; } +/** + * @brief + * + * @param fp_addr + * @param replace + * @param backup + */ void fp_hook(uintptr_t fp_addr, void *replace, void **backup); + +/** + * @brief + * + * @param fp_addr + * @param backup + */ void fp_unhook(uintptr_t fp_addr, void *backup); + +/** + * @brief + * + * @param fp_addr + * @param argno + * @param before + * @param after + * @param udata + * @return hook_err_t + */ hook_err_t fp_hook_wrap(uintptr_t fp_addr, int32_t argno, void *before, void *after, void *udata); + +/** + * @brief + * + * @param fp_addr + * @param before + * @param after + */ void fp_hook_unwrap(uintptr_t fp_addr, void *before, void *after); static inline void hook_chain_install(hook_chain_t *chain) diff --git a/kernel/include/hotpatch.h b/kernel/include/hotpatch.h new file mode 100644 index 00000000..3a418f46 --- /dev/null +++ b/kernel/include/hotpatch.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024 bmax121. All Rights Reserved. + */ + +#ifndef _KP_HOTPATCH_H_ +#define _KP_HOTPATCH_H_ + +#include + +int kp_insn_patch_text(void *addrs[], uint32_t insn[], int cnt); + +#endif \ No newline at end of file diff --git a/kernel/include/predata.h b/kernel/include/predata.h index 66e60ec1..56ae5bd4 100644 --- a/kernel/include/predata.h +++ b/kernel/include/predata.h @@ -11,7 +11,7 @@ int auth_superkey(const char *key); void reset_superkey(const char *key); -void enable_auth_root_key(int skip_hash); +void enable_auth_root_key(int enable); const char *get_superkey(); uint64_t rand_next(); diff --git a/kernel/include/preset.h b/kernel/include/preset.h index af5921f9..1970d33e 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -117,15 +117,6 @@ struct patch_symbol uint64_t __cfi_slowpath; uint64_t copy_process; uint64_t cgroup_post_fork; - uint64_t do_execveat_common; - uint64_t __do_execve_file; - uint64_t do_execve_common; - uint64_t do_faccessat; - uint64_t sys_faccessat; - uint64_t sys_faccessat2; - uint64_t sys_newfstatat; - uint64_t vfs_statx; - uint64_t vfs_fstatat; uint64_t avc_denied; uint64_t slow_avc_audit; uint64_t input_handle_event; diff --git a/kernel/include/stdbool.h b/kernel/include/stdbool.h index 488efdb1..b40bcdfa 100644 --- a/kernel/include/stdbool.h +++ b/kernel/include/stdbool.h @@ -1,7 +1,8 @@ #ifndef _KP_STDBOOL_H_ #define _KP_STDBOOL_H_ -typedef unsigned char bool; +#define bool _Bool + #define true ((bool)1) #define false ((bool)0) diff --git a/kernel/include/symbol.h b/kernel/include/symbol.h index 14a487ff..c9e620ca 100644 --- a/kernel/include/symbol.h +++ b/kernel/include/symbol.h @@ -22,8 +22,14 @@ typedef struct #define KP_EXPORT_SYMBOL(sym) _KP_EXPORT_SYMBOL(sym) +extern unsigned long link_base_addr; +extern unsigned long runtime_base_addr; + unsigned long symbol_lookup_name(const char *name); -int symbol_init(); +static inline unsigned long link2runtime(unsigned long addr) +{ + return addr - link_base_addr + runtime_base_addr; +} #endif \ No newline at end of file diff --git a/kernel/linux/arch/arm64/include/asm/processor.h b/kernel/linux/arch/arm64/include/asm/processor.h index ca39a61c..79dad534 100644 --- a/kernel/linux/arch/arm64/include/asm/processor.h +++ b/kernel/linux/arch/arm64/include/asm/processor.h @@ -17,8 +17,6 @@ // #define THREAD_START_SP (THREAD_SIZE - 16) // #define task_pt_regs(p) ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) -// implemented in utils - extern int16_t pt_regs_offset; struct pt_regs *_task_pt_reg(struct task_struct *task); diff --git a/kernel/linux/include/linux/cred.h b/kernel/linux/include/linux/cred.h index b425a0ee..6af545fa 100644 --- a/kernel/linux/include/linux/cred.h +++ b/kernel/linux/include/linux/cred.h @@ -163,36 +163,41 @@ static inline struct cred *prepare_kernel_cred(struct task_struct *daemon) kfunc_not_found(); return 0; } + static inline int change_create_files_as(struct cred *cred, struct inode *inode) { kfunc_call(change_create_files_as, cred, inode); kfunc_not_found(); return 0; } + static inline int set_security_override(struct cred *new, u32 secid) { kfunc_call(set_security_override, new, secid); - kfunc_not_found(); return 0; } + static inline int set_security_override_from_ctx(struct cred *new, const char *secctx) { kfunc_call(set_security_override_from_ctx, new, secctx); kfunc_not_found(); return 0; } + static inline int set_create_files_as(struct cred *new, struct inode *inode) { kfunc_call(set_create_files_as, new, inode); kfunc_not_found(); return 0; } + static inline int cred_fscmp(const struct cred *a, const struct cred *b) { kfunc_call(cred_fscmp, a, b); kfunc_not_found(); return 0; } + static inline void cred_init(void) { kfunc_call(cred_init); diff --git a/kernel/linux/include/linux/fs.h b/kernel/linux/include/linux/fs.h index 799980a8..896915fb 100644 --- a/kernel/linux/include/linux/fs.h +++ b/kernel/linux/include/linux/fs.h @@ -359,7 +359,6 @@ static inline loff_t vfs_llseek(struct file *file, loff_t offset, int whence) static inline void putname(struct filename *name) { - // logkd("aaaaaaaaaaa %llx\n", kfunc(putname)); kfunc_direct_call_void(putname, name); // kfunc_direct_call_void(final_putname, name); } diff --git a/kernel/linux/include/linux/security.h b/kernel/linux/include/linux/security.h index 51922cd8..18f3eb48 100644 --- a/kernel/linux/include/linux/security.h +++ b/kernel/linux/include/linux/security.h @@ -624,8 +624,6 @@ static inline int cap_vm_enough_memory(struct mm_struct *mm, long pages) return 0; } -// - static inline void security_task_getsecid(struct task_struct *task, u32 *secid) { kfunc_call(security_task_getsecid, task, secid); @@ -633,19 +631,14 @@ static inline void security_task_getsecid(struct task_struct *task, u32 *secid) kfunc_not_found(); } -// When we are uncertain whether secctx exists or is correct, we cannot rely on security_secctx_to_secid; otherwise, secid might be set to an unexpected value. static inline int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) { - kfunc_call(security_secctx_to_secid, secdata, seclen, secid); - kfunc_not_found(); - return 0; + kfunc_direct_call(security_secctx_to_secid, secdata, seclen, secid); } static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { - kfunc_call(security_secid_to_secctx, secid, secdata, seclen); - kfunc_not_found(); - return 0; + kfunc_direct_call(security_secid_to_secctx, secid, secdata, seclen); } static inline void security_release_secctx(char *secdata, u32 seclen) diff --git a/kernel/linux/include/linux/string.h b/kernel/linux/include/linux/string.h index c52930b9..bec5fcd2 100644 --- a/kernel/linux/include/linux/string.h +++ b/kernel/linux/include/linux/string.h @@ -6,11 +6,15 @@ #include #include +extern char *kfunc_def(strndup_user)(const char __user *, long); +extern void *kfunc_def(memdup_user)(const void __user *, size_t); +extern void *kfunc_def(vmemdup_user)(const void __user *, size_t); +extern void *kfunc_def(memdup_user_nul)(const void __user *, size_t); + extern void kfunc_def(kfree_const)(const void *x); extern char *kfunc_def(kstrdup)(const char *s, gfp_t gfp); extern const char *kfunc_def(kstrdup_const)(const char *s, gfp_t gfp); extern char *kfunc_def(kstrndup)(const char *s, size_t len, gfp_t gfp); -extern void *kfunc_def(memdup_user)(const void __user *src, size_t len); extern void *kfunc_def(kmemdup)(const void *src, size_t len, gfp_t gfp); extern char *kfunc_def(kmemdup_nul)(const char *s, size_t len, gfp_t gfp); extern char **kfunc_def(argv_split)(gfp_t gfp, const char *str, int *argcp); @@ -62,6 +66,9 @@ extern void *kfunc_def(memchr_inv)(const void *start, int c, size_t bytes); extern char *kfunc_def(strreplace)(char *s, char old, char new); extern void kfunc_def(fortify_panic)(const char *name); +extern int __must_check kfunc_def(kstrtoull)(const char *s, unsigned int base, unsigned long long *res); +extern int __must_check kfunc_def(kstrtoll)(const char *s, unsigned int base, long long *res); + static inline void kfree_const(const void *x) { kfunc_direct_call(kfree_const, x); @@ -92,6 +99,11 @@ static inline char *kmemdup_nul(const char *s, size_t len, gfp_t gfp) kfunc_direct_call(kmemdup_nul, s, len, gfp); } +static inline char *strndup_user(const void __user *s, long len) +{ + kfunc_direct_call(strndup_user, s, len); +} + static inline void *memdup_user(const void __user *src, size_t len) { kfunc_direct_call(memdup_user, src, len); @@ -332,4 +344,14 @@ static inline void fortify_panic(const char *name) kfunc_direct_call(fortify_panic, name); } +static inline int __must_check kstrtoull(const char *s, unsigned int base, unsigned long long *res) +{ + kfunc_direct_call(kstrtoull, s, base, res); +} + +static inline int __must_check kstrtoll(const char *s, unsigned int base, long long *res) +{ + kfunc_direct_call(kstrtoll, s, base, res); +} + #endif \ No newline at end of file diff --git a/kernel/linux/include/linux/uaccess.h b/kernel/linux/include/linux/uaccess.h index 4400e034..22230dbb 100644 --- a/kernel/linux/include/linux/uaccess.h +++ b/kernel/linux/include/linux/uaccess.h @@ -60,6 +60,4 @@ extern long kfunc_def(strnlen_user_nofault)(const void __user *unsafe_addr, long extern long kfunc_def(strnlen_unsafe_user)(const void __user *unsafe_addr, long count); extern long kfunc_def(strnlen_user)(const char __user *str, long n); -long compat_strncpy_from_user(char *dest, const char __user *src, long count); - #endif \ No newline at end of file diff --git a/kernel/patch/android/supercall.c b/kernel/patch/android/supercall.c deleted file mode 100644 index 413a6876..00000000 --- a/kernel/patch/android/supercall.c +++ /dev/null @@ -1,85 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2023 bmax121. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static long call_grant_uid(uid_t uid, struct su_profile *__user uprofile) -{ - struct su_profile *profile = memdup_user(uprofile, sizeof(struct su_profile)); - if (!profile || IS_ERR(profile)) return PTR_ERR(profile); - int rc = su_add_allow_uid(uid, profile, 1); - kvfree(profile); - return rc; -} - -static long call_revoke_uid(uid_t uid) -{ - return su_remove_allow_uid(uid, 1); -} - -static long call_su_allow_uid_nums() -{ - return su_allow_uid_nums(); -} - -static long call_su_list_allow_uid(uid_t *__user uids, int num) -{ - return su_allow_uids(uids, num); -} - -static long call_su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile) -{ - return su_allow_uid_profile(uid, uprofile); -} - -static long call_reset_su_path(const char *__user upath) -{ - char path[SU_PATH_MAX_LEN]; - compat_strncpy_from_user(path, upath, sizeof(path)); - return su_reset_path(path); -} - -static long call_su_get_path(char *__user ubuf, int buf_len) -{ - return su_get_path(ubuf, buf_len); -} - -long supercall_android(long cmd, long arg1, long arg2, long arg3) -{ - switch (cmd) { - case SUPERCALL_SU_GRANT_UID: - return call_grant_uid((uid_t)arg1, (struct su_profile * __user) arg2); - case SUPERCALL_SU_REVOKE_UID: - return call_revoke_uid((uid_t)arg1); - case SUPERCALL_SU_NUMS: - return call_su_allow_uid_nums(); - case SUPERCALL_SU_LIST: - return call_su_list_allow_uid((uid_t *)arg1, (int)arg2); - case SUPERCALL_SU_PROFILE: - return call_su_allow_uid_profile((uid_t)arg1, (struct su_profile * __user) arg2); - case SUPERCALL_SU_RESET_PATH: - return call_reset_su_path((const char *)arg1); - case SUPERCALL_SU_GET_PATH: - return call_su_get_path((char *__user)arg1, (int)arg2); - default: - break; - } - return -ENOSYS; -} diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index feb174c9..16c99253 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -35,7 +35,7 @@ static const void *kernel_read_file(const char *path, loff_t *len) { - set_priv_selinx_allow(current, 1); + set_priv_sel_allow(current, true); void *data = 0; struct file *filp = filp_open(path, O_RDONLY, 0); @@ -51,14 +51,14 @@ static const void *kernel_read_file(const char *path, loff_t *len) filp_close(filp, 0); out: - set_priv_selinx_allow(current, 0); + set_priv_sel_allow(current, false); return data; } static loff_t kernel_write_file(const char *path, const void *data, loff_t len, umode_t mode) { loff_t off = 0; - set_priv_selinx_allow(current, 1); + set_priv_sel_allow(current, true); struct file *fp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); if (!fp || IS_ERR(fp)) { @@ -75,48 +75,13 @@ static loff_t kernel_write_file(const char *path, const void *data, loff_t len, filp_close(fp, 0); out: - set_priv_selinx_allow(current, 0); + set_priv_sel_allow(current, false); return off; } -static loff_t kernel_write_exec(const char *path, const void *data, loff_t len) -{ - return kernel_write_file(path, data, len, 0744); -} - -static int extract_kpatch_call_back(const patch_extra_item_t *extra, const char *arg, const void *con, void *udata) -{ - const char *event = (const char *)udata; - if (extra->type == EXTRA_TYPE_EXEC && !strcmp("kpatch", extra->name)) { - loff_t size = kernel_write_exec(KPATCH_DEV_PATH, con, extra->con_size); - log_boot("%s extract kpatch size: %d\n", event, (long)size); - } - return 0; -} - -static void try_extract_kpatch(const char *event) -{ - set_priv_selinx_allow(current, 1); - struct file *fp = filp_open(KPATCH_DEV_PATH, O_RDONLY, 0); - if (!fp || IS_ERR(fp)) { - on_each_extra_item(extract_kpatch_call_back, (void *)event); - } else { - filp_close(fp, 0); - } - set_priv_selinx_allow(current, 0); -} - static void pre_user_exec_init() { log_boot("event: %s\n", EXTRA_EVENT_PRE_EXEC_INIT); - try_extract_kpatch(EXTRA_EVENT_PRE_EXEC_INIT); - - // struct file *work_dir = filp_open(KPATCH_DEV_WORK_DIR, O_DIRECTORY | O_CREAT, S_IRUSR); - // if (!work_dir || IS_ERR(work_dir)) { - // log_boot("creat work dir error: %s\n", KPATCH_DEV_WORK_DIR); - // return; - // } - // filp_close(work_dir, 0); } static void pre_init_second_stage() @@ -213,8 +178,8 @@ static void handle_after_execve(hook_local_t *hook_local) { int unhook = hook_local->data7; if (unhook) { - fp_unhook_syscall(__NR_execve, before_execve, after_execve); - fp_unhook_syscall(__NR_execveat, before_execveat, after_execveat); + unhook_syscalln(__NR_execve, before_execve, after_execve); + unhook_syscalln(__NR_execveat, before_execveat, after_execveat); } } @@ -253,30 +218,23 @@ static void after_execveat(hook_fargs5_t *args, void *udata) #define ORIGIN_RC_FILE "/system/etc/init/atrace.rc" #define REPLACE_RC_FILE "/dev/anduser.rc" +#define ADB_FLODER "/data/adb/" +#define AP_DIR "/data/adb/ap/" +#define AP_BIN_DIR AP_DIR "bin/" +#define AP_LOG_DIR AP_DIR "log/" + static const char user_rc_data[] = { // "\n" - "\n" - "on early-init\n" - " exec -- " SUPERCMD " %s " KPATCH_DEV_PATH " %s android_user early-init -k\n" - "on post-fs-data\n" - " exec -- " SUPERCMD " %s " KPATCH_DEV_PATH " %s android_user post-fs-data-init -k\n" - " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user post-fs-data-init -k\n" - " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user post-fs-data -k\n" - + " exec -- " SUPERCMD " %s exec " AP_BIN_DIR "magiskpolicy --live --magisk\n" + " exec -- " SUPERCMD " %s exec " APD_PATH " post-fs-data\n" "on nonencrypted\n" - " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user services -k\n" - + " exec -- " SUPERCMD " %s exec " APD_PATH " services\n" "on property:vold.decrypt=trigger_restart_framework\n" - " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user services -k\n" - + " exec -- " SUPERCMD " %s exec " APD_PATH " services\n" "on property:sys.boot_completed=1\n" - " rm " REPLACE_RC_FILE "\n" - " rm " KPATCH_DEV_PATH "\n" - " rm " EARLY_INIT_LOG_0 "\n" - " rm " EARLY_INIT_LOG_1 "\n" - " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user boot-completed -k\n" - "\n\n" + " exec -- " SUPERCMD " %s exec " APD_PATH " boot-completed\n" + "\n" "" }; @@ -322,7 +280,7 @@ static void before_openat(hook_fargs4_t *args, void *udata) char added_rc_data[2048]; const char *sk = get_superkey(); - sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk, sk, sk, sk, sk, sk, sk, sk, sk, sk); + sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk, sk); kernel_write(newfp, added_rc_data, strlen(added_rc_data), &off); if (off != strlen(added_rc_data) + ori_len) { @@ -358,7 +316,7 @@ static void after_openat(hook_fargs4_t *args, void *udata) log_boot("restore rc file: %x\n", args->local.data0); } if (args->local.data2) { - fp_unhook_syscall(__NR_openat, before_openat, after_openat); + unhook_syscalln(__NR_openat, before_openat, after_openat); } } @@ -386,7 +344,7 @@ static void before_input_handle_event(hook_fargs4_t *args, void *udata) } } -int kpuserd_init() +int android_user_init() { hook_err_t ret = 0; hook_err_t rc = HOOK_NO_ERR; diff --git a/kernel/patch/common/accctl.c b/kernel/patch/common/accctl.c index e8b345d2..58e6a8cf 100644 --- a/kernel/patch/common/accctl.c +++ b/kernel/patch/common/accctl.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -15,18 +16,19 @@ #include #include #include -#include #include #include #include +#include +#include +#include +#include +#include +#include -int set_priv_selinx_allow(struct task_struct *task, int val) -{ - struct task_ext *ext = get_task_ext(task); - ext->priv_selinux_allow = val; - dsb(ish); - return 0; -} +char all_allow_sctx[SUPERCALL_SCONTEXT_LEN] = { '\0' }; +int allow_sid_enable = 0; +uint32_t all_allow_sid = 0; static void su_cred(struct cred *cred, uid_t uid) { @@ -47,26 +49,38 @@ static void su_cred(struct cred *cred, uid_t uid) *(uid_t *)((uintptr_t)cred + cred_offset.sgid_offset) = uid; } -// int commit_kernel_cred() -// { -// int rc = 0; -// struct task_struct *task = current; -// struct task_ext *ext = get_task_ext(task); -// if (!task_ext_valid(ext)) goto out; - -// const struct cred *old = get_task_cred(task); -// struct cred *new = prepare_kernel_cred(0); -// u32 secid; -// if (kfunc(security_cred_getsecid)) { -// kfunc(security_cred_getsecid)(old, &secid); -// set_security_override(new, secid); -// } -// commit_creds(new); -// out: -// return rc; -// } +int set_all_allow_sctx(const char *sctx) +{ + if (!sctx || !sctx[0]) { + all_allow_sctx[0] = 0; + all_allow_sid = 0; + dsb(ish); + allow_sid_enable = 0; + dsb(ish); + logkfd("clear all allow sconetxt\n"); + return 0; + } -int commit_su(uid_t to_uid, const char *sctx) + int rc = security_secctx_to_secid(sctx, strlen(sctx), &all_allow_sid); + if (!rc) { + strncpy(all_allow_sctx, sctx, sizeof(all_allow_sctx) - 1); + all_allow_sctx[sizeof(all_allow_sctx) - 1] = '\0'; + dsb(ish); + allow_sid_enable = 1; + dsb(ish); + logkfd("set all allow sconetxt: %s, sid: %d\n", all_allow_sctx, all_allow_sid); + } + return rc; +} + +int commit_kernel_su() +{ + struct cred *new = prepare_kernel_cred(0); + set_security_override(new, all_allow_sid); + return commit_creds(new); +} + +int commit_common_su(uid_t to_uid, const char *sctx) { int rc = 0; struct task_struct *task = current; @@ -88,22 +102,33 @@ int commit_su(uid_t to_uid, const char *sctx) // seccomp_filter_release(task); } - ext->selinux_allow = 1; + ext->sel_allow = 1; struct cred *new = prepare_creds(); su_cred(new, to_uid); struct group_info *group_info = groups_alloc(0); set_groups(new, group_info); - if (sctx && sctx[0]) ext->selinux_allow = !!set_security_override_from_ctx(new, sctx); + if (sctx && sctx[0]) { + ext->sel_allow = !!set_security_override_from_ctx(new, sctx); + } commit_creds(new); out: logkfi("pid: %d, tgid: %d, to_uid: %d, sctx: %s, via_hook: %d\n", ext->pid, ext->tgid, to_uid, sctx, - ext->selinux_allow); + ext->sel_allow); return rc; } +int commit_su(uid_t to_uid, const char *sctx) +{ + if (unlikely(allow_sid_enable) && !to_uid) { + return commit_kernel_su(); + } else { + return commit_common_su(to_uid, sctx); + } +} + // todo: rcu int task_su(pid_t pid, uid_t to_uid, const char *sctx) { @@ -142,10 +167,94 @@ int task_su(pid_t pid, uid_t to_uid, const char *sctx) su_cred(real_cred, to_uid); if (sctx && sctx[0]) scontext_changed = scontext_changed && !set_security_override_from_ctx(real_cred, sctx); } - ext->priv_selinux_allow = !scontext_changed; + ext->priv_sel_allow = !scontext_changed; logkfi("pid: %d, tgid: %d, to_uid: %d, sctx: %s, via_hook: %d\n", ext->pid, ext->tgid, to_uid, sctx, - ext->priv_selinux_allow); + ext->priv_sel_allow); out: return rc; } + +static int (*avc_denied_backup)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, void *requested, + void *driver, void *xperm, void *flags, struct av_decision *avd) = 0; + +static int avc_denied_replace(struct selinux_state *_state, void *_ssid, void *_tsid, void *_tclass, void *_requested, + void *_driver, void *_xperm, void *_flags, struct av_decision *_avd) +{ + if (unlikely(allow_sid_enable)) { + u32 ssid = (u32)(u64)_ssid; + if ((uint64_t)_state <= 0xffffffffL) { + ssid = (u32)(u64)_state; + } + if (ssid == all_allow_sid) { + goto allow; + } + } + + struct task_ext *ext = get_current_task_ext(); + if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { + goto allow; + } + + int rc = avc_denied_backup(_state, _ssid, _tsid, _tclass, _requested, _driver, _xperm, _flags, _avd); + return rc; + +allow: + struct av_decision *avd = (struct av_decision *)_avd; + if ((uint64_t)_state <= 0xffffffffL) { + avd = (struct av_decision *)_flags; + } + avd->allowed = 0xffffffff; + avd->auditallow = 0; + avd->auditdeny = 0; + return 0; +} + +static int (*slow_avc_audit_backup)(struct selinux_state *_state, void *_ssid, void *_tsid, void *_tclass, + void *_requested, void *_audited, void *_denied, void *_result, + struct common_audit_data *_a) = 0; + +static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, void *_tsid, void *_tclass, + void *_requested, void *_audited, void *_denied, void *_result, + struct common_audit_data *_a) +{ + if (allow_sid_enable) { + u32 ssid = (u64)_ssid; + if ((uint64_t)_state <= 0xffffffffL) { + ssid = (u64)_state; + } + if (ssid == all_allow_sid) { + return 0; + } + } + + struct task_ext *ext = get_current_task_ext(); + if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { + return 0; + } + + int rc = slow_avc_audit_backup(_state, _ssid, _tsid, _tclass, _requested, _audited, _denied, _result, _a); + return rc; +} + +int bypass_selinux() +{ + unsigned long avc_denied_addr = get_preset_patch_sym()->avc_denied; + if (avc_denied_addr) { + hook_err_t err = hook((void *)avc_denied_addr, (void *)avc_denied_replace, (void **)&avc_denied_backup); + if (err != HOOK_NO_ERR) { + log_boot("hook avc_denied_addr: %llx, error: %d\n", avc_denied_addr, err); + } + } + + unsigned long slow_avc_audit_addr = get_preset_patch_sym()->slow_avc_audit; + if (slow_avc_audit_addr) { + hook_err_t err = + hook((void *)slow_avc_audit_addr, (void *)slow_avc_audit_replace, (void **)&slow_avc_audit_backup); + if (err != HOOK_NO_ERR) { + log_boot("hook slow_avc_audit: %llx, error: %d\n", slow_avc_audit_addr, err); + } + } + + return 0; +} diff --git a/kernel/patch/common/selinuxhook.c b/kernel/patch/common/selinuxhook.c.bak similarity index 94% rename from kernel/patch/common/selinuxhook.c rename to kernel/patch/common/selinuxhook.c.bak index 2a0ca50e..2e2329c8 100644 --- a/kernel/patch/common/selinuxhook.c +++ b/kernel/patch/common/selinuxhook.c.bak @@ -63,10 +63,10 @@ static void _selinux_debug(u32 ssid, u32 tsid, u16 tclass, u32 requested) log_boot("no symbol %s\n", #func); \ } -#define HOOK_AVC_RET_ZERO_BEFORE() \ - struct task_ext *ext = get_current_task_ext(); \ - if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { \ - return 0; \ +#define HOOK_AVC_RET_ZERO_BEFORE() \ + struct task_ext *ext = get_current_task_ext(); \ + if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { \ + return 0; \ } static int (*avc_denied_backup)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, void *requested, @@ -76,7 +76,7 @@ static int avc_denied_replace(struct selinux_state *_state, void *_ssid, void *_ void *_driver, void *_xperm, void *_flags, struct av_decision *_avd) { struct task_ext *ext = get_current_task_ext(); - if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { + if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { struct av_decision *avd = (struct av_decision *)_avd; if ((uint64_t)_state <= 0xffffffffL) { avd = (struct av_decision *)_flags; @@ -99,7 +99,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi struct common_audit_data *_a) { struct task_ext *ext = get_current_task_ext(); - if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { + if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { return 0; } int rc = slow_avc_audit_backup(_state, _ssid, _tsid, _tclass, _requested, _audited, _denied, _result, _a); @@ -123,7 +123,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi // // HOOK_AVC_RET_ZERO_BEFORE(); // struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { +// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { // struct av_decision *avd = (struct av_decision *)avd; // if (((uint64_t)state & 0xF000000000000000) != 0xF000000000000000) { // avd = (struct av_decision *)flags; @@ -197,7 +197,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi // if (!node) return node; // struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { +// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { // make_avc_node_all_perm(node); // } // return node; @@ -212,7 +212,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi // { // struct avc_node *node = hook_call_backup(avc_compute_av, _state, _ssid, _tsid, _tclass, _avd, _xp_node); // struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { +// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { // struct av_decision *avd = (struct av_decision *)_avd; // struct avc_xperms_node *xp_node = (struct avc_xperms_node *)_xp_node; // if ((uint64_t)_state <= 0xffffffffL) { @@ -241,7 +241,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi // hook_call_backup(security_compute_av, _state, _ssid, _tsid, _orig_tclass, _avd, _xperms); // struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { +// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { // struct av_decision *avd = (struct av_decision *)_avd; // struct extended_perms *xperms = (struct extended_perms *)_xperms; // if ((uint64_t)_state <= 0xffffffffL) { @@ -266,7 +266,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi // { // hook_call_backup(security_compute_xperms_decision, _state, _ssid, _tsid, _orig_tclass, _driver, _xpermd); // struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { +// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { // struct extended_perms_decision *xpermd = (struct extended_perms_decision *)_xpermd; // if ((uint64_t)_state <= 0xffffffffL) { // xpermd = (struct extended_perms_decision *)_driver; @@ -286,7 +286,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi // hook_call_backup(security_compute_av_user, _state, _ssid, _tsid, _tclass, _avd); // struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->selinux_allow || ext->priv_selinux_allow))) { +// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { // struct av_decision *avd = (struct av_decision *)_avd; // if ((uint64_t)_state <= 0xffffffffL) { // avd = (struct av_decision *)_tclass; diff --git a/kernel/patch/android/sucompat.c b/kernel/patch/common/sucompat.c similarity index 50% rename from kernel/patch/android/sucompat.c rename to kernel/patch/common/sucompat.c index 28dccbf6..06161c23 100644 --- a/kernel/patch/android/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -39,11 +40,15 @@ #include #include -static const char sh_path[] = ANDROID_SH_PATH; -static const char default_su_path[] = ANDROID_SU_PATH; -static const char legacy_su_path[] = ANDROID_LEGACY_SU_PATH; +const char sh_path[] = SH_PATH; +const char default_su_path[] = SU_PATH; + +#ifdef ANDROID +const char legacy_su_path[] = LEGACY_SU_PATH; +const char apd_path[] = APD_PATH; +#endif + static const char *current_su_path = 0; -static const char apd_path[] = APD_PATH; static struct list_head allow_uid_list; static spinlock_t list_lock; @@ -88,8 +93,10 @@ int is_su_allow_uid(uid_t uid) } KP_EXPORT_SYMBOL(is_su_allow_uid); -int su_add_allow_uid(uid_t uid, struct su_profile *profile, int async) +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, int async) { + if (!scontext) scontext = ""; + rcu_read_lock(); struct allow_uid *pos, *old = 0; list_for_each_entry(pos, &allow_uid_list, list) @@ -99,9 +106,12 @@ int su_add_allow_uid(uid_t uid, struct su_profile *profile, int async) break; } } + // todo: vmalloc -> kmalloc, gfp struct allow_uid *new = (struct allow_uid *)vmalloc(sizeof(struct allow_uid)); - new->uid = profile->uid; - memcpy(&new->profile, profile, sizeof(struct su_profile)); + new->uid = uid; + new->profile.uid = uid; + new->profile.to_uid = to_uid; + strncpy(new->profile.scontext, scontext, sizeof(new->profile.scontext)); new->profile.scontext[sizeof(new->profile.scontext) - 1] = '\0'; spin_lock(&list_lock); @@ -125,6 +135,7 @@ int su_add_allow_uid(uid_t uid, struct su_profile *profile, int async) } return 0; } +KP_EXPORT_SYMBOL(su_add_allow_uid); int su_remove_allow_uid(uid_t uid, int async) { @@ -148,6 +159,7 @@ int su_remove_allow_uid(uid_t uid, int async) spin_unlock(&list_lock); return 0; } +KP_EXPORT_SYMBOL(su_remove_allow_uid); int su_allow_uid_nums() { @@ -162,8 +174,9 @@ int su_allow_uid_nums() logkfd("%d\n", num); return num; } +KP_EXPORT_SYMBOL(su_allow_uid_nums); -int su_allow_uids(uid_t *__user uuids, int unum) +int su_allow_uids(int is_user, uid_t *out_uids, int out_num) { int rc = 0; int num = 0; @@ -171,17 +184,21 @@ int su_allow_uids(uid_t *__user uuids, int unum) struct allow_uid *pos; list_for_each_entry(pos, &allow_uid_list, list) { - if (num >= unum) { - goto out; - } + if (num >= out_num) goto out; + uid_t uid = pos->profile.uid; - int cplen = compat_copy_to_user(uuids + num, &uid, sizeof(uid)); - logkfd("uid: %d\n", uid); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; + if (is_user) { + int cplen = compat_copy_to_user(out_uids + num, &uid, sizeof(uid)); + logkfd("uid: %d\n", uid); + if (cplen <= 0) { + logkfd("compat_copy_to_user error: %d", cplen); + rc = cplen; + goto out; + } + } else { + out_uids[num] = uid; } + num++; } rc = num; @@ -189,8 +206,9 @@ int su_allow_uids(uid_t *__user uuids, int unum) rcu_read_unlock(); return rc; } +KP_EXPORT_SYMBOL(su_allow_uids); -int su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile) +int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile) { int rc = -ENOENT; rcu_read_lock(); @@ -198,12 +216,16 @@ int su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile) list_for_each_entry(pos, &allow_uid_list, list) { if (pos->profile.uid != uid) continue; - int cplen = compat_copy_to_user(uprofile, &pos->profile, sizeof(struct su_profile)); - logkfd("profile: %d %d %s\n", uid, pos->profile.to_uid, pos->profile.scontext); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; + if (is_user) { + int cplen = compat_copy_to_user(profile, &pos->profile, sizeof(struct su_profile)); + logkfd("profile: %d %d %s\n", uid, pos->profile.to_uid, pos->profile.scontext); + if (cplen <= 0) { + logkfd("compat_copy_to_user error: %d", cplen); + rc = cplen; + goto out; + } + } else { + memcpy(profile, &pos->profile, sizeof(struct su_profile)); } rc = 0; goto out; @@ -212,190 +234,31 @@ int su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile) rcu_read_unlock(); return rc; } +KP_EXPORT_SYMBOL(su_allow_uid_profile); // no free, no lock int su_reset_path(const char *path) { if (!path) return -EINVAL; - int len = strlen(path); - if (len <= 0) return -EINVAL; - char *new_su_path = vmalloc(len + 1); - if (!new_su_path) return -ENOMEM; - strcpy(new_su_path, path); - new_su_path[len] = '\0'; - current_su_path = new_su_path; - dsb(ishst); - logkfi("%s\n", current_su_path); + if (IS_ERR(path)) return PTR_ERR(path); + current_su_path = path; + logkfd("%s\n", current_su_path); + dsb(ish); return 0; } +KP_EXPORT_SYMBOL(su_reset_path); -int su_get_path(char *__user ubuf, int buf_len) -{ - if (!current_su_path) { - logkfi("null su path\n"); - current_su_path = default_su_path; - } - int len = strnlen(current_su_path, SU_PATH_MAX_LEN); - if (len <= 0) return -EINVAL; - if (buf_len < len) return -ENOBUFS; - logkfi("%s\n", current_su_path); - return compat_copy_to_user(ubuf, current_su_path, len + 1); -} - -// todo: rcu_dereference_protected -static uid_t current_uid() -{ - struct cred *cred = *(struct cred **)((uintptr_t)current + task_struct_offset.cred_offset); - uid_t uid = *(uid_t *)((uintptr_t)cred + cred_offset.uid_offset); - return uid; -} - -// #define SU_COMPAT_INLINE_HOOK - -#ifdef SU_COMPAT_INLINE_HOOK - -// int do_execveat_common(int fd, struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp, int flags) -// int __do_execve_file(int fd, struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp, int flags, -// struct file *file); -// static int do_execve_common(struct filename *filename, struct user_arg_ptr argv, struct user_arg_ptr envp) -static void before_do_execve(hook_fargs8_t *args, void *udata) -{ - struct filename *filename; - int filename_index = 1; - - if (udata && (((uintptr_t)args->arg0) & 0xF000000000000000) == 0xF000000000000000) { - // int, AT_FDCWD(ffffff9c) or fd - filename_index = 0; - } - - filename = (struct filename *)args->args[filename_index]; - if (!filename || IS_ERR(filename)) return; - - if (!strcmp(current_su_path, filename->name)) { - uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; - struct su_profile profile = profile_su_allow_uid(uid); - - uid_t to_uid = profile.to_uid; - const char *sctx = profile.scontext; - commit_su(to_uid, sctx); - - struct file *filp = filp_open(apd_path, O_RDONLY, 0); - if (!filp || IS_ERR(filp)) { - logkfi("call su uid: %d, to_uid: %d, sctx: %s\n", uid, to_uid, sctx); - strcpy((char *)filename->name, sh_path); - } else { - filp_close(filp, 0); - strcpy((char *)filename->name, apd_path); - int cplen = 0; - if (strcmp(legacy_su_path, filename->name)) { - const char *__user p0 = - get_user_arg_ptr((void *)args->args[filename_index + 1], (void *)args->args[filename_index + 2], 0); - cplen = compat_copy_to_user((char *__user)p0, legacy_su_path, sizeof(legacy_su_path)); - } - logkfi("call apd uid: %d, to_uid: %d, sctx: %s, cplen: %d\n", uid, to_uid, sctx, cplen); - } - } else if (!strcmp(SUPERCMD, filename->name)) { - void *ua0 = (void *)args->args[filename_index + 1]; - void *ua1 = (void *)args->args[filename_index + 2]; - - // key - const char __user *p1 = get_user_arg_ptr(ua0, ua1, 1); - if (IS_ERR(p1)) return; - - // auth skey - char arg1[SUPER_KEY_LEN]; - if (compat_strncpy_from_user(arg1, p1, sizeof(arg1)) <= 0) return; - if (auth_superkey(arg1)) return; - - commit_su(0, 0); - - // real command -#define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(*filename) - 128) // enough - - const char __user *p2 = get_user_arg_ptr(ua0, ua1, 2); - if (!p2 || IS_ERR(p2)) { - strcpy((char *)filename->name, sh_path); - } else { - compat_strncpy_from_user((char *)filename->name, p2, EMBEDDED_NAME_MAX); - } - logkfi("supercmd %s\n", filename->name); - - // shift args - args->args[filename_index + (has_config_compat ? 2 : 1)] += 2 * ((has_config_compat && ua0) ? 4 : 8); - } - return; -} - -// SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) -// SYSCALL_DEFINE4(faccessat2, int, dfd, const char __user *, filename, int, mode, int, flags) -static void before_faccessat(hook_fargs4_t *args, void *udata) +const char *su_get_path() { - uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; - - char __user *filename = (char __user *)syscall_argn(args, 1); - - char buf[SU_PATH_MAX_LEN]; - compat_strncpy_from_user(buf, filename, sizeof(buf)); - if (strcmp(current_su_path, buf)) return; - - logkfd("uid: %d\n", uid); - args->ret = 0; - args->skip_origin = 1; -} - -// SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename, struct stat __user *, statbuf, int, flag) -static void before_sysfstatat(hook_fargs4_t *args, void *udata) -{ - uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; - - char *__user filename = (char *__user)syscall_argn(args, 1); - - char buf[SU_PATH_MAX_LEN]; - compat_strncpy_from_user(buf, filename, sizeof(buf)); - if (!strcmp(current_su_path, buf)) { - void *__user uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); - if (uptr && !IS_ERR(uptr)) set_syscall_argn(args, 1, (uint64_t)uptr); - logkfd("uid: %d, %llx\n", uid, uptr); - } - return; + if (!current_su_path) current_su_path = default_su_path; + return current_su_path; } - -// int vfs_statx(int dfd, struct filename *filename, int flags, struct kstat *stat, u32 request_mask) -// int vfs_fstatat(int dfd, const char __user *filename, struct kstat *stat, int flags) -// int vfs_statx(int dfd, const char __user *filename, int flags, struct kstat *stat, u32 request_mask) -// static void before_stat(hook_fargs8_t *args, void *udata) -// { -// uid_t uid = current_uid(); -// if (!is_su_allow_uid(uid)) return; - -// if ((args->arg1 & 0xF000000000000000) == 0xF000000000000000) { -// struct filename *filename = (struct filename *)args->arg1; -// if (IS_ERR(filename)) return; -// if (!strcmp(current_su_path, filename->name)) { -// logkfd("0 uid: %d\n", uid); -// strcpy((char *)filename->name, sh_path); -// return; -// } -// } else { -// char __user *filename = (char __user *)args->arg1; -// char buf[SU_PATH_MAX_LEN]; -// compat_strncpy_from_user(buf, filename, sizeof(buf)); -// if (!strcmp(current_su_path, buf)) { -// void *__user uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); -// args->arg1 = (uint64_t)uptr; -// logkfd("1 uid: %d, %llx\n", uid, uptr); -// } -// return; -// } -// } - -#else // SU_COMPAT_INLINE_HOOK +KP_EXPORT_SYMBOL(su_get_path); // #define TRY_DIRECT_MODIFY_USER +#define INLINE_HOOK_SYSCALL + static void handle_before_execve(hook_local_t *hook_local, char **__user u_filename_p, char **__user uargv, void *udata) { #ifdef TRY_DIRECT_MODIFY_USER @@ -403,8 +266,6 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen hook_local->data0 = 0; #endif - void *is_compact = udata; - char __user *ufilename = *u_filename_p; char filename[SU_PATH_MAX_LEN]; int flen = compat_strncpy_from_user(filename, ufilename, sizeof(filename)); @@ -419,8 +280,10 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen const char *sctx = profile.scontext; commit_su(to_uid, sctx); +#ifdef ANDROID struct file *filp = filp_open(apd_path, O_RDONLY, 0); if (!filp || IS_ERR(filp)) { +#endif int cplen = 0; #ifdef TRY_DIRECT_MODIFY_USER cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); @@ -437,6 +300,8 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen } logkfi("call su uid: %d, to_uid: %d, sctx: %s, uptr: %llx\n", uid, to_uid, sctx, uptr); } + +#ifdef ANDROID } else { filp_close(filp, 0); @@ -464,7 +329,7 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen int argv_cplen = 0; if (strcmp(legacy_su_path, filename)) { #ifdef TRY_DIRECT_MODIFY_USER - const char __user *p1 = get_user_arg_ptr(is_compact, *uargv, 0); + const char __user *p1 = get_user_arg_ptr(0, *uargv, 0); argv_cplen = compat_copy_to_user((void *__user)p1, legacy_su_path, sizeof(legacy_su_path)); #endif if (argv_cplen <= 0) { @@ -473,7 +338,7 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen sp &= 0xFFFFFFFFFFFFFFF8; argv_cplen = compat_copy_to_user((void *)sp, legacy_su_path, sizeof(legacy_su_path)); if (argv_cplen > 0) { - int rc = set_user_arg_ptr(is_compact, *uargv, 0, sp); + int rc = set_user_arg_ptr(0, *uargv, 0, sp); if (rc < 0) { // todo: modify entire argv logkfi("call apd argv error, uid: %d, to_uid: %d, sctx: %s, rc: %d\n", uid, to_uid, sctx, rc); @@ -483,43 +348,10 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen } logkfi("call apd uid: %d, to_uid: %d, sctx: %s, cplen: %d, %d\n", uid, to_uid, sctx, cplen, argv_cplen); } - +#endif // ANDROID } else if (!strcmp(SUPERCMD, filename)) { - // key - const char __user *p1 = get_user_arg_ptr(is_compact, *uargv, 1); - if (!p1 || IS_ERR(p1)) return; - - // auth key - char arg1[SUPER_KEY_LEN]; - if (compat_strncpy_from_user(arg1, p1, sizeof(arg1)) <= 0) return; - if (auth_superkey(arg1)) return; - - commit_su(0, 0); - - // real command -#define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(*filename) - 128) // enough - - const char *exec = sh_path; - int exec_len = sizeof(sh_path); - const char __user *p2 = get_user_arg_ptr(is_compact, *uargv, 2); - - if (p1 && !IS_ERR(p2)) { - char buffer[EMBEDDED_NAME_MAX]; - int len = compat_strncpy_from_user(buffer, p2, EMBEDDED_NAME_MAX); - if (len >= 0) { - exec = buffer; - exec_len = len; - } - } - - int cplen = 0; -#ifdef TRY_DIRECT_MODIFY_USER - cplen = compat_copy_to_user(*u_filename_p, exec, exec_len); -#endif - if (cplen <= 0) *u_filename_p = copy_to_user_stack(exec, exec_len); - - // shift args - *uargv += 2 * (is_compact ? 4 : 8); + handle_supercmd(u_filename_p, uargv); + return; } } @@ -542,6 +374,7 @@ static void handle_after_execve(hook_local_t *hook_local) // https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2087 // SYSCALL_DEFINE3(execve, const char __user *, filename, const char __user *const __user *, argv, // const char __user *const __user *, envp) + static void before_execve(hook_fargs3_t *args, void *udata) { void *arg0p = syscall_argn_p(args, 0); @@ -568,7 +401,7 @@ static void after_execve(hook_fargs3_t *args, void *udata) // https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2095 // SYSCALL_DEFINE5(execveat, int, fd, const char __user *, filename, const char __user *const __user *, argv, // const char __user *const __user *, envp, int, flags) -static void before_execveat(hook_fargs5_t *args, void *udata) +__maybe_unused static void before_execveat(hook_fargs5_t *args, void *udata) { void *arg1p = syscall_argn_p(args, 1); void *arg2p = syscall_argn_p(args, 2); @@ -607,26 +440,28 @@ static void su_handler_arg1_ufilename_before(hook_fargs6_t *args, void *udata) uid_t uid = current_uid(); if (!is_su_allow_uid(uid)) return; - char __user *ufilename = (char __user *)syscall_argn(args, 1); + char __user **u_filename_p = (char __user **)syscall_argn_p(args, 1); + char filename[SU_PATH_MAX_LEN]; - int flen = compat_strncpy_from_user(filename, ufilename, sizeof(filename)); + int flen = compat_strncpy_from_user(filename, *u_filename_p, sizeof(filename)); if (flen <= 0) return; if (!strcmp(current_su_path, filename)) { int cplen = 0; #ifdef TRY_DIRECT_MODIFY_USER - cplen = compat_copy_to_user(ufilename, sh_path, sizeof(sh_path)); + cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); #endif if (cplen > 0) { args->local.data0 = cplen; - args->local.data1 = (uint64_t)ufilename; - // logkfi("su uid: %d, cp: %d\n", uid, cplen); + args->local.data1 = (uint64_t)*u_filename_p; + logkfi("su uid: %d, cp: %d\n", uid, cplen); } else { void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); if (uptr && !IS_ERR(uptr)) { - set_syscall_argn(args, 1, (uint64_t)uptr); + *u_filename_p = uptr; + } else { + logkfi("su uid: %d, cp stack error: %d\n", uid, uptr); } - // logkfi("su uid: %d, cp stack: %llx\n", uid, uptr); } } } @@ -643,8 +478,6 @@ static void su_handler_arg1_ufilename_after(hook_fargs6_t *args, void *udata) #define su_handler_arg1_ufilename_after 0 #endif -#endif // SU_COMPAT_INLINE_HOOK - int su_compat_init() { current_su_path = default_su_path; @@ -653,84 +486,44 @@ int su_compat_init() spin_lock_init(&list_lock); // default shell - struct su_profile default_allow_profile = { - .uid = 2000, - .to_uid = 0, - .scontext = ALL_ALLOW_SCONTEXT, - }; - su_add_allow_uid(default_allow_profile.uid, &default_allow_profile, 1); - - // default root - default_allow_profile.uid = 0; - su_add_allow_uid(default_allow_profile.uid, &default_allow_profile, 1); + su_add_allow_uid(2000, 0, all_allow_sctx, 1); + su_add_allow_uid(0, 0, all_allow_sctx, 1); hook_err_t rc = HOOK_NO_ERR; -#ifdef SU_COMPAT_INLINE_HOOK - - struct patch_symbol *symbol = get_preset_patch_sym(); - - if (symbol->do_execveat_common) { // [5.9.0, ) or [3.19, 4.19] - rc = hook_wrap8((void *)symbol->do_execveat_common, (void *)before_do_execve, 0, 0); - log_boot("hook do_execveat_common rc: %d\n", rc); - } else if (symbol->__do_execve_file) { // [4.19, 5.9) - rc = hook_wrap8((void *)symbol->__do_execve_file, (void *)before_do_execve, 0, 0); - log_boot("hook __do_execve_file rc: %d\n", rc); - } else if (symbol->do_execve_common) { // (, 3.19) - rc = hook_wrap8((void *)symbol->do_execve_common, (void *)before_do_execve, 0, (void *)1); - log_boot("hook do_execve_common rc: %d\n", rc); - } - - if (symbol->sys_faccessat) { - rc = hook_wrap4((void *)symbol->sys_faccessat, (void *)before_faccessat, 0, (void *)1); - log_boot("hook sys_faccessat rc: %d\n", rc); - } - if (symbol->sys_faccessat2) { - rc = hook_wrap4((void *)symbol->sys_faccessat2, (void *)before_faccessat, 0, (void *)1); - log_boot("hook sys_faccessat2 rc: %d\n", rc); - } - - if (symbol->sys_newfstatat) { - rc = hook_wrap4((void *)symbol->sys_newfstatat, (void *)before_sysfstatat, 0, (void *)1); - log_boot("hook sys_newfstatat rc: %d\n", rc); - } - -#else - - rc = fp_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)0); + rc = hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)0); log_boot("hook __NR_execve rc: %d\n", rc); - rc = fp_hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)0); - log_boot("hook __NR_execveat rc: %d\n", rc); + // rc = hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)0); + // log_boot("hook __NR_execveat rc: %d\n", rc); - rc = fp_hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)0); + rc = hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, + (void *)0); log_boot("hook __NR3264_fstatat rc: %d\n", rc); - rc = fp_hook_syscalln(__NR_statx, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - log_boot("hook __NR_statx rc: %d\n", rc); + // rc = hook_syscalln(__NR_statx, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + // log_boot("hook __NR_statx rc: %d\n", rc); - rc = fp_hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)0); + rc = hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); log_boot("hook __NR_faccessat rc: %d\n", rc); - rc = fp_hook_syscalln(__NR_faccessat2, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)0); - log_boot("hook __NR_faccessat2 rc: %d\n", rc); + // rc = + // hook_syscalln(__NR_faccessat2, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + // log_boot("hook __NR_faccessat2 rc: %d\n", rc); // #include // __NR_execve 11 - rc = fp_hook_compat_syscalln(11, 3, before_execve, after_execve, (void *)1); + rc = hook_compat_syscalln(11, 3, before_execve, after_execve, (void *)1); log_boot("hook 32 __NR_execve rc: %d\n", rc); // __NR_execveat 387 - rc = fp_hook_compat_syscalln(387, 5, before_execveat, after_execveat, (void *)1); - log_boot("hook 32 __NR_execveat rc: %d\n", rc); + // rc = hook_compat_syscalln(387, 5, before_execveat, after_execveat, (void *)1); + // log_boot("hook 32 __NR_execveat rc: %d\n", rc); // __NR_statx 397 - rc = fp_hook_compat_syscalln(397, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - log_boot("hook 32 __NR_statx rc: %d\n", rc); + // rc = hook_compat_syscalln(397, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + // log_boot("hook 32 __NR_statx rc: %d\n", rc); // #define __NR_stat 106 // #define __NR_lstat 107 @@ -738,18 +531,16 @@ int su_compat_init() // #define __NR_lstat64 196 // __NR_fstatat64 327 - rc = fp_hook_compat_syscalln(327, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + rc = hook_compat_syscalln(327, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); log_boot("hook 32 __NR_fstatat64 rc: %d\n", rc); // __NR_faccessat 334 - rc = fp_hook_compat_syscalln(334, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + rc = hook_compat_syscalln(334, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); log_boot("hook 32 __NR_faccessat rc: %d\n", rc); // __NR_faccessat2 439 - rc = fp_hook_compat_syscalln(439, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - log_boot("hook 32 __NR_faccessat2 rc: %d\n", rc); - -#endif + // rc = hook_compat_syscalln(439, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + // log_boot("hook 32 __NR_faccessat2 rc: %d\n", rc); - return rc; + return 0; } \ No newline at end of file diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 3d3bd33f..d512fd09 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #define MAX_KEY_LEN 128 @@ -178,7 +180,65 @@ static unsigned long call_pid_virt_to_phys(pid_t pid, uintptr_t vaddr) return pid_virt_to_phys(pid, vaddr); } -static long supercall(long cmd, long arg1, long arg2, long arg3, long arg4) +static long call_grant_uid(struct su_profile *__user uprofile) +{ + struct su_profile *profile = memdup_user(uprofile, sizeof(struct su_profile)); + if (!profile || IS_ERR(profile)) return PTR_ERR(profile); + int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext, 1); + kvfree(profile); + return rc; +} + +static long call_revoke_uid(uid_t uid) +{ + return su_remove_allow_uid(uid, 1); +} + +static long call_su_allow_uid_nums() +{ + return su_allow_uid_nums(); +} + +static long call_su_list_allow_uid(uid_t *__user uids, int num) +{ + return su_allow_uids(1, uids, num); +} + +static long call_su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile) +{ + return su_allow_uid_profile(1, uid, uprofile); +} + +static long call_reset_su_path(const char *__user upath) +{ + return su_reset_path(strndup_user(upath, SU_PATH_MAX_LEN)); +} + +static long call_su_get_path(char *__user ubuf, int buf_len) +{ + const char *path = su_get_path(); + int len = strlen(path); + if (buf_len <= len) return -ENOBUFS; + return compat_copy_to_user(ubuf, path, len + 1); +} + +static long call_su_get_allow_sctx(char *__user usctx, int ulen) +{ + int len = strlen(all_allow_sctx); + if (ulen <= len) return -ENOBUFS; + return compat_copy_to_user(usctx, all_allow_sctx, len + 1); +} + +static long call_su_set_allow_sctx(char *__user usctx) +{ + char buf[SUPERCALL_SCONTEXT_LEN]; + buf[0] = '\0'; + int len = compat_strncpy_from_user(buf, usctx, sizeof(buf)); + if (len >= SUPERCALL_SCONTEXT_LEN && buf[SUPERCALL_SCONTEXT_LEN - 1]) return -E2BIG; + return set_all_allow_sctx(buf); +} + +static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3, long arg4) { switch (cmd) { case SUPERCALL_HELLO: @@ -192,6 +252,47 @@ static long supercall(long cmd, long arg1, long arg2, long arg3, long arg4) return kver; } + switch (cmd) { + case SUPERCALL_SU: + return call_su((struct su_profile * __user) arg1); + case SUPERCALL_SU_TASK: + return call_su_task((pid_t)arg1, (struct su_profile * __user) arg2); + + case SUPERCALL_SU_GRANT_UID: + return call_grant_uid((struct su_profile * __user) arg1); + case SUPERCALL_SU_REVOKE_UID: + return call_revoke_uid((uid_t)arg1); + case SUPERCALL_SU_NUMS: + return call_su_allow_uid_nums(); + case SUPERCALL_SU_LIST: + return call_su_list_allow_uid((uid_t *)arg1, (int)arg2); + case SUPERCALL_SU_PROFILE: + return call_su_allow_uid_profile((uid_t)arg1, (struct su_profile * __user) arg2); + case SUPERCALL_SU_RESET_PATH: + return call_reset_su_path((const char *)arg1); + case SUPERCALL_SU_GET_PATH: + return call_su_get_path((char *__user)arg1, (int)arg2); + case SUPERCALL_SU_GET_ALLOW_SCTX: + return call_su_get_allow_sctx((char *__user)arg1, (int)arg2); + case SUPERCALL_SU_SET_ALLOW_SCTX: + return call_su_set_allow_sctx((char *__user)arg1); + default: + break; + } + + switch (cmd) { + case SUPERCALL_BOOTLOG: + return call_bootlog(); + case SUPERCALL_PANIC: + return call_panic(); + case SUPERCALL_TEST: + return call_test(arg1, arg2, arg3); + default: + break; + } + + if (!is_key_auth) return -EPERM; + switch (cmd) { case SUPERCALL_SKEY_GET: return call_skey_get((char *__user)arg1, (int)arg2); @@ -203,10 +304,6 @@ static long supercall(long cmd, long arg1, long arg2, long arg3, long arg4) } switch (cmd) { - case SUPERCALL_SU: - return call_su((struct su_profile * __user) arg1); - case SUPERCALL_SU_TASK: - return call_su_task((pid_t)arg1, (struct su_profile * __user) arg2); case SUPERCALL_KPM_LOAD: return call_kpm_load((const char *__user)arg1, (const char *__user)arg2, (void *__user)arg3); case SUPERCALL_KPM_UNLOAD: @@ -219,21 +316,16 @@ static long supercall(long cmd, long arg1, long arg2, long arg3, long arg4) return call_kpm_list((char *__user)arg1, (int)arg2); case SUPERCALL_KPM_INFO: return call_kpm_info((const char *__user)arg1, (char *__user)arg2, (int)arg3); + } + + switch (cmd) { case SUPERCALL_MEM_PHYS: return call_pid_virt_to_phys((pid_t)arg1, (uintptr_t)arg2); - - case SUPERCALL_BOOTLOG: - return call_bootlog(); - case SUPERCALL_PANIC: - return call_panic(); - case SUPERCALL_TEST: - return call_test(arg1, arg2, arg3); + default: + break; } -#ifdef ANDROID - return supercall_android(cmd, arg1, arg2, arg3); -#endif - return NO_SYSCALL; + return -ENOSYS; } static void before(hook_fargs6_t *args, void *udata) @@ -251,7 +343,17 @@ static void before(hook_fargs6_t *args, void *udata) char key[MAX_KEY_LEN]; long len = compat_strncpy_from_user(key, ukey, MAX_KEY_LEN); if (len <= 0) return; - if (auth_superkey(key)) return; + + int is_key_auth = 0; + + if (auth_superkey(key)) { + is_key_auth = 1; + } else if (!strcmp("su", key)) { + uid_t uid = current_uid(); + if (!is_su_allow_uid(uid)) return; + } else { + return; + } long a1 = (long)syscall_argn(args, 2); long a2 = (long)syscall_argn(args, 3); @@ -259,14 +361,14 @@ static void before(hook_fargs6_t *args, void *udata) long a4 = (long)syscall_argn(args, 5); args->skip_origin = 1; - args->ret = supercall(cmd, a1, a2, a3, a4); + args->ret = supercall(is_key_auth, cmd, a1, a2, a3, a4); } int supercall_install() { int rc = 0; - hook_err_t err = fp_hook_syscalln(__NR_supercall, 6, before, 0, 0); + hook_err_t err = hook_syscalln(__NR_supercall, 6, before, 0, 0); if (err) { log_boot("install supercall hook error: %d\n", err); rc = err; diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c new file mode 100644 index 00000000..090eb7ad --- /dev/null +++ b/kernel/patch/common/supercmd.c @@ -0,0 +1,405 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *__user supercmd_str_to_user_sp(const char *data, uintptr_t *sp) +{ + int len = strlen(data) + 1; + *sp -= len; + *sp &= 0xFFFFFFFFFFFFFFF8; + int cplen = compat_copy_to_user((void *)*sp, data, len); + if (cplen > 0) return (char *__user) * sp; + return 0; +} + +static void supercmd_exec(char **__user u_filename_p, const char *cmd, uintptr_t *sp) +{ + int cplen = 0; +#if 1 + cplen = compat_copy_to_user(*u_filename_p, cmd, strlen(cmd) + 1); +#endif + if (cplen <= 0) *u_filename_p = supercmd_str_to_user_sp(cmd, sp); +} + +static void supercmd_echo(char **__user u_filename_p, char **__user uargv, uintptr_t *sp, const char *fmt, ...) +{ + supercmd_exec(u_filename_p, ECHO_PATH, sp); + + char buffer[4096]; + va_list va; + va_start(va, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, va); + va_end(va); + + const char *__user cmd = supercmd_str_to_user_sp(ECHO_PATH, sp); + const char *__user argv1 = supercmd_str_to_user_sp(buffer, sp); + + set_user_arg_ptr(0, *uargv, 0, (uintptr_t)cmd); + set_user_arg_ptr(0, *uargv, 1, (uintptr_t)argv1); + set_user_arg_ptr(0, *uargv, 2, 0); +} + +static const char supercmd_help[] = + "" + "KernelPatch supercmd:\n" + "Usage: truncate [-uZc] [Command [[SubCommand]...]]\n" + "superkey|su: Authentication. For certain commands, if the current uid is allowed to use su,\n" + " the 'su' string can be used for authentication.\n" + "Options:\n" + " -u Change user id to UID.\n" + " -Z Change security context to SCONTEXT.\n" + "\n" + "Command:\n" + " help: Print this help message.\n" + " version: Print Kernel version and KernelPatch version,\n " + " eg: 50a0a,a06 means kernel version 5.10.10, KernelPatch version 0.10.6.\n" + " -c [...]: Pass a single COMMAND to the default shell.\n" + " exec [...]: Execute command with full PATH.\n" + " sumgr [...]: SU permission manager\n" + " The default command obtain a shell with the specified TO_UID and SCONTEXT is 'kp',\n" + " whose full PATH is '/system/bin/kp'. This can avoid conflicts with the existing 'su' command.\n" + " If you wish to modify this PATH, you can use the 'reset' command.\n" + " SubCommand:\n" + " grant [TO_UID] [SCONTEXT] Grant su permission to UID.\n" + " revoke Revoke su permission to UID.\n" + " num Get the number of uids with the aforementioned permissions.\n" + " list List all su allowed uids.\n" + " profile Get the profile of the uid configuration.\n" + " path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n" + " sctx [SCONTEXT] Get or Reset current all allowed security context, \n" + "\n" + "The command below requires superkey authentication.\n" + " module [...]: KernelPatch Module manager\n" + " SubCommand:\n" + " load [KPM_ARGS] Load module with KPM_PATH and KPM_ARGS.\n" + " ctl0 Control module named KPM_PATH with CTL_ARGS.\n" + " unload Unload module named KPM_NAME.\n" + " num Get the number of modules that have been loaded.\n" + " list List names of all loaded modules.\n" + " info Get detailed information about module named KPM_NAME.\n" + " key [...]: Superkey manager\n" + " SubCommand:\n" + " key [SUPERKEY]: Get or Reset current superkey\n" + " hash [enable|disable]: Whether to use hash to verify the root superkey.\n" + ""; + +void handle_supercmd(char **__user u_filename_p, char **__user uargv) +{ + int is_key_auth = 0; + + // key + const char __user *p1 = get_user_arg_ptr(0, *uargv, 1); + if (!p1 || IS_ERR(p1)) return; + + struct su_profile profile = { .to_uid = 0, .scontext = "" }; + + // auth key + char arg1[SUPER_KEY_LEN]; + if (compat_strncpy_from_user(arg1, p1, sizeof(arg1)) <= 0) return; + + if (!auth_superkey(arg1)) { + is_key_auth = 1; + } else if (!strcmp("su", arg1)) { + uid_t uid = current_uid(); + if (!is_su_allow_uid(uid)) return; + profile = profile_su_allow_uid(uid); + } else { + return; + } + +#define SUPERCMD_ARGS_NO 16 + + // args + const char *parr[SUPERCMD_ARGS_NO + 4] = { 0 }; + + for (int i = 2; i < SUPERCMD_ARGS_NO; i++) { + const char __user *ua = get_user_arg_ptr(0, *uargv, i); + if (!ua || IS_ERR(ua)) break; + const char *a = strndup_user(ua, 512); + if (IS_ERR(a)) break; + // ignore after -c or exec + if (a[0] == '-' && a[1] == 'c') break; + if (!strcmp("exec", a)) break; + parr[i] = a; + } + + uint64_t sp = current_user_stack_pointer(); + + // if no any more + if (!parr[2]) { + supercmd_exec(u_filename_p, sh_path, &sp); + const char *__user argv1 = supercmd_str_to_user_sp(sh_path, &sp); + set_user_arg_ptr(0, *uargv, 1, (uintptr_t)argv1); + *uargv += 1 * 8; + commit_su(profile.to_uid, profile.scontext); + return; + } + + int pi = 2; + + // options, contiguous + while (pi < SUPERCMD_ARGS_NO) { + const char *arg = parr[pi]; + if (!arg || arg[0] != '-') break; + // ignore -c + if (arg[0] == '-' && arg[1] == 'c') break; + char o = arg[1]; + pi++; + switch (o) { + case 'u': + if (parr[pi]) { + unsigned long long to_uid = profile.to_uid; + kstrtoull(parr[pi++], 10, &to_uid); + profile.to_uid = to_uid; + } else { + supercmd_echo(u_filename_p, uargv, &sp, "supercmd error: invalid to_uid"); + goto free; + } + break; + case 'Z': + if (parr[pi]) { + strncpy(profile.scontext, parr[pi++], sizeof(profile.scontext) - 1); + profile.scontext[sizeof(profile.scontext) - 1] = '\0'; + } else { + supercmd_echo(u_filename_p, uargv, &sp, "supercmd error: invalid scontext"); + goto free; + } + break; + default: + goto out_opt; + } + } + +out_opt: + + commit_su(profile.to_uid, profile.scontext); + + int rc = 0; + const char *msg = 0; + const char *err_msg = 0; + char buffer[4096]; + + // command + const char **carr = parr + pi; + const char *cmd = 0; + if (pi < SUPERCMD_ARGS_NO - 1) cmd = carr[0]; + if (!cmd) { + supercmd_exec(u_filename_p, sh_path, &sp); + *uargv += pi * 8; + goto free; + } + + if (!strcmp("help", cmd)) { + msg = supercmd_help; + } else if (!strcmp("-c", cmd)) { + supercmd_exec(u_filename_p, sh_path, &sp); + *uargv += (carr - parr - 1) * 8; + } else if (!strcmp("exec", cmd)) { + if (!carr[1]) { + err_msg = "invalid commmand path"; + goto echo; + } + supercmd_exec(u_filename_p, carr[1], &sp); + *uargv += 3 * 8; + } else if (!strcmp("version", cmd)) { + supercmd_echo(u_filename_p, uargv, &sp, "%x,%x", kver, kpver); + } else if (!strcmp("sumgr", cmd)) { + const char *sub_cmd = carr[1]; + if (!sub_cmd) sub_cmd = ""; + if (!strcmp(sub_cmd, "grant")) { + unsigned long long uid = 0, to_uid = 0; + const char *scontext = ""; + if (!carr[2] || kstrtoull(carr[2], 10, &uid)) { + supercmd_echo(u_filename_p, uargv, &sp, "supercmd error: illegal uid"); + goto free; + } + if (carr[3]) kstrtoull(carr[3], 10, &to_uid); + if (carr[4]) scontext = carr[4]; + su_add_allow_uid(uid, to_uid, scontext, 1); + supercmd_echo(u_filename_p, uargv, &sp, "supercmd: grant %d, %d, %s", uid, to_uid, scontext); + } else if (!strcmp(sub_cmd, "revoke")) { + const char *suid = carr[2]; + unsigned long long uid; + if (!suid || kstrtoull(suid, 10, &uid)) { + supercmd_echo(u_filename_p, uargv, &sp, "supercmd error: illegal uid"); + goto free; + } + su_remove_allow_uid(uid, 1); + msg = suid; + } else if (!strcmp(sub_cmd, "num")) { + int num = su_allow_uid_nums(); + supercmd_echo(u_filename_p, uargv, &sp, "%d", num); + } else if (!strcmp(sub_cmd, "list")) { + int num = su_allow_uid_nums(); + uid_t *uids = (uid_t *)buffer; + int offset = 0; + su_allow_uids(0, uids, num); + + char *msg_buf = buffer + num * sizeof(uid_t); + msg_buf[0] = '\0'; + for (int i = 0; i < num; i++) { + offset += sprintf(msg_buf + offset, "%d\n", uids[i]); + }; + if (offset > 0) msg_buf[offset - 1] = '\0'; + msg = msg_buf; + } else if (!strcmp(sub_cmd, "profile")) { + unsigned long long uid; + if (!carr[2] || kstrtoull(carr[2], 10, &uid)) { + err_msg = "invalid uid"; + goto echo; + } + struct su_profile *profile = (struct su_profile *)buffer; + rc = su_allow_uid_profile(0, uid, profile); + char *msg = buffer + sizeof(struct su_profile); + msg[0] = '\0'; + if (!rc) + sprintf(msg, "uid: %d, to_uid: %d, scontext: %s", profile->uid, profile->to_uid, profile->scontext); + } else if (!strcmp(sub_cmd, "path")) { + if (carr[2]) { + rc = su_reset_path(carr[2]); + msg = carr[2]; + carr[2] = 0; // no free + } else { + msg = su_get_path(); + } + } else if (!strcmp(sub_cmd, "sctx")) { + if (carr[2]) { + rc = set_all_allow_sctx(carr[2]); + if (!rc) msg = carr[2]; + } else { + msg = all_allow_sctx; + } + } else { + err_msg = "invalid subcommand"; + } + } else if (!strcmp("bootlog", cmd)) { + msg = get_boot_log(); + } else if (!strcmp("test", cmd)) { + void test(); + test(); + msg = "test done..."; + } else { + // superkey authrication command + const char *not_key_auth_err_msg = "superkey(not su) is required"; + if (!strcmp("key", cmd)) { + if (!is_key_auth) { + err_msg = not_key_auth_err_msg; + goto echo; + } + const char *sub_cmd = carr[1]; + if (!sub_cmd) sub_cmd = ""; + if (!strcmp("get", sub_cmd)) { + msg = get_superkey(); + } else if (!strcmp("set", sub_cmd)) { + const char *key = carr[2]; + if (!key) { + err_msg = "invalid new key"; + goto echo; + } + msg = key; + reset_superkey(key); + } else if (!strcmp("hash", sub_cmd)) { + const char *able = carr[2]; + if (!strcmp("enable", able) || !strcmp("disable", able)) { + msg = able; + enable_auth_root_key(1); + } else if (!strcmp("disable", able)) { + msg = able; + enable_auth_root_key(0); + } else { + err_msg = "enable or disable"; + } + } else { + err_msg = "invalid subcommand"; + } + } else if (!strcmp("module", cmd)) { + if (!is_key_auth) { + err_msg = not_key_auth_err_msg; + goto echo; + } + const char *sub_cmd = carr[1]; + if (!sub_cmd) sub_cmd = ""; + if (!strcmp("num", sub_cmd)) { + int num = get_module_nums(); + supercmd_echo(u_filename_p, uargv, &sp, "%d", num); + } else if (!strcmp("list", sub_cmd)) { + buffer[0] = '\0'; + list_modules(buffer, sizeof(buffer)); + msg = buffer; + } else if (!strcmp("load", sub_cmd)) { + const char *path = carr[2]; + if (!path) { + err_msg = "invalid module path"; + goto echo; + } + rc = load_module_path(path, carr[3], 0); + if (!rc) msg = path; + } else if (!strcmp("ctl0", sub_cmd)) { + const char *name = carr[2]; + if (!name) { + err_msg = "invalid module name"; + goto echo; + } + const char *mod_args = carr[3]; + if (!mod_args) { + err_msg = "invalid control arguments"; + goto echo; + } + buffer[0] = '\0'; + rc = module_control0(name, mod_args, buffer, sizeof(buffer)); + msg = buffer; + } else if (!strcmp("ctl1", sub_cmd)) { + err_msg = "not implement"; + } else if (!strcmp("unload", sub_cmd)) { + const char *name = carr[2]; + if (!name) { + err_msg = "invalid module name"; + goto echo; + } + rc = unload_module(name, 0); + if (!rc) msg = name; + } else if (!strcmp("info", sub_cmd)) { + const char *name = carr[2]; + if (!name) { + err_msg = "invalid module name"; + goto echo; + } + buffer[0] = '\0'; + int sz = get_module_info(name, buffer, sizeof(buffer)); + if (sz <= 0) rc = sz; + msg = buffer; + } else { + err_msg = "invalid subcommand"; + } + } else { + err_msg = "invalid command"; + } + } + +echo: + if (msg) supercmd_echo(u_filename_p, uargv, &sp, msg); + if (rc) supercmd_echo(u_filename_p, uargv, &sp, "supercmd error code: %d", rc); + if (err_msg) supercmd_echo(u_filename_p, uargv, &sp, "supercmd error message: %s", err_msg); + +free: + // free args + for (int i = 2; i < sizeof(parr) / sizeof(parr[0]); i++) { + const char *a = parr[i]; + if (!a) break; + kfree(a); + } +} diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index c83130b0..d8a6b7ca 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -18,6 +18,7 @@ #include #include #include +#include uintptr_t *sys_call_table = 0; KP_EXPORT_SYMBOL(sys_call_table); @@ -68,7 +69,7 @@ const char __user *get_user_arg_ptr(void *a0, void *a1, int nr) } else { uptr = (char __user *)(unsigned long)*(int32_t *)upptr; } - kvfree(upptr); + kfree(upptr); return uptr; } @@ -103,7 +104,8 @@ long raw_syscall0(long nr) uintptr_t addr = sys_call_table[nr]; if (has_syscall_wrapper) { struct pt_regs regs; - memset(®s, 0, sizeof(regs)); + regs.syscallno = nr; + regs.regs[8] = nr; return ((warp_raw_syscall_f)addr)(®s); } return ((raw_syscall0_f)addr)(); @@ -115,7 +117,9 @@ long raw_syscall1(long nr, long arg0) uintptr_t addr = sys_call_table[nr]; if (has_syscall_wrapper) { struct pt_regs regs; - memset(®s, 0, sizeof(regs)); + regs.syscallno = nr; + regs.regs[8] = nr; + regs.regs[0] = arg0; return ((warp_raw_syscall_f)addr)(®s); } return ((raw_syscall1_f)addr)(arg0); @@ -126,7 +130,8 @@ long raw_syscall2(long nr, long arg0, long arg1) uintptr_t addr = sys_call_table[nr]; if (has_syscall_wrapper) { struct pt_regs regs; - memset(®s, 0, sizeof(regs)); + regs.syscallno = nr; + regs.regs[8] = nr; regs.regs[0] = arg0; regs.regs[1] = arg1; return ((warp_raw_syscall_f)addr)(®s); @@ -139,7 +144,8 @@ long raw_syscall3(long nr, long arg0, long arg1, long arg2) uintptr_t addr = sys_call_table[nr]; if (has_syscall_wrapper) { struct pt_regs regs; - memset(®s, 0, sizeof(regs)); + regs.syscallno = nr; + regs.regs[8] = nr; regs.regs[0] = arg0; regs.regs[1] = arg1; regs.regs[2] = arg2; @@ -153,7 +159,8 @@ long raw_syscall4(long nr, long arg0, long arg1, long arg2, long arg3) uintptr_t addr = sys_call_table[nr]; if (has_syscall_wrapper) { struct pt_regs regs; - memset(®s, 0, sizeof(regs)); + regs.syscallno = nr; + regs.regs[8] = nr; regs.regs[0] = arg0; regs.regs[1] = arg1; regs.regs[2] = arg2; @@ -168,7 +175,8 @@ long raw_syscall5(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 uintptr_t addr = sys_call_table[nr]; if (has_syscall_wrapper) { struct pt_regs regs; - memset(®s, 0, sizeof(regs)); + regs.syscallno = nr; + regs.regs[8] = nr; regs.regs[0] = arg0; regs.regs[1] = arg1; regs.regs[2] = arg2; @@ -184,7 +192,8 @@ long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 uintptr_t addr = sys_call_table[nr]; if (has_syscall_wrapper) { struct pt_regs regs; - memset(®s, 0, sizeof(regs)); + regs.syscallno = nr; + regs.regs[8] = nr; regs.regs[0] = arg0; regs.regs[1] = arg1; regs.regs[2] = arg2; @@ -196,6 +205,36 @@ long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 return ((raw_syscall6_f)addr)(arg0, arg1, arg2, arg3, arg4, arg5); } +uintptr_t syscalln_name_addr(int nr, int is_compat) +{ + const char *name = 0; + if (!is_compat) { + name = syscall_name_table[nr]; + } else { + name = compat_syscall_name_table[nr]; + } + if (!name) return 0; + char buffer[128] = "__arm64_"; + strlcat(buffer, name, 64); + uintptr_t addr = kallsyms_lookup_name(buffer); + if (!addr) addr = kallsyms_lookup_name(name); + return addr; +} + +hook_err_t __inline_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) +{ + uintptr_t addr = syscalln_name_addr(nr, is_compat); + if (!addr) return -HOOK_BAD_ADDRESS; + if (has_syscall_wrapper) narg = 1; + return hook_wrap((void *)addr, narg, before, after, udata); +} + +void __inline_unhook_syscalln(int nr, int is_compat, void *before, void *after) +{ + uintptr_t addr = syscalln_name_addr(nr, is_compat); + hook_unwrap((void *)addr, before, after); +} + static uint64_t search_sys_call_table_addr() { uint64_t addr = kernel_va; @@ -249,18 +288,20 @@ static uint64_t search_sys_call_table_addr() return 0; } -int syscall_init() +void syscall_init() { - int rc = 0; - sys_call_table = (typeof(sys_call_table))kallsyms_lookup_name("sys_call_table"); - if (!sys_call_table) { - sys_call_table = (typeof(sys_call_table))search_sys_call_table_addr(); + for (int i = 0; i < sizeof(syscall_name_table) / sizeof(syscall_name_table[0]); i++) { + uintptr_t *addr = (uintptr_t *)syscall_name_table + i; + *addr = link2runtime(*addr); } - if (!sys_call_table) { - rc = -ENOENT; - log_boot("no symbol sys_call_table\n"); - goto out; + + for (int i = 0; i < sizeof(compat_syscall_name_table) / sizeof(compat_syscall_name_table[0]); i++) { + uintptr_t *addr = (uintptr_t *)compat_syscall_name_table + i; + *addr = link2runtime(*addr); } + + sys_call_table = (typeof(sys_call_table))kallsyms_lookup_name("sys_call_table"); + if (!sys_call_table) sys_call_table = (typeof(sys_call_table))search_sys_call_table_addr(); log_boot("sys_call_table addr: %llx\n", sys_call_table); compat_sys_call_table = (typeof(compat_sys_call_table))kallsyms_lookup_name("compat_sys_call_table"); @@ -282,9 +323,5 @@ int syscall_init() } log_boot("syscall config_compat: %d\n", has_config_compat); - log_boot("syscall has_wrapper: %d\n", has_syscall_wrapper); - -out: - return rc; } diff --git a/kernel/patch/common/sysname.c b/kernel/patch/common/sysname.c new file mode 100644 index 00000000..21e28f01 --- /dev/null +++ b/kernel/patch/common/sysname.c @@ -0,0 +1,712 @@ +#include + +const char *syscall_name_table[460] = { + [0] = "sys_io_setup", + [1] = "sys_io_destroy", + [2] = "sys_io_submit", + [3] = "sys_io_cancel", + [4] = "sys_io_getevents", + [5] = "sys_setxattr", + [6] = "sys_lsetxattr", + [7] = "sys_fsetxattr", + [8] = "sys_getxattr", + [9] = "sys_lgetxattr", + [10] = "sys_fgetxattr", + [11] = "sys_listxattr", + [12] = "sys_llistxattr", + [13] = "sys_flistxattr", + [14] = "sys_removexattr", + [15] = "sys_lremovexattr", + [16] = "sys_fremovexattr", + [17] = "sys_getcwd", + [19] = "sys_eventfd2", + [20] = "sys_epoll_create1", + [21] = "sys_epoll_ctl", + [22] = "sys_epoll_pwait", + [23] = "sys_dup", + [24] = "sys_dup3", + [25] = "sys_fcntl", + [26] = "sys_inotify_init1", + [27] = "sys_inotify_add_watch", + [28] = "sys_inotify_rm_watch", + [29] = "sys_ioctl", + [30] = "sys_ioprio_set", + [31] = "sys_ioprio_get", + [32] = "sys_flock", + [33] = "sys_mknodat", + [34] = "sys_mkdirat", + [35] = "sys_unlinkat", + [36] = "sys_symlinkat", + [37] = "sys_linkat", + [38] = "sys_renameat", + [39] = "sys_umount", + [40] = "sys_mount", + [41] = "sys_pivot_root", + [43] = "sys_statfs", + [44] = "sys_fstatfs", + [45] = "sys_truncate", + [46] = "sys_ftruncate", + [47] = "sys_fallocate", + [48] = "sys_faccessat", + [49] = "sys_chdir", + [50] = "sys_fchdir", + [51] = "sys_chroot", + [52] = "sys_fchmod", + [53] = "sys_fchmodat", + [54] = "sys_fchownat", + [55] = "sys_fchown", + [56] = "sys_openat", + [57] = "sys_close", + [58] = "sys_vhangup", + [59] = "sys_pipe2", + [60] = "sys_quotactl", + [61] = "sys_getdents64", + [62] = "sys_lseek", + [63] = "sys_read", + [64] = "sys_write", + [65] = "sys_readv", + [66] = "sys_writev", + [67] = "sys_pread64", + [68] = "sys_pwrite64", + [69] = "sys_preadv", + [70] = "sys_pwritev", + [71] = "sys_sendfile64", + [72] = "sys_pselect6", + [73] = "sys_ppoll", + [74] = "sys_signalfd4", + [75] = "sys_vmsplice", + [76] = "sys_splice", + [77] = "sys_tee", + [78] = "sys_readlinkat", + [79] = "sys_newfstatat", + [80] = "sys_newfstat", + [81] = "sys_sync", + [82] = "sys_fsync", + [83] = "sys_fdatasync", + [84] = "sys_sync_file_range", + [85] = "sys_timerfd_create", + [86] = "sys_timerfd_settime", + [87] = "sys_timerfd_gettime", + [88] = "sys_utimensat", + [89] = "sys_acct", + [90] = "sys_capget", + [91] = "sys_capset", + [92] = "sys_arm64_personality", + [93] = "sys_exit", + [94] = "sys_exit_group", + [95] = "sys_waitid", + [96] = "sys_set_tid_address", + [97] = "sys_unshare", + [98] = "sys_futex", + [99] = "sys_set_robust_list", + [100] = "sys_get_robust_list", + [101] = "sys_nanosleep", + [102] = "sys_getitimer", + [103] = "sys_setitimer", + [104] = "sys_kexec_load", + [105] = "sys_init_module", + [106] = "sys_delete_module", + [107] = "sys_timer_create", + [108] = "sys_timer_gettime", + [109] = "sys_timer_getoverrun", + [110] = "sys_timer_settime", + [111] = "sys_timer_delete", + [112] = "sys_clock_settime", + [113] = "sys_clock_gettime", + [114] = "sys_clock_getres", + [115] = "sys_clock_nanosleep", + [116] = "sys_syslog", + [117] = "sys_ptrace", + [118] = "sys_sched_setparam", + [119] = "sys_sched_setscheduler", + [120] = "sys_sched_getscheduler", + [121] = "sys_sched_getparam", + [122] = "sys_sched_setaffinity", + [123] = "sys_sched_getaffinity", + [124] = "sys_sched_yield", + [125] = "sys_sched_get_priority_max", + [126] = "sys_sched_get_priority_min", + [127] = "sys_sched_rr_get_interval", + [128] = "sys_restart_syscall", + [129] = "sys_kill", + [130] = "sys_tkill", + [131] = "sys_tgkill", + [132] = "sys_sigaltstack", + [133] = "sys_rt_sigsuspend", + [134] = "sys_rt_sigaction", + [135] = "sys_rt_sigprocmask", + [136] = "sys_rt_sigpending", + [137] = "sys_rt_sigtimedwait", + [138] = "sys_rt_sigqueueinfo", + [139] = "sys_rt_sigreturn", + [140] = "sys_setpriority", + [141] = "sys_getpriority", + [142] = "sys_reboot", + [143] = "sys_setregid", + [144] = "sys_setgid", + [145] = "sys_setreuid", + [146] = "sys_setuid", + [147] = "sys_setresuid", + [148] = "sys_getresuid", + [149] = "sys_setresgid", + [150] = "sys_getresgid", + [151] = "sys_setfsuid", + [152] = "sys_setfsgid", + [153] = "sys_times", + [154] = "sys_setpgid", + [155] = "sys_getpgid", + [156] = "sys_getsid", + [157] = "sys_setsid", + [158] = "sys_getgroups", + [159] = "sys_setgroups", + [160] = "sys_newuname", + [161] = "sys_sethostname", + [162] = "sys_setdomainname", + [163] = "sys_getrlimit", + [164] = "sys_setrlimit", + [165] = "sys_getrusage", + [166] = "sys_umask", + [167] = "sys_prctl", + [168] = "sys_getcpu", + [169] = "sys_gettimeofday", + [170] = "sys_settimeofday", + [171] = "sys_adjtimex", + [172] = "sys_getpid", + [173] = "sys_getppid", + [174] = "sys_getuid", + [175] = "sys_geteuid", + [176] = "sys_getgid", + [177] = "sys_getegid", + [178] = "sys_gettid", + [179] = "sys_sysinfo", + [180] = "sys_mq_open", + [181] = "sys_mq_unlink", + [182] = "sys_mq_timedsend", + [183] = "sys_mq_timedreceive", + [184] = "sys_mq_notify", + [185] = "sys_mq_getsetattr", + [186] = "sys_msgget", + [187] = "sys_msgctl", + [188] = "sys_msgrcv", + [189] = "sys_msgsnd", + [190] = "sys_semget", + [191] = "sys_semctl", + [192] = "sys_semtimedop", + [193] = "sys_semop", + [194] = "sys_shmget", + [195] = "sys_shmctl", + [196] = "sys_shmat", + [197] = "sys_shmdt", + [198] = "sys_socket", + [199] = "sys_socketpair", + [200] = "sys_bind", + [201] = "sys_listen", + [202] = "sys_accept", + [203] = "sys_connect", + [204] = "sys_getsockname", + [205] = "sys_getpeername", + [206] = "sys_sendto", + [207] = "sys_recvfrom", + [208] = "sys_setsockopt", + [209] = "sys_getsockopt", + [210] = "sys_shutdown", + [211] = "sys_sendmsg", + [212] = "sys_recvmsg", + [213] = "sys_readahead", + [214] = "sys_brk", + [215] = "sys_munmap", + [216] = "sys_mremap", + [217] = "sys_add_key", + [218] = "sys_request_key", + [219] = "sys_keyctl", + [220] = "sys_clone", + [221] = "sys_execve", + [222] = "sys_mmap", + [223] = "sys_fadvise64_64", + [224] = "sys_swapon", + [225] = "sys_swapoff", + [226] = "sys_mprotect", + [227] = "sys_msync", + [228] = "sys_mlock", + [229] = "sys_munlock", + [230] = "sys_mlockall", + [231] = "sys_munlockall", + [232] = "sys_mincore", + [233] = "sys_madvise", + [234] = "sys_remap_file_pages", + [235] = "sys_mbind", + [236] = "sys_get_mempolicy", + [237] = "sys_set_mempolicy", + [238] = "sys_migrate_pages", + [239] = "sys_move_pages", + [240] = "sys_rt_tgsigqueueinfo", + [241] = "sys_perf_event_open", + [242] = "sys_accept4", + [243] = "sys_recvmmsg", + [260] = "sys_wait4", + [261] = "sys_prlimit64", + [262] = "sys_fanotify_init", + [263] = "sys_fanotify_mark", + [264] = "sys_name_to_handle_at", + [265] = "sys_open_by_handle_at", + [266] = "sys_clock_adjtime", + [267] = "sys_syncfs", + [268] = "sys_setns", + [269] = "sys_sendmmsg", + [270] = "sys_process_vm_readv", + [271] = "sys_process_vm_writev", + [272] = "sys_kcmp", + [273] = "sys_finit_module", + [274] = "sys_sched_setattr", + [275] = "sys_sched_getattr", + [276] = "sys_renameat2", + [277] = "sys_seccomp", + [278] = "sys_getrandom", + [279] = "sys_memfd_create", + [280] = "sys_bpf", + [281] = "sys_execveat", + [282] = "sys_userfaultfd", + [283] = "sys_membarrier", + [284] = "sys_mlock2", + [285] = "sys_copy_file_range", + [286] = "sys_preadv2", + [287] = "sys_pwritev2", + [288] = "sys_pkey_mprotect", + [289] = "sys_pkey_alloc", + [290] = "sys_pkey_free", + [291] = "sys_statx", + [292] = "sys_io_pgetevents", + [293] = "sys_rseq", + [294] = "sys_kexec_file_load", + [424] = "sys_pidfd_send_signal", + [425] = "sys_io_uring_setup", + [426] = "sys_io_uring_enter", + [427] = "sys_io_uring_register", + [428] = "sys_open_tree", + [429] = "sys_move_mount", + [430] = "sys_fsopen", + [431] = "sys_fsconfig", + [432] = "sys_fsmount", + [433] = "sys_fspick", + [434] = "sys_pidfd_open", + [435] = "sys_clone3", + [436] = "sys_close_range", + [437] = "sys_openat2", + [438] = "sys_pidfd_getfd", + [439] = "sys_faccessat2", + [440] = "sys_process_madvise", + [441] = "sys_epoll_pwait2", + [442] = "sys_mount_setattr", + [443] = "sys_quotactl_fd", + [444] = "sys_landlock_create_ruleset", + [445] = "sys_landlock_add_rule", + [446] = "sys_landlock_restrict_self", + [447] = "sys_memfd_secret", + [448] = "sys_process_mrelease", + [449] = "sys_futex_waitv", + [450] = "sys_set_mempolicy_home_node", + [451] = "sys_cachestat", +}; +KP_EXPORT_SYMBOL(syscall_name_table); + +const char *compat_syscall_name_table[460] = { + [0] = "sys_restart_syscall", + [1] = "sys_exit", + [2] = "sys_fork", + [3] = "sys_read", + [4] = "sys_write", + [5] = "sys_open", + [6] = "sys_close", + [8] = "sys_creat", + [9] = "sys_link", + [10] = "sys_unlink", + [11] = "sys_execve", + [12] = "sys_chdir", + [14] = "sys_mknod", + [15] = "sys_chmod", + [16] = "sys_lchown16", + [19] = "sys_lseek", + [20] = "sys_getpid", + [21] = "sys_mount", + [23] = "sys_setuid16", + [24] = "sys_getuid16", + [26] = "sys_ptrace", + [29] = "sys_pause", + [33] = "sys_access", + [34] = "sys_nice", + [36] = "sys_sync", + [37] = "sys_kill", + [38] = "sys_rename", + [39] = "sys_mkdir", + [40] = "sys_rmdir", + [41] = "sys_dup", + [42] = "sys_pipe", + [43] = "sys_times", + [45] = "sys_brk", + [46] = "sys_setgid16", + [47] = "sys_getgid16", + [49] = "sys_geteuid16", + [50] = "sys_getegid16", + [51] = "sys_acct", + [52] = "sys_umount", + [54] = "sys_ioctl", + [55] = "sys_fcntl", + [57] = "sys_setpgid", + [60] = "sys_umask", + [61] = "sys_chroot", + [62] = "sys_ustat", + [63] = "sys_dup2", + [64] = "sys_getppid", + [65] = "sys_getpgrp", + [66] = "sys_setsid", + [67] = "sys_sigaction", + [70] = "sys_setreuid16", + [71] = "sys_setregid16", + [72] = "sys_sigsuspend", + [73] = "sys_sigpending", + [74] = "sys_sethostname", + [75] = "sys_setrlimit", + [77] = "sys_getrusage", + [78] = "sys_gettimeofday", + [79] = "sys_settimeofday", + [80] = "sys_getgroups16", + [81] = "sys_setgroups16", + [83] = "sys_symlink", + [85] = "sys_readlink", + [86] = "sys_uselib", + [87] = "sys_swapon", + [88] = "sys_reboot", + [91] = "sys_munmap", + [92] = "sys_truncate", + [93] = "sys_ftruncate", + [94] = "sys_fchmod", + [95] = "sys_fchown16", + [96] = "sys_getpriority", + [97] = "sys_setpriority", + [99] = "sys_statfs", + [100] = "sys_fstatfs", + [103] = "sys_syslog", + [104] = "sys_setitimer", + [105] = "sys_getitimer", + [106] = "sys_newstat", + [107] = "sys_newlstat", + [108] = "sys_newfstat", + [111] = "sys_vhangup", + [114] = "sys_wait4", + [115] = "sys_swapoff", + [116] = "sys_sysinfo", + [118] = "sys_fsync", + [119] = "sys_sigreturn", + [120] = "sys_clone", + [121] = "sys_setdomainname", + [122] = "sys_newuname", + [124] = "sys_adjtimex_time32", + [125] = "sys_mprotect", + [126] = "sys_sigprocmask", + [128] = "sys_init_module", + [129] = "sys_delete_module", + [131] = "sys_quotactl", + [132] = "sys_getpgid", + [133] = "sys_fchdir", + [135] = "sys_sysfs", + [136] = "sys_personality", + [138] = "sys_setfsuid16", + [139] = "sys_setfsgid16", + [140] = "sys_llseek", + [141] = "sys_getdents", + [142] = "sys_select", + [143] = "sys_flock", + [144] = "sys_msync", + [145] = "sys_readv", + [146] = "sys_writev", + [147] = "sys_getsid", + [148] = "sys_fdatasync", + [150] = "sys_mlock", + [151] = "sys_munlock", + [152] = "sys_mlockall", + [153] = "sys_munlockall", + [154] = "sys_sched_setparam", + [155] = "sys_sched_getparam", + [156] = "sys_sched_setscheduler", + [157] = "sys_sched_getscheduler", + [158] = "sys_sched_yield", + [159] = "sys_sched_get_priority_max", + [160] = "sys_sched_get_priority_min", + [161] = "sys_sched_rr_get_interval_time32", + [162] = "sys_nanosleep_time32", + [163] = "sys_mremap", + [164] = "sys_setresuid16", + [165] = "sys_getresuid16", + [168] = "sys_poll", + [170] = "sys_setresgid16", + [171] = "sys_getresgid16", + [172] = "sys_prctl", + [173] = "sys_rt_sigreturn", + [174] = "sys_rt_sigaction", + [175] = "sys_rt_sigprocmask", + [176] = "sys_rt_sigpending", + [177] = "sys_rt_sigtimedwait_time32", + [178] = "sys_rt_sigqueueinfo", + [179] = "sys_rt_sigsuspend", + [180] = "sys_aarch32_pread64", + [181] = "sys_aarch32_pwrite64", + [182] = "sys_chown16", + [183] = "sys_getcwd", + [184] = "sys_capget", + [185] = "sys_capset", + [186] = "sys_sigaltstack", + [187] = "sys_sendfile", + [190] = "sys_vfork", + [191] = "sys_getrlimit", + [192] = "sys_aarch32_mmap2", + [193] = "sys_aarch32_truncate64", + [194] = "sys_aarch32_ftruncate64", + [195] = "sys_stat64", + [196] = "sys_lstat64", + [197] = "sys_fstat64", + [198] = "sys_lchown", + [199] = "sys_getuid", + [200] = "sys_getgid", + [201] = "sys_geteuid", + [202] = "sys_getegid", + [203] = "sys_setreuid", + [204] = "sys_setregid", + [205] = "sys_getgroups", + [206] = "sys_setgroups", + [207] = "sys_fchown", + [208] = "sys_setresuid", + [209] = "sys_getresuid", + [210] = "sys_setresgid", + [211] = "sys_getresgid", + [212] = "sys_chown", + [213] = "sys_setuid", + [214] = "sys_setgid", + [215] = "sys_setfsuid", + [216] = "sys_setfsgid", + [217] = "sys_getdents64", + [218] = "sys_pivot_root", + [219] = "sys_mincore", + [220] = "sys_madvise", + [221] = "sys_fcntl64", + [224] = "sys_gettid", + [225] = "sys_aarch32_readahead", + [226] = "sys_setxattr", + [227] = "sys_lsetxattr", + [228] = "sys_fsetxattr", + [229] = "sys_getxattr", + [230] = "sys_lgetxattr", + [231] = "sys_fgetxattr", + [232] = "sys_listxattr", + [233] = "sys_llistxattr", + [234] = "sys_flistxattr", + [235] = "sys_removexattr", + [236] = "sys_lremovexattr", + [237] = "sys_fremovexattr", + [238] = "sys_tkill", + [239] = "sys_sendfile64", + [240] = "sys_futex_time32", + [241] = "sys_sched_setaffinity", + [242] = "sys_sched_getaffinity", + [243] = "sys_io_setup", + [244] = "sys_io_destroy", + [245] = "sys_io_getevents_time32", + [246] = "sys_io_submit", + [247] = "sys_io_cancel", + [248] = "sys_exit_group", + [250] = "sys_epoll_create", + [251] = "sys_epoll_ctl", + [252] = "sys_epoll_wait", + [253] = "sys_remap_file_pages", + [256] = "sys_set_tid_address", + [257] = "sys_timer_create", + [258] = "sys_timer_settime32", + [259] = "sys_timer_gettime32", + [260] = "sys_timer_getoverrun", + [261] = "sys_timer_delete", + [262] = "sys_clock_settime32", + [263] = "sys_clock_gettime32", + [264] = "sys_clock_getres_time32", + [265] = "sys_clock_nanosleep_time32", + [266] = "sys_aarch32_statfs64", + [267] = "sys_aarch32_fstatfs64", + [268] = "sys_tgkill", + [269] = "sys_utimes_time32", + [270] = "sys_aarch32_fadvise64_64", + [272] = "sys_pciconfig_read", + [273] = "sys_pciconfig_write", + [274] = "sys_mq_open", + [275] = "sys_mq_unlink", + [276] = "sys_mq_timedsend_time32", + [277] = "sys_mq_timedreceive_time32", + [278] = "sys_mq_notify", + [279] = "sys_mq_getsetattr", + [280] = "sys_waitid", + [281] = "sys_socket", + [282] = "sys_bind", + [283] = "sys_connect", + [284] = "sys_listen", + [285] = "sys_accept", + [286] = "sys_getsockname", + [287] = "sys_getpeername", + [288] = "sys_socketpair", + [289] = "sys_send", + [290] = "sys_sendto", + [291] = "sys_recv", + [292] = "sys_recvfrom", + [293] = "sys_shutdown", + [294] = "sys_setsockopt", + [295] = "sys_getsockopt", + [296] = "sys_sendmsg", + [297] = "sys_recvmsg", + [298] = "sys_semop", + [299] = "sys_semget", + [300] = "sys_old_semctl", + [301] = "sys_msgsnd", + [302] = "sys_msgrcv", + [303] = "sys_msgget", + [304] = "sys_old_msgctl", + [305] = "sys_shmat", + [306] = "sys_shmdt", + [307] = "sys_shmget", + [308] = "sys_old_shmctl", + [309] = "sys_add_key", + [310] = "sys_request_key", + [311] = "sys_keyctl", + [312] = "sys_semtimedop_time32", + [314] = "sys_ioprio_set", + [315] = "sys_ioprio_get", + [316] = "sys_inotify_init", + [317] = "sys_inotify_add_watch", + [318] = "sys_inotify_rm_watch", + [319] = "sys_mbind", + [320] = "sys_get_mempolicy", + [321] = "sys_set_mempolicy", + [322] = "sys_openat", + [323] = "sys_mkdirat", + [324] = "sys_mknodat", + [325] = "sys_fchownat", + [326] = "sys_futimesat_time32", + [327] = "sys_fstatat64", + [328] = "sys_unlinkat", + [329] = "sys_renameat", + [330] = "sys_linkat", + [331] = "sys_symlinkat", + [332] = "sys_readlinkat", + [333] = "sys_fchmodat", + [334] = "sys_faccessat", + [335] = "sys_pselect6_time32", + [336] = "sys_ppoll_time32", + [337] = "sys_unshare", + [338] = "sys_set_robust_list", + [339] = "sys_get_robust_list", + [340] = "sys_splice", + [341] = "sys_aarch32_sync_file_range2", + [342] = "sys_tee", + [343] = "sys_vmsplice", + [344] = "sys_move_pages", + [345] = "sys_getcpu", + [346] = "sys_epoll_pwait", + [347] = "sys_kexec_load", + [348] = "sys_utimensat_time32", + [349] = "sys_signalfd", + [350] = "sys_timerfd_create", + [351] = "sys_eventfd", + [352] = "sys_aarch32_fallocate", + [353] = "sys_timerfd_settime32", + [354] = "sys_timerfd_gettime32", + [355] = "sys_signalfd4", + [356] = "sys_eventfd2", + [357] = "sys_epoll_create1", + [358] = "sys_dup3", + [359] = "sys_pipe2", + [360] = "sys_inotify_init1", + [361] = "sys_preadv", + [362] = "sys_pwritev", + [363] = "sys_rt_tgsigqueueinfo", + [364] = "sys_perf_event_open", + [365] = "sys_recvmmsg_time32", + [366] = "sys_accept4", + [367] = "sys_fanotify_init", + [368] = "sys_fanotify_mark", + [369] = "sys_prlimit64", + [370] = "sys_name_to_handle_at", + [371] = "sys_open_by_handle_at", + [372] = "sys_clock_adjtime32", + [373] = "sys_syncfs", + [374] = "sys_sendmmsg", + [375] = "sys_setns", + [376] = "sys_process_vm_readv", + [377] = "sys_process_vm_writev", + [378] = "sys_kcmp", + [379] = "sys_finit_module", + [380] = "sys_sched_setattr", + [381] = "sys_sched_getattr", + [382] = "sys_renameat2", + [383] = "sys_seccomp", + [384] = "sys_getrandom", + [385] = "sys_memfd_create", + [386] = "sys_bpf", + [387] = "sys_execveat", + [388] = "sys_userfaultfd", + [389] = "sys_membarrier", + [390] = "sys_mlock2", + [391] = "sys_copy_file_range", + [392] = "sys_preadv2", + [393] = "sys_pwritev2", + [394] = "sys_pkey_mprotect", + [395] = "sys_pkey_alloc", + [396] = "sys_pkey_free", + [397] = "sys_statx", + [398] = "sys_rseq", + [399] = "sys_io_pgetevents", + [400] = "sys_migrate_pages", + [401] = "sys_kexec_file_load", + [403] = "sys_clock_gettime", + [404] = "sys_clock_settime", + [405] = "sys_clock_adjtime", + [406] = "sys_clock_getres", + [407] = "sys_clock_nanosleep", + [408] = "sys_timer_gettime", + [409] = "sys_timer_settime", + [410] = "sys_timerfd_gettime", + [411] = "sys_timerfd_settime", + [412] = "sys_utimensat", + [413] = "sys_pselect6_time64", + [414] = "sys_ppoll_time64", + [416] = "sys_io_pgetevents", + [417] = "sys_recvmmsg_time64", + [418] = "sys_mq_timedsend", + [419] = "sys_mq_timedreceive", + [420] = "sys_semtimedop", + [421] = "sys_rt_sigtimedwait_time64", + [422] = "sys_futex", + [423] = "sys_sched_rr_get_interval", + [424] = "sys_pidfd_send_signal", + [425] = "sys_io_uring_setup", + [426] = "sys_io_uring_enter", + [427] = "sys_io_uring_register", + [428] = "sys_open_tree", + [429] = "sys_move_mount", + [430] = "sys_fsopen", + [431] = "sys_fsconfig", + [432] = "sys_fsmount", + [433] = "sys_fspick", + [434] = "sys_pidfd_open", + [435] = "sys_clone3", + [436] = "sys_close_range", + [437] = "sys_openat2", + [438] = "sys_pidfd_getfd", + [439] = "sys_faccessat2", + [440] = "sys_process_madvise", + [441] = "sys_epoll_pwait2", + [442] = "sys_mount_setattr", + [443] = "sys_quotactl_fd", + [444] = "sys_landlock_create_ruleset", + [445] = "sys_landlock_add_rule", + [446] = "sys_landlock_restrict_self", + [448] = "sys_process_mrelease", + [449] = "sys_futex_waitv", + [450] = "sys_set_mempolicy_home_node", + [451] = "sys_cachestat", +}; +KP_EXPORT_SYMBOL(compat_syscall_name_table); diff --git a/kernel/patch/common/taskob.c b/kernel/patch/common/taskob.c index b41f079d..e82fa8e4 100644 --- a/kernel/patch/common/taskob.c +++ b/kernel/patch/common/taskob.c @@ -20,6 +20,7 @@ #include #include #include +#include static inline void prepare_init_ext(struct task_struct *task) { @@ -27,7 +28,9 @@ static inline void prepare_init_ext(struct task_struct *task) for (uintptr_t i = (uintptr_t)ext; i < (uintptr_t)ext + sizeof(struct task_ext); i += 8) { *(uintptr_t *)i = 0; } - ext->magic = TASK_EXT_MAGIC; + ext->size = task_ext_size; + ext->_magic = TASK_EXT_MAGIC; + dsb(ish); } static void prepare_task_ext(struct task_struct *new, struct task_struct *old) @@ -41,32 +44,29 @@ static void prepare_task_ext(struct task_struct *new, struct task_struct *old) for (uintptr_t i = (uintptr_t)new_ext; i < (uintptr_t)new_ext + sizeof(struct task_ext); i += 8) { *(uintptr_t *)i = 0; } - new_ext->magic = TASK_EXT_MAGIC; + new_ext->size = task_ext_size; + new_ext->_magic = TASK_EXT_MAGIC; new_ext->pid = __task_pid_nr_ns(new, PIDTYPE_PID, 0); new_ext->tgid = __task_pid_nr_ns(new, PIDTYPE_TGID, 0); - new_ext->selinux_allow = old_ext->selinux_allow; + new_ext->sel_allow = old_ext->sel_allow; - dsb(ishst); + dsb(ish); } -static struct task_struct *(*backup_copy_process)(void *a0, void *a1, void *a2, void *a3, void *a4, void *a5, void *a6, - void *a7) = 0; +int task_ext_size = (sizeof(struct task_ext) - sizeof(int)); +KP_EXPORT_SYMBOL(task_ext_size); -struct task_struct *replace_copy_process(void *a0, void *a1, void *a2, void *a3, void *a4, void *a5, void *a6, void *a7) +static void after_copy_process(hook_fargs8_t *args, void *udata) { - struct task_struct *new = backup_copy_process(a0, a1, a2, a3, a4, a5, a6, a7); - if (unlikely(!new || IS_ERR(new))) return new; + struct task_struct *new = (struct task_struct *)args->ret; + if (unlikely(!new || IS_ERR(new))) return; prepare_task_ext(new, current); - return new; } -static void (*backup_cgroup_post_fork)(struct task_struct *p, void *a1) = 0; - -static void replace_cgroup_post_fork(struct task_struct *p, void *a1) +static void after_cgroup_post_fork(hook_fargs4_t *args, void *udata) { - struct task_struct *new = p; - backup_cgroup_post_fork(p, a1); + struct task_struct *new = (struct task_struct *)args->arg0; prepare_task_ext(new, current); } @@ -76,32 +76,19 @@ int task_observer() prepare_init_ext(init_task); - // __switch_to unsigned long copy_process_addr = get_preset_patch_sym()->copy_process; if (copy_process_addr) { - hook_err_t err = hook((void *)copy_process_addr, (void *)replace_copy_process, (void **)&backup_copy_process); - if (err) { - log_boot("hook copy_process: %llx, error: %d\n", copy_process_addr, err); - rc = err; - goto out; - } + rc |= hook_wrap8((void *)copy_process_addr, 0, after_copy_process, 0); + log_boot("hook copy_process: %llx, rc: %d\n", copy_process_addr, rc); } else { - log_boot("no symbol copy_process, try cgroup_post_fork\n"); unsigned long cgroup_post_fork_addr = get_preset_patch_sym()->cgroup_post_fork; - if (!cgroup_post_fork_addr) { - log_boot("no symbol cgroup_post_fork\n"); - rc = -ENOENT; - goto out; - } - hook_err_t err = - hook((void *)cgroup_post_fork_addr, (void *)replace_cgroup_post_fork, (void **)&backup_cgroup_post_fork); - if (err != HOOK_NO_ERR) { - log_boot("hook cgroup_post_fork: %llx, error: %d\n", cgroup_post_fork_addr, err); - rc = err; - goto out; + if (cgroup_post_fork_addr) { + rc |= hook_wrap4((void *)cgroup_post_fork_addr, 0, after_cgroup_post_fork, 0); + log_boot("hook cgroup_post_fork: %llx, rc: %d\n", cgroup_post_fork_addr, rc); + } else { + rc = HOOK_BAD_ADDRESS; } } -out: return rc; } \ No newline at end of file diff --git a/kernel/patch/common/test.c b/kernel/patch/common/test.c new file mode 100644 index 00000000..6b4c054d --- /dev/null +++ b/kernel/patch/common/test.c @@ -0,0 +1,17 @@ +#include +#include +#include + +void test() +{ + logkd("=== start test ==="); + + const char *sctx = "u:r:kernel:s0"; + + uint32_t secid = 0; + int rc = security_secctx_to_secid(sctx, strlen(sctx), &secid); + + logkd("secid: %d, rc: %d\n", secid, rc); + + logkd("=== end test ==="); +} \ No newline at end of file diff --git a/kernel/patch/common/utils.c b/kernel/patch/common/utils.c index beff9dde..5b09302c 100644 --- a/kernel/patch/common/utils.c +++ b/kernel/patch/common/utils.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include extern int kfunc_def(xt_data_to_user)(void __user *dst, const void *src, int usersize, int size, int aligned_size); @@ -96,8 +98,6 @@ KP_EXPORT_SYMBOL(compat_copy_to_user); long compat_strncpy_from_user(char *dest, const char __user *src, long count) { - kfunc_call(strncpy_from_user_nofault, dest, src, count); - kfunc_call(strncpy_from_unsafe_user, dest, src, count); if (kfunc(strncpy_from_user)) { long rc = kfunc(strncpy_from_user)(dest, src, count); if (rc >= count) { @@ -108,6 +108,8 @@ long compat_strncpy_from_user(char *dest, const char __user *src, long count) } return rc; } + kfunc_call(strncpy_from_user_nofault, dest, src, count); + kfunc_call(strncpy_from_unsafe_user, dest, src, count); return 0; } KP_EXPORT_SYMBOL(compat_strncpy_from_user); @@ -123,15 +125,15 @@ struct pt_regs *_task_pt_reg(struct task_struct *task) } else { #ifndef ANDROID if (kver < VERSION(4, 4, 19)) { - addr -= sizeof(struct pt_regs_lt4419); + addr -= sizeof(struct pt_regs_lt4419); // 0x120 } else if (kver < VERSION(4, 14, 0)) { - addr -= sizeof(struct pt_regs_lt4140); + addr -= sizeof(struct pt_regs_lt4140); // 0x130 } else #endif if (kver < VERSION(5, 10, 0)) { - addr -= sizeof(struct pt_regs_lt5100); + addr -= sizeof(struct pt_regs_lt5100); // 0x140 } else { - addr -= sizeof(struct pt_regs); + addr -= sizeof(struct pt_regs); // 0x150 } } @@ -156,3 +158,12 @@ uint64_t get_random_u64(void) return rand_next(); } KP_EXPORT_SYMBOL(get_random_u64); + +// todo: rcu_dereference_protected +uid_t current_uid() +{ + struct cred *cred = *(struct cred **)((uintptr_t)current + task_struct_offset.cred_offset); + uid_t uid = *(uid_t *)((uintptr_t)cred + cred_offset.uid_offset); + return uid; +} +KP_EXPORT_SYMBOL(current_uid); \ No newline at end of file diff --git a/kernel/patch/include/accctl.h b/kernel/patch/include/accctl.h index 8e6960a9..f2607478 100644 --- a/kernel/patch/include/accctl.h +++ b/kernel/patch/include/accctl.h @@ -11,26 +11,39 @@ #include #include #include +#include +#include +#include -int set_priv_selinx_allow(struct task_struct *task, int val); -int commit_kernel_cred(); +extern char all_allow_sctx[SUPERCALL_SCONTEXT_LEN]; +extern int allow_sid_enable; +extern uint32_t all_allow_sid; + +int set_all_allow_sctx(const char *sctx); +int commit_kernel_su(); +int commit_common_su(uid_t to_uid, const char *sctx); int commit_su(uid_t uid, const char *sctx); int task_su(pid_t pid, uid_t to_uid, const char *sctx); -int selinux_hook_install(); -int supercall_install(); - -#ifdef ANDROID -int kpuserd_init(); -int su_compat_init(); -int su_add_allow_uid(uid_t uid, struct su_profile *profile, int async); +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, int async); int su_remove_allow_uid(uid_t uid, int async); int su_allow_uid_nums(); -int su_allow_uids(uid_t *__user uuids, int unum); -int su_allow_uid_profile(uid_t uid, struct su_profile *__user uprofile); +int su_allow_uids(int is_user, uid_t *out_uids, int out_num); +int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile); int su_reset_path(const char *path); -int su_get_path(char *__user ubuf, int buf_len); -long supercall_android(long cmd, long arg1, long arg2, long arg3); -#endif +const char *su_get_path(); + +/** + * @brief Whether to make the current task bypass all selinux permission checks. + * + * @param task + * @param val + */ +static inline void set_priv_sel_allow(struct task_struct *task, bool val) +{ + struct task_ext *ext = get_task_ext(task); + ext->priv_sel_allow = val; + dsb(ish); +} #endif \ No newline at end of file diff --git a/kernel/patch/include/kputils.h b/kernel/patch/include/kputils.h index 9e847efb..bed8e2e5 100644 --- a/kernel/patch/include/kputils.h +++ b/kernel/patch/include/kputils.h @@ -10,9 +10,9 @@ #include int __must_check compat_copy_to_user(void __user *to, const void *from, int n); - +long compat_strncpy_from_user(char *dest, const char __user *src, long count); void *__user copy_to_user_stack(const void *data, int len); - +uid_t current_uid(); uint64_t get_random_u64(void); void print_bootlog(); diff --git a/kernel/patch/include/module.h b/kernel/patch/include/module.h index dff41462..08e87555 100644 --- a/kernel/patch/include/module.h +++ b/kernel/patch/include/module.h @@ -62,6 +62,4 @@ int get_module_nums(); int list_modules(char *out_names, int size); int get_module_info(const char *name, char *out_info, int size); -int module_init(); - #endif \ No newline at end of file diff --git a/kernel/patch/include/sucompat.h b/kernel/patch/include/sucompat.h index f2277871..03a00bbd 100644 --- a/kernel/patch/include/sucompat.h +++ b/kernel/patch/include/sucompat.h @@ -8,6 +8,12 @@ #include #include +#include + +extern const char sh_path[]; +extern const char default_su_path[]; +extern const char legacy_su_path[]; +extern const char apd_path[]; struct allow_uid { @@ -20,4 +26,6 @@ struct allow_uid struct su_profile profile_su_allow_uid(uid_t uid); int is_su_allow_uid(uid_t uid); +void handle_supercmd(char **__user u_filename_p, char **__user uargv); + #endif diff --git a/kernel/patch/include/syscall.h b/kernel/patch/include/syscall.h index af024ea7..efa733c3 100644 --- a/kernel/patch/include/syscall.h +++ b/kernel/patch/include/syscall.h @@ -15,6 +15,8 @@ extern uintptr_t *sys_call_table; extern uintptr_t *compat_sys_call_table; extern int has_syscall_wrapper; +extern const char *syscall_name_table[460]; +extern const char *compat_syscall_name_table[460]; const char __user *get_user_arg_ptr(void *a0, void *a1, int nr); int set_user_arg_ptr(void *a0, void *a1, int nr, uintptr_t val); @@ -58,13 +60,15 @@ static inline void *syscall_argn_p(void *fdata_args, int n) static inline hook_err_t fp_hook_syscalln(int nr, int narg, void *before, void *after, void *udata) { + if (!sys_call_table) return HOOK_BAD_ADDRESS; uintptr_t fp_addr = (uintptr_t)(sys_call_table + nr); if (has_syscall_wrapper) narg = 1; return fp_hook_wrap(fp_addr, narg, before, after, udata); } -static inline void fp_unhook_syscall(int nr, void *before, void *after) +static inline void fp_unhook_syscalln(int nr, void *before, void *after) { + if (!sys_call_table) return; uintptr_t fp_addr = (uintptr_t)(sys_call_table + nr); fp_hook_unwrap(fp_addr, before, after); } @@ -77,7 +81,7 @@ static inline hook_err_t fp_hook_compat_syscalln(int nr, int narg, void *before, return fp_hook_wrap(fp_addr, narg, before, after, udata); } -static inline void fp_unhook_compat_syscall(int nr, void *before, void *after) +static inline void fp_unhook_compat_syscalln(int nr, void *before, void *after) { if (!compat_sys_call_table) return; uintptr_t fp_addr = (uintptr_t)(compat_sys_call_table + nr); @@ -85,38 +89,67 @@ static inline void fp_unhook_compat_syscall(int nr, void *before, void *after) } /* -xxx.cfi_jt example: -hint #0x22 +syscall table element: +sys_xxx.cfi_jt +hint #0x22 # bti c b #0xfffffffffeb452f4 */ + +/** + * @brief + * + * @param nr + * @param narg + * @param is_compat + * @param before + * @param after + * @param udata + * @return hook_err_t + */ +hook_err_t __inline_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata); + +/** + * @brief + * + * @param nr + * @param is_compat + * @param before + * @param after + */ +void __inline_unhook_syscalln(int nr, int is_compat, void *before, void *after); + static inline hook_err_t inline_hook_syscalln(int nr, int narg, void *before, void *after, void *udata) { - uintptr_t fp = sys_call_table[nr]; - if (has_syscall_wrapper) narg = 1; - return hook_wrap((void *)fp, narg, before, after, udata); + return __inline_hook_syscalln(nr, narg, 0, before, after, udata); } -static inline void inline_unhook_syscall(int nr, void *before, void *after) +static inline void inline_unhook_syscalln(int nr, void *before, void *after) { - uintptr_t fp = sys_call_table[nr]; - hook_unwrap((void *)fp, before, after); + __inline_unhook_syscalln(nr, 0, before, after); } static inline hook_err_t inline_hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) { - if (!compat_sys_call_table) return HOOK_BAD_ADDRESS; - uintptr_t fp = compat_sys_call_table[nr]; - if (has_syscall_wrapper) narg = 1; - return hook_wrap((void *)fp, narg, before, after, udata); + return __inline_hook_syscalln(nr, narg, 1, before, after, udata); } -static inline void inline_unhook_compat_syscall(int nr, void *before, void *after) +static inline void inline_unhook_compat_syscalln(int nr, void *before, void *after) { - if (!compat_sys_call_table) return; - uintptr_t fp = compat_sys_call_table[nr]; - hook_unwrap((void *)fp, before, after); + __inline_unhook_syscalln(nr, 0, before, after); } -int syscall_init(); +// #define DEFAULT_INLINE_HOOK_SYSCALL + +#ifdef DEFAULT_INLINE_HOOK_SYSCALL +#define hook_syscalln inline_hook_syscalln +#define unhook_syscalln inline_unhook_syscalln +#define hook_compat_syscalln inline_hook_compat_syscalln +#define unhook_compat_syscalln inline_unhook_compat_syscalln +#else +#define hook_syscalln fp_hook_syscalln +#define unhook_syscalln fp_unhook_syscalln +#define hook_compat_syscalln fp_hook_compat_syscalln +#define unhook_compat_syscalln fp_unhook_compat_syscalln +#endif #endif \ No newline at end of file diff --git a/kernel/patch/include/taskext.h b/kernel/patch/include/taskext.h index 901a0e09..06240e24 100644 --- a/kernel/patch/include/taskext.h +++ b/kernel/patch/include/taskext.h @@ -9,26 +9,91 @@ #include #include #include +#include +#include -#define TASK_EXT_MAGIC 0x1158115811581158 +#define TASK_EXT_MAGIC 0x11581158 +/// @brief the size of current struct task_ext, not included _magic +extern int task_ext_size; + +/** + * @brief An extension of task_struct, stored in the kernel thread stack, + * can be used to store task-local(thread-local) variables. + * This can be very useful if you need to pass thread-local variables across multiple hook points. + * + * Task-local variables can be dynamically expanded. + * @see reg_task_local + * @see has_task_local + * @see task_local_ptr + */ struct task_ext { // first + int size; pid_t pid; pid_t tgid; - int super; - int _; - int selinux_allow; - int priv_selinux_allow; - void *__; + bool root; + bool sel_allow; + bool priv_sel_allow; // last - uint64_t magic; + int _magic; }; -static inline int task_ext_valid(struct task_ext *ext) +/** + * @brief Is task_ext dirty, and is it available? + * + * @param ext + * @return int + */ +static inline bool task_ext_valid(struct task_ext *ext) +{ + return !IS_ERR(ext) && (*(int *)(ext->size + (uintptr_t)ext) == TASK_EXT_MAGIC); +} + +/** + * @brief Register a new task-local varilable + * + * @param size The size of task-local varilable + * @return The offset of of task-local varilable, + * This value is needed when access this task-local variable. + * + * @see has_task_local + * @see task_local_ptr + */ +static inline int reg_task_local(int size) +{ + int offset = task_ext_size; + task_ext_size += size; + return offset; +} + +/** + * @brief Is there a task-local variable regiseted? + * + * @param ext + * @param offset Return value of reg_task_local + * @return true + * @return false + * + * @see reg_task_local + */ +static inline bool has_task_local(struct task_ext *ext, int offset) +{ + return offset >= ext->size; +} + +/** + * @brief Access task-local varilable, + * + * @param offset Return value of reg_task_local + * @return void* Task-local varilable pointer + * + * @see reg_task_local + */ +static inline void *task_local_ptr(struct task_ext *ext, int offset) { - return ext && (ext->magic == TASK_EXT_MAGIC); + return (void *)((uintptr_t)ext + offset); } #endif diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 1126c79d..8db8ca88 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -6,15 +6,6 @@ #ifndef _KP_UAPI_SCDEF_H_ #define _KP_UAPI_SCDEF_H_ -static inline long hash_key(const char *key) -{ - long hash = 1000000007; - for (int i = 0; key[i]; i++) { - hash = hash * 31 + key[i]; - } - return hash; -} - #define SUPERCALL_HELLO_ECHO "hello1158" // #define __NR_supercall __NR3264_truncate // 45 @@ -63,40 +54,39 @@ struct su_profile }; #ifdef ANDROID - -#define ANDROID_SH_PATH "/system/bin/sh" -#define SU_PATH_MAX_LEN 128 - -#define ANDROID_SU_PATH "/system/bin/kp" -#define ANDROID_LEGACY_SU_PATH "/system/bin/su" -#define KPATCH_DATA_PATH "/data/adb/kpatch" -#define KPATCH_DEV_PATH "/dev/kpatch" -#define KPATCH_DEV_WORK_DIR "/dev/kp/" +#define SH_PATH "/system/bin/sh" +#define SU_PATH "/system/bin/kp" +#define LEGACY_SU_PATH "/system/bin/su" +#define ECHO_PATH "/system/bin/echo" #define KERNELPATCH_DATA_DIR "/data/adb/kp" #define KERNELPATCH_MODULE_DATA_DIR KERNELPATCH_DATA_DIR "/modules" #define APD_PATH "/data/adb/apd" +#define ALL_ALLOW_SCONTEXT "u:r:kp:s0" +#define ALL_ALLOW_SCONTEXT_MAGISK "u:r:magisk:s0" +#define ALL_ALLOW_SCONTEXT_KERNEL "u:r:kernel:s0" +#else +#define SH_PATH "/usr/bin/sh" +#define ECHO_PATH "/usr/bin/echo" +#define SU_PATH "/usr/bin/kp" +#define ALL_ALLOW_SCONTEXT "u:r:kernel:s0" +#endif + +#define SU_PATH_MAX_LEN 128 + #define SUPERCMD "/system/bin/truncate" -#define ADB_FLODER "/data/adb/" -#define APATCH_FLODER "/data/adb/ap/" -#define APATCH_BIN_FLODER APATCH_FLODER "bin/" -#define APATCH_LOG_FLODER APATCH_FLODER "log/" #define SAFE_MODE_FLAG_FILE "/dev/.safemode" -#define EARLY_INIT_LOG_0 "/dev/early_init_0.log" -#define EARLY_INIT_LOG_1 "/dev/early_init_1.log" - -#define ALL_ALLOW_SCONTEXT "u:r:magisk:s0" #define SUPERCALL_SU_GRANT_UID 0x1100 #define SUPERCALL_SU_REVOKE_UID 0x1101 #define SUPERCALL_SU_NUMS 0x1102 #define SUPERCALL_SU_LIST 0x1103 #define SUPERCALL_SU_PROFILE 0x1104 +#define SUPERCALL_SU_GET_ALLOW_SCTX 0x1105 +#define SUPERCALL_SU_SET_ALLOW_SCTX 0x1106 #define SUPERCALL_SU_GET_PATH 0x1110 #define SUPERCALL_SU_RESET_PATH 0x1111 -#endif - #define SUPERCALL_MAX 0x1200 #define SUPERCALL_RES_SUCCEED 0 diff --git a/kernel/patch/ksyms/execv.c b/kernel/patch/ksyms/execv.c index b58dfec1..7f32b54a 100644 --- a/kernel/patch/ksyms/execv.c +++ b/kernel/patch/ksyms/execv.c @@ -38,7 +38,7 @@ static void before_execve(hook_fargs3_t *args, void *udata) unsigned long stack = (unsigned long)get_stack(current); uintptr_t addr = (uintptr_t)(thread_size + stack); - for (uintptr_t i = addr - sizeof(struct pt_regs) - 0x40; i < addr - 31 * 8; i += 8) { + for (uintptr_t i = addr - sizeof(struct pt_regs) - 0x40; i < addr - 32 * 8; i += 0x10) { uintptr_t val0 = *(uintptr_t *)i; uintptr_t val1 = *(uintptr_t *)(i + 0x8); uintptr_t val2 = *(uintptr_t *)(i + 0x10); @@ -56,8 +56,8 @@ static void before_execve(hook_fargs3_t *args, void *udata) static void after_execv(hook_fargs5_t *args, void *udata) { - fp_unhook_syscall(__NR_execve, before_execve, after_execv); - fp_unhook_syscall(__NR_execveat, before_execve, after_execv); + unhook_syscalln(__NR_execve, before_execve, after_execv); + unhook_syscalln(__NR_execveat, before_execve, after_execv); } int resolve_pt_regs() @@ -65,11 +65,11 @@ int resolve_pt_regs() hook_err_t ret = 0; hook_err_t rc = HOOK_NO_ERR; - rc = fp_hook_syscalln(__NR_execve, 3, before_execve, after_execv, (void *)__NR_execve); + rc = hook_syscalln(__NR_execve, 3, before_execve, after_execv, (void *)__NR_execve); log_boot("hook __NR_execve rc: %d\n", rc); ret |= rc; - rc = fp_hook_syscalln(__NR_execveat, 5, before_execve, after_execv, (void *)__NR_execveat); + rc = hook_syscalln(__NR_execveat, 5, before_execve, after_execv, (void *)__NR_execveat); log_boot("hook __NR_execveat rc: %d\n", rc); ret |= rc; diff --git a/kernel/patch/ksyms/libs.c b/kernel/patch/ksyms/libs.c index 9e1c52e5..57bfd4c2 100644 --- a/kernel/patch/ksyms/libs.c +++ b/kernel/patch/ksyms/libs.c @@ -132,6 +132,11 @@ KP_EXPORT_SYMBOL(kfunc(strreplace)); void kfunc_def(fortify_panic)(const char *name) = 0; KP_EXPORT_SYMBOL(kfunc(fortify_panic)); +int __must_check kfunc_def(kstrtoull)(const char *s, unsigned int base, unsigned long long *res) = 0; +KP_EXPORT_SYMBOL(kfunc(kstrtoull)); +int __must_check kfunc_def(kstrtoll)(const char *s, unsigned int base, long long *res) = 0; +KP_EXPORT_SYMBOL(kfunc(kstrtoll)); + static void _linux_lib_string_sym_match(const char *name, unsigned long addr) { kfunc_match(strncasecmp, name, addr); @@ -178,6 +183,8 @@ static void _linux_lib_string_sym_match(const char *name, unsigned long addr) kfunc_match(memchr_inv, name, addr); kfunc_match(strreplace, name, addr); // kfunc_match(fortify_panic, name, addr); + kfunc_match(kstrtoull, name, addr); + kfunc_match(kstrtoll, name, addr); } // lib/argv_split.c @@ -246,7 +253,7 @@ static void _linux_include_kernel_sym_match(const char *name, unsigned long addr kfunc_match(vsscanf, name, addr); } -static int _linux_libs_symbol_init(void *data, const char *name, struct module *m, unsigned long addr) +static void _linux_libs_symbol_init(void *data, const char *name, struct module *m, unsigned long addr) { _linux_lib_misc(name, addr); _linux_lib_strncpy_from_user_sym_match(name, addr); @@ -254,15 +261,13 @@ static int _linux_libs_symbol_init(void *data, const char *name, struct module * _linux_lib_argv_split_sym_match(name, addr); _linux_lib_seq_buf_sym_match(name, addr); _linux_include_kernel_sym_match(name, addr); - return 0; } -int linux_libs_symbol_init(const char *name, unsigned long addr) +void linux_libs_symbol_init(const char *name, unsigned long addr) { #ifdef INIT_USE_KALLSYMS_LOOKUP_NAME _linux_libs_symbol_init(0, 0, 0, 0); #else kallsyms_on_each_symbol(_linux_libs_symbol_init, 0); #endif - return 0; } diff --git a/kernel/patch/ksyms/misc.c b/kernel/patch/ksyms/misc.c index ee759c15..6fa55e0e 100644 --- a/kernel/patch/ksyms/misc.c +++ b/kernel/patch/ksyms/misc.c @@ -274,16 +274,17 @@ struct page; struct address_space; struct task_struct; +char *kfunc_def(strndup_user)(const char __user *, long) = 0; +void *kfunc_def(memdup_user)(const void __user *, size_t) = 0; +void *kfunc_def(vmemdup_user)(const void __user *, size_t) = 0; +void *kfunc_def(memdup_user_nul)(const void __user *, size_t) = 0; + void kfunc_def(kfree_const)(const void *x) = 0; char *kfunc_def(kstrdup)(const char *s, gfp_t gfp) = 0; const char *kfunc_def(kstrdup_const)(const char *s, gfp_t gfp) = 0; char *kfunc_def(kstrndup)(const char *s, size_t max, gfp_t gfp) = 0; void *kfunc_def(kmemdup)(const void *src, size_t len, gfp_t gfp) = 0; char *kfunc_def(kmemdup_nul)(const char *s, size_t len, gfp_t gfp) = 0; -void *kfunc_def(memdup_user)(const void __user *src, size_t len) = 0; -void *kfunc_def(vmemdup_user)(const void __user *src, size_t len) = 0; -char *kfunc_def(strndup_user)(const char __user *s, long n) = 0; -void *kfunc_def(memdup_user_nul)(const void __user *src, size_t len) = 0; unsigned long kfunc_def(vm_mmap)(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset) = 0; void *kfunc_def(kvmalloc_node)(size_t size, gfp_t flags, int node) = 0; @@ -311,7 +312,7 @@ static void _linux_mm_utils_sym_match(const char *name, unsigned long addr) kfunc_match(memdup_user, name, addr); // kfunc_match(vmemdup_user, name, addr); kfunc_match(strndup_user, name, addr); - kfunc_match(memdup_user_nul, name, addr); + // kfunc_match(memdup_user_nul, name, addr); // kfunc_match(vm_mmap, name, addr); // kfunc_match(kvmalloc_node, name, addr); kfunc_match(kvfree, name, addr); @@ -669,6 +670,8 @@ int kfunc_def(cap_task_setscheduler)(struct task_struct *p) = 0; int kfunc_def(cap_task_setioprio)(struct task_struct *p, int ioprio) = 0; int kfunc_def(cap_task_setnice)(struct task_struct *p, int nice) = 0; int kfunc_def(cap_vm_enough_memory)(struct mm_struct *mm, long pages) = 0; +// int kfunc_def(security_secid_to_secctx)(u32 secid, char **secdata, u32 *seclen) = 0; +int kfunc_def(security_secctx_to_secid)(const char *secdata, u32 seclen, u32 *secid) = 0; kernel_cap_t full_cap = { 0 }; @@ -693,7 +696,8 @@ static void _linux_security_commoncap_sym_match(const char *name, unsigned long // kfunc_match(cap_task_setscheduler, name, addr); // kfunc_match(cap_task_setioprio, name, addr); // kfunc_match(cap_task_setnice, name, addr); - // kfunc_match(cap_vm_enough_memory, name, addr); + // kfunc_match(security_secid_to_secctx, name, addr); + kfunc_match(security_secctx_to_secid, name, addr); } #include @@ -855,12 +859,11 @@ static int _linux_misc_symbol_init(void *data, const char *name, struct module * return 0; } -int linux_misc_symbol_init() +void linux_misc_symbol_init() { #ifdef INIT_USE_KALLSYMS_LOOKUP_NAME _linux_misc_symbol_init(0, 0, 0, 0); #else kallsyms_on_each_symbol(_linux_misc_symbol_init, 0); #endif - return 0; } diff --git a/kernel/patch/module/module.c b/kernel/patch/module/module.c index ea1c2c1c..2c09fd2a 100644 --- a/kernel/patch/module/module.c +++ b/kernel/patch/module/module.c @@ -460,6 +460,7 @@ long load_module(const void *data, int len, const char *args, const char *event, // todo: lock long unload_module(const char *name, void *__user reserved) { + if (!name) return -EINVAL; logkfe("name: %s\n", name); rcu_read_lock(); @@ -490,6 +491,7 @@ long load_module_path(const char *path, const char *args, void *__user reserved) { long rc = 0; logkfd("%s\n", path); + if (!path) return -EINVAL; struct file *filp = filp_open(path, O_RDONLY, 0); if (unlikely(!filp || IS_ERR(filp))) { @@ -527,7 +529,7 @@ long load_module_path(const char *path, const char *args, void *__user reserved) long module_control0(const char *name, const char *ctl_args, char *__user out_msg, int outlen) { - if (!ctl_args) return -EINVAL; + if (!name || !ctl_args) return -EINVAL; int args_len = strlen(ctl_args); if (args_len <= 0) return -EINVAL; @@ -630,7 +632,7 @@ int list_modules(char *out_names, int size) { off += snprintf(out_names + off, size - 1 - off, "%s\n", pos->info.name); } - out_names[off] = '\0'; + if (off > 0) out_names[off - 1] = '\0'; rcu_read_unlock(); return off; @@ -653,15 +655,16 @@ int get_module_info(const char *name, char *out_info, int size) "args=%s\n", mod->info.name, mod->info.version, mod->info.license, mod->info.author, mod->info.description, mod->args); + + if (sz > 0) out_info[sz - 1] = '\0'; logkfd("%s", out_info); rcu_read_unlock(); return sz; } -int module_init() +void module_init() { INIT_LIST_HEAD(&modules.list); spin_lock_init(&module_lock); - return 0; } \ No newline at end of file diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 6681566b..d4093dfe 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -1,5 +1,3 @@ -#include "patch.h" - #include #include #include @@ -14,14 +12,6 @@ #include #include -int linux_misc_symbol_init(); -int linux_libs_symbol_init(); - -int resolve_struct(); -int task_observer(); -int bypass_kcfi(); -int resolve_pt_regs(); - void print_bootlog() { const char *log = get_boot_log(); @@ -48,60 +38,59 @@ void before_panic(hook_fargs12_t *args, void *udata) printk("==== End KernelPatch for Kernel panic ====\n"); } +int resolve_struct(); +int task_observer(); +int bypass_kcfi(); +int bypass_selinux(); +int resolve_pt_regs(); +int supercall_install(); +int su_compat_init(); + +int android_user_init(); + static void before_rest_init(hook_fargs4_t *args, void *udata) { int rc = 0; log_boot("entering init ...\n"); - if ((rc = linux_libs_symbol_init())) goto out; - log_boot("linux_libs_symbol_init done: %d\n", rc); - - if ((rc = linux_misc_symbol_init())) goto out; - log_boot("linux_misc_symbol_init done: %d\n", rc); - if ((rc = bypass_kcfi())) goto out; log_boot("bypass_kcfi done: %d\n", rc); - if ((rc = syscall_init())) goto out; - log_boot("syscall_init done: %d\n", rc); - if ((rc = resolve_struct())) goto out; log_boot("resolve_struct done: %d\n", rc); - if ((rc = selinux_hook_install())) goto out; - log_boot("selinux_hook_install done: %d\n", rc); + if ((rc = bypass_selinux())) goto out; + log_boot("bypass_selinux done: %d\n", rc); if ((rc = task_observer())) goto out; log_boot("task_observer done: %d\n", rc); - if ((rc = module_init())) goto out; - log_boot("module_init done: %d\n", rc); - rc = supercall_install(); log_boot("supercall_install done: %d\n", rc); + rc = su_compat_init(); + log_boot("su_compat_init done: %d\n", rc); + rc = resolve_pt_regs(); log_boot("resolve_pt_regs done: %d\n", rc); #ifdef ANDROID - rc = su_compat_init(); - log_boot("su_compat_init done: %d\n", rc); - rc = kpuserd_init(); - log_boot("kpuserd_init done: %d\n", rc); + rc = android_user_init(); + log_boot("android_user_init done: %d\n", rc); + #endif out: return; } -static int pre_kernel_init(const patch_extra_item_t *extra, const char *args, const void *data, void *udata) +static int extra_event_pre_kernel_init(const patch_extra_item_t *extra, const char *args, const void *data, void *udata) { - const char *event = (const char *)udata; if (extra->type == EXTRA_TYPE_KPM) { if (!strcmp(EXTRA_EVENT_PRE_KERNEL_INIT, extra->event) || !extra->event[0]) { - int rc = load_module(data, extra->con_size, args, event, 0); - log_boot("%s loading extra kpm return: %d\n", event, rc); + int rc = load_module(data, extra->con_size, args, EXTRA_EVENT_PRE_KERNEL_INIT, 0); + log_boot("load kpm: %s, rc: %d\n", extra->name, rc); } } return 0; @@ -110,7 +99,7 @@ static int pre_kernel_init(const patch_extra_item_t *extra, const char *args, co static void before_kernel_init(hook_fargs4_t *args, void *udata) { log_boot("event: %s\n", EXTRA_EVENT_PRE_KERNEL_INIT); - on_each_extra_item(pre_kernel_init, 0); + on_each_extra_item(extra_event_pre_kernel_init, 0); } static void after_kernel_init(hook_fargs4_t *args, void *udata) @@ -118,33 +107,44 @@ static void after_kernel_init(hook_fargs4_t *args, void *udata) log_boot("event: %s\n", EXTRA_EVENT_POST_KERNEL_INIT); } +// internal header +void linux_misc_symbol_init(); +void linux_libs_symbol_init(); +void module_init(); +void syscall_init(); + int patch() { - hook_err_t ret = 0; + linux_libs_symbol_init(); + linux_misc_symbol_init(); + module_init(); + syscall_init(); + + hook_err_t rc = 0; unsigned long panic_addr = get_preset_patch_sym()->panic; + logkd("panic addr: %llx\n", panic_addr); if (panic_addr) { - hook_err_t rc = hook_wrap12((void *)panic_addr, before_panic, 0, 0); + rc = hook_wrap12((void *)panic_addr, before_panic, 0, 0); log_boot("hook panic rc: %d\n", rc); - ret |= rc; } + if (rc) return rc; // rest_init or cgroup_init unsigned long init_addr = get_preset_patch_sym()->rest_init; if (!init_addr) init_addr = get_preset_patch_sym()->cgroup_init; if (init_addr) { - hook_err_t rc = hook_wrap4((void *)init_addr, before_rest_init, 0, (void *)init_addr); + rc = hook_wrap4((void *)init_addr, before_rest_init, 0, (void *)init_addr); log_boot("hook rest_init rc: %d\n", rc); - ret |= rc; } + if (rc) return rc; // kernel_init unsigned long kernel_init_addr = get_preset_patch_sym()->kernel_init; if (kernel_init_addr) { - hook_err_t rc = hook_wrap4((void *)kernel_init_addr, before_kernel_init, after_kernel_init, 0); + rc = hook_wrap4((void *)kernel_init_addr, before_kernel_init, after_kernel_init, 0); log_boot("hook kernel_init rc: %d\n", rc); - ret |= rc; } - return ret; + return rc; } diff --git a/kernel/patch/patch.h b/kernel/patch/patch.h deleted file mode 100644 index 8b0adf6c..00000000 --- a/kernel/patch/patch.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _KP_PATCH_H_ -#define _KP_PATCH_H_ - -int patch(); - -#endif \ No newline at end of file diff --git a/kpms/demo-syscallhook/syscallhook.c b/kpms/demo-syscallhook/syscallhook.c index a4b78af5..2719f496 100644 --- a/kpms/demo-syscallhook/syscallhook.c +++ b/kpms/demo-syscallhook/syscallhook.c @@ -10,6 +10,7 @@ #include #include #include +#include #include KPM_NAME("kpm-syscall-hook-demo"); @@ -119,10 +120,10 @@ static long syscall_hook_demo_exit(void *__user reserved) pr_info("kpm-syscall-hook-demo exit ...\n"); if (hook_type == INLINE_CHAIN) { - inline_unhook_syscall(__NR_openat, before_openat_0, 0); + inline_unhook_syscalln(__NR_openat, before_openat_0, 0); } else if (hook_type == FUNCTION_POINTER_CHAIN) { - fp_unhook_syscall(__NR_openat, before_openat_0, 0); - fp_unhook_syscall(__NR_openat, before_openat_1, after_openat_1); + fp_unhook_syscalln(__NR_openat, before_openat_0, 0); + fp_unhook_syscalln(__NR_openat, before_openat_1, after_openat_1); } else { } return 0; diff --git a/tools/kptools.c b/tools/kptools.c index af14d8d2..99f60c2b 100644 --- a/tools/kptools.c +++ b/tools/kptools.c @@ -90,7 +90,6 @@ int main(int argc, char *argv[]) { "skey-hash", required_argument, NULL, 'S' }, { "out", required_argument, NULL, 'o' }, { "addition", required_argument, NULL, 'a' }, - { "kpatch", required_argument, NULL, 'K' }, { "embed-extra-path", required_argument, NULL, 'M' }, { "embeded-extra-name", required_argument, NULL, 'E' }, @@ -99,13 +98,12 @@ int main(int argc, char *argv[]) { "extra-event", required_argument, NULL, 'V' }, { "extra-args", required_argument, NULL, 'A' }, { 0, 0, 0, 0 } }; - char *optstr = "hvpurdli:s:S:k:o:a:K:M:E:T:N:V:A:"; + char *optstr = "hvpurdli:s:S:k:o:a:M:E:T:N:V:A:"; char *kimg_path = NULL; char *kpimg_path = NULL; char *out_path = NULL; char *superkey = NULL; - char *kpatch_path = NULL; bool root_skey = false; int additional_num = 0; @@ -148,9 +146,6 @@ int main(int argc, char *argv[]) case 'a': additional[additional_num++] = optarg; break; - case 'K': - kpatch_path = optarg; - break; case 'M': config = &extra_configs[extra_config_num++]; config->is_path = true; @@ -190,8 +185,8 @@ int main(int argc, char *argv[]) else fprintf(stdout, "%x\n", version); } else if (cmd == 'p') { - ret = patch_update_img(kimg_path, kpimg_path, out_path, superkey, root_skey, additional, kpatch_path, - extra_configs, extra_config_num); + ret = patch_update_img(kimg_path, kpimg_path, out_path, superkey, root_skey, additional, extra_configs, + extra_config_num); } else if (cmd == 'd') { ret = dump_kallsym(kimg_path); } else if (cmd == 'u') { diff --git a/tools/patch.c b/tools/patch.c index f9a5ba5f..bc981db6 100644 --- a/tools/patch.c +++ b/tools/patch.c @@ -337,8 +337,7 @@ static void extra_append(char *kimg, const void *data, int len, int *offset) } int patch_update_img(const char *kimg_path, const char *kpimg_path, const char *out_path, const char *superkey, - bool root_key, const char **additional, const char *kpatch_path, extra_config_t *extra_configs, - int extra_config_num) + bool root_key, const char **additional, extra_config_t *extra_configs, int extra_config_num) { set_log_enable(true); @@ -372,18 +371,6 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * int kpimg_len = 0; read_file_align(kpimg_path, &kpimg, &kpimg_len, 0x10); - // embed kpatch executable - if (kpatch_path) { - // add new - extra_config_t *config = extra_configs + extra_config_num; - extra_config_num++; - config->extra_type = EXTRA_TYPE_EXEC; - config->is_path = true; - config->path = kpatch_path; - config->priority = __INT32_MAX__; - config->set_name = "kpatch"; - } - // extra int extra_size = 0; int extra_num = 0; diff --git a/tools/patch.h b/tools/patch.h index d2443e67..0882b457 100644 --- a/tools/patch.h +++ b/tools/patch.h @@ -69,8 +69,7 @@ uint32_t get_kpimg_version(const char *kpimg_path); int extra_str_type(const char *extra_str); const char *extra_type_str(extra_item_type extra_type); int patch_update_img(const char *kimg_path, const char *kpimg_path, const char *out_path, const char *superkey, - bool root_skey, const char **additional, const char *kpatch_path, extra_config_t *extra_configs, - int extra_config_num); + bool root_skey, const char **additional, extra_config_t *extra_configs, int extra_config_num); int unpatch_img(const char *kimg_path, const char *out_path); int reset_key(const char *kimg_path, const char *out_path, const char *key); int dump_kallsym(const char *kimg_path); diff --git a/tools/symbol.c b/tools/symbol.c index 4513a9cc..d3787b90 100644 --- a/tools/symbol.c +++ b/tools/symbol.c @@ -120,27 +120,6 @@ int fillin_patch_symbol(kallsym_t *kallsym, char *img_buf, int imglen, patch_sym if (!symbol->copy_process) symbol->cgroup_post_fork = get_symbol_offset_zero(kallsym, img_buf, "cgroup_post_fork"); if (!symbol->copy_process && !symbol->cgroup_post_fork) tools_loge_exit("no symbol copy_process"); - symbol->do_execveat_common = try_get_symbol_offset_zero(kallsym, img_buf, "do_execveat_common"); - symbol->__do_execve_file = try_get_symbol_offset_zero(kallsym, img_buf, "__do_execve_file"); - symbol->do_execve_common = try_get_symbol_offset_zero(kallsym, img_buf, "do_execve_common"); - if (!symbol->do_execveat_common && !symbol->__do_execve_file && !symbol->do_execve_common) - tools_loge_exit("no symbol do_execveat_common, __do_execve_file and do_execve_common"); - - symbol->do_faccessat = try_get_symbol_offset_zero(kallsym, img_buf, "do_faccessat"); - symbol->sys_faccessat = get_symbol_offset_zero(kallsym, img_buf, "__arm64_sys_faccessat"); - if (!symbol->sys_faccessat) symbol->sys_faccessat = get_symbol_offset_zero(kallsym, img_buf, "sys_faccessat"); - symbol->sys_faccessat2 = get_symbol_offset_zero(kallsym, img_buf, "__arm64_sys_faccessat2"); - if (!symbol->sys_faccessat2) symbol->sys_faccessat2 = get_symbol_offset_zero(kallsym, img_buf, "sys_faccessat2"); - if (!symbol->do_faccessat && !symbol->sys_faccessat && !symbol->sys_faccessat) - tools_loge_exit("no symbol do_faccessat, sys_faccessat and sys_faccessat2"); - - symbol->sys_newfstatat = get_symbol_offset_zero(kallsym, img_buf, "__arm64_sys_newfstatat"); - if (!symbol->sys_newfstatat) symbol->sys_newfstatat = get_symbol_offset_zero(kallsym, img_buf, "sys_newfstatat"); - symbol->vfs_statx = try_get_symbol_offset_zero(kallsym, img_buf, "vfs_statx"); - symbol->vfs_fstatat = try_get_symbol_offset_zero(kallsym, img_buf, "vfs_fstatat"); - if (!symbol->sys_newfstatat && !symbol->vfs_fstatat && !symbol->vfs_statx) - tools_loge_exit("no symbol vfs_statx and vfs_fstatat"); - // gcc -fipa-sra eg: avc_denied.isra.5 symbol->avc_denied = try_get_symbol_offset_zero(kallsym, img_buf, "avc_denied"); if (!symbol->avc_denied && is_android) tools_loge_exit("no symbol avc_denied"); diff --git a/user/.gitignore b/user/.gitignore index e755c739..94b9893e 100644 --- a/user/.gitignore +++ b/user/.gitignore @@ -1,39 +1 @@ -# Prerequisites -*.d - -# Object files -*.o -*.ko -*.obj -*.elf - -# Linker output -*.ilk -*.map -*.exp - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - - -build/* - -uapi -version -kpatch - -build_android.sh - +uapi \ No newline at end of file diff --git a/user/supercall.h b/user/supercall.h index 2f200241..cc54225c 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -16,16 +16,15 @@ #include "uapi/scdefs.h" #include "../version" -// TODO: delete this file and use supercall_ge0a04.h instead when no one has kernelpatch <= 0.10.4, - -// be 0a04 +/// @deprecated +/// KernelPatch version less than 0xa05 static inline long hash_key_cmd(const char *key, long cmd) { long hash = hash_key(key); return hash & 0xFFFF0000 | cmd; } -// ge 0a05 +/// KernelPatch version is greater than or equal to 0x0a05 static inline long ver_and_cmd(const char *key, long cmd) { uint32_t version_code = (MAJOR << 16) + (MINOR << 8) + PATCH; @@ -34,11 +33,19 @@ static inline long ver_and_cmd(const char *key, long cmd) static inline long compact_cmd(const char *key, long cmd) { +#if 1 long ver = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KERNELPATCH_VER)); if (ver >= 0xa05) return ver_and_cmd(key, cmd); +#endif return hash_key_cmd(key, cmd); } +/** + * @brief If KernelPatch installed, @see SUPERCALL_HELLO_ECHO will echoed. + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @return long + */ static inline long sc_hello(const char *key) { if (!key || !key[0]) return -EINVAL; @@ -46,11 +53,25 @@ static inline long sc_hello(const char *key) return ret; } +/** + * @brief Is KernelPatch installed? + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @return true + * @return false + */ static inline bool sc_ready(const char *key) { return sc_hello(key) == SUPERCALL_HELLO_MAGIC; } +/** + * @brief Print messages by printk in the kernel + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param msg + * @return long + */ static inline long sc_klog(const char *key, const char *msg) { if (!key || !key[0]) return -EINVAL; @@ -59,6 +80,12 @@ static inline long sc_klog(const char *key, const char *msg) return ret; } +/** + * @brief KernelPatch version number + * + * @param key + * @return uint32_t + */ static inline uint32_t sc_kp_ver(const char *key) { if (!key || !key[0]) return -EINVAL; @@ -66,6 +93,12 @@ static inline uint32_t sc_kp_ver(const char *key) return (uint32_t)ret; } +/** + * @brief Kernel version number + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @return uint32_t + */ static inline uint32_t sc_k_ver(const char *key) { if (!key || !key[0]) return -EINVAL; @@ -73,170 +106,340 @@ static inline uint32_t sc_k_ver(const char *key) return (uint32_t)ret; } -static inline uint32_t sc_skey_get(const char *key, char *out_key, int outlen) +/** + * @brief Substitute user of current thread + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param profile : if scontext is invalid or illegal, all selinux permission checks will bypass via hook + * @see struct su_profile + * @return long : 0 if succeed + */ +static inline long sc_su(const char *key, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL; - if (outlen < SUPERCALL_KEY_MAX_LEN) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_GET), out_key, outlen); - return (uint32_t)ret; + if (strlen(profile->scontext) >= SUPERCALL_SCONTEXT_LEN) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU), profile); + return ret; } -static inline uint32_t sc_skey_set(const char *key, const char *new_key) +/** + * @brief Substitute user of tid specfied + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param tid : target thread id + * @param profile : if scontext is invalid or illegal, all selinux permission checks will bypass via hook + * @see struct su_profile + * @return long : 0 if succeed + */ +static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL; - if (!new_key || !new_key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_SET), new_key); - return (uint32_t)ret; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_TASK), tid, profile); + return ret; } -static inline uint32_t sc_skey_root_enable(const char *key, bool enable) +/** + * @brief Grant su permission + * + * @param key + * @param profile : if scontext is invalid or illegal, all selinux permission checks will bypass via hook + * @return long : 0 if succeed + */ +static inline long sc_su_grant_uid(const char *key, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_ROOT_ENABLE), (long)enable); - return (uint32_t)ret; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GRANT_UID), profile); + return ret; } -static inline long sc_su(const char *key, struct su_profile *profile) +/** + * @brief Revoke su permission + * + * @param key + * @param uid + * @return long 0 if succeed + */ +static inline long sc_su_revoke_uid(const char *key, uid_t uid) { if (!key || !key[0]) return -EINVAL; - if (strlen(profile->scontext) >= SUPERCALL_SCONTEXT_LEN) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU), profile); + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_REVOKE_UID), uid); return ret; } -static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *profile) +/** + * @brief Get numbers of su allowed uids + * + * @param key + * @return long + */ +static inline long sc_su_uid_nums(const char *key) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_TASK), tid, profile); + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_NUMS)); return ret; } -static inline long sc_kpm_load(const char *key, const char *path, const char *args, void *reserved) +/** + * @brief + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param buf + * @param num + * @return long : The numbers of uids if succeed, nagative value if failed + */ +static inline long sc_su_allow_uids(const char *key, uid_t *buf, int num) { if (!key || !key[0]) return -EINVAL; - if (!path || strlen(path) <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_LOAD), path, args, reserved); + if (!buf || num <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_LIST), buf, num); return ret; } -static inline long sc_kpm_control(const char *key, const char *name, const char *ctl_args, char *out_msg, long outlen) +/** + * @brief Get su profile of specified uid + * + * @param key + * @param uid + * @param out_profile + * @return long : 0 if succeed + */ +static inline long sc_su_uid_profile(const char *key, uid_t uid, struct su_profile *out_profile) { if (!key || !key[0]) return -EINVAL; - if (!name || strlen(name) <= 0) return -EINVAL; - if (!ctl_args || strlen(ctl_args) <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_CONTROL), name, ctl_args, out_msg, outlen); + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_PROFILE), uid, out_profile); return ret; } -static inline long sc_kpm_unload(const char *key, const char *name, void *reserved) +/** + * @brief Get full path of current 'su' command + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param out_path + * @param path_len + * @return long : The length of result string if succeed, negative if failed + */ +static inline long sc_su_get_path(const char *key, char *out_path, int path_len) { if (!key || !key[0]) return -EINVAL; - if (!name || strlen(name) <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_UNLOAD), name, reserved); + if (!out_path || out_path <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_PATH), out_path, path_len); return ret; } -static inline long sc_kpm_nums(const char *key) +/** + * @brief Reset full path of 'su' command + * + * @param key + * @param path + * @return long : 0 if succeed + */ +static inline long sc_su_reset_path(const char *key, const char *path) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_NUMS)); + if (!path || !path[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_RESET_PATH), path); return ret; } -static inline long sc_kpm_list(const char *key, char *names_buf, int buf_len) +/** + * @brief Get current all-allowed selinux context + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param out_sctx + * @param sctx_len + * @return long 0 if there is a all-allowed selinux context now + */ +static inline long sc_su_get_all_allow_sctx(const char *key, char *out_sctx, int sctx_len) { if (!key || !key[0]) return -EINVAL; - if (!names_buf || buf_len <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_LIST), names_buf, buf_len); + if (!out_sctx) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_ALLOW_SCTX), out_sctx); return ret; } -static inline long sc_kpm_info(const char *key, const char *name, char *buf, int buf_len) +/** + * @brief Reset current all-allowed selinux context + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param sctx If sctx is empty string, clear all-allowed selinux, + * otherwise, try to reset a new all-allowed selinux context + * @return long 0 if succeed + */ +static inline long sc_su_reset_all_allow_sctx(const char *key, const char *sctx) { if (!key || !key[0]) return -EINVAL; - if (!buf || buf_len <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_INFO), name, buf, buf_len); + if (!sctx) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_SET_ALLOW_SCTX), sctx); return ret; } -static inline long sc_pid_virt_to_phys(const char *key, pid_t pid, unsigned long vaddr) +/** + * @brief Load module + * + * @param key : superkey + * @param path + * @param args + * @param reserved + * @return long : 0 if succeed + */ +static inline long sc_kpm_load(const char *key, const char *path, const char *args, void *reserved) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_MEM_PHYS), pid, vaddr); + if (!path || strlen(path) <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_LOAD), path, args, reserved); return ret; } -static inline long sc_bootlog(const char *key) +/** + * @brief Control module with arguments + * + * @param key : superkey + * @param name : module name + * @param ctl_args : control argument + * @param out_msg : output message buffer + * @param outlen : buffer length of out_msg + * @return long : 0 if succeed + */ +static inline long sc_kpm_control(const char *key, const char *name, const char *ctl_args, char *out_msg, long outlen) { - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_BOOTLOG)); + if (!key || !key[0]) return -EINVAL; + if (!name || strlen(name) <= 0) return -EINVAL; + if (!ctl_args || strlen(ctl_args) <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_CONTROL), name, ctl_args, out_msg, outlen); return ret; } -static inline long sc_panic(const char *key) +/** + * @brief Unload module + * + * @param key : superkey + * @param name : module name + * @param reserved + * @return long : 0 if succeed + */ +static inline long sc_kpm_unload(const char *key, const char *name, void *reserved) { - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_PANIC)); + if (!key || !key[0]) return -EINVAL; + if (!name || strlen(name) <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_UNLOAD), name, reserved); return ret; } -static inline long __sc_test(const char *key, long a1, long a2, long a3) +/** + * @brief Current loaded module numbers + * + * @param key : superkey + * @return long + */ +static inline long sc_kpm_nums(const char *key) { - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_TEST), a1, a2, a3); + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_NUMS)); return ret; } -#ifdef ANDROID -static inline long sc_su_grant_uid(const char *key, uid_t uid, struct su_profile *profile) +/** + * @brief List names of current loaded modules, splited with '\n' + * + * @param key : superkey + * @param names_buf : output buffer + * @param buf_len : the length of names_buf + * @return long : the length of result string if succeed, negative if failed + */ +static inline long sc_kpm_list(const char *key, char *names_buf, int buf_len) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GRANT_UID), uid, profile); + if (!names_buf || buf_len <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_LIST), names_buf, buf_len); return ret; } -static inline long sc_su_revoke_uid(const char *key, uid_t uid) +/** + * @brief Get module information. + * + * @param key : superkey + * @param name : module name + * @param buf : + * @param buf_len : + * @return long : The length of result string if succeed, negative if failed + */ +static inline long sc_kpm_info(const char *key, const char *name, char *buf, int buf_len) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_REVOKE_UID), uid); + if (!buf || buf_len <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_INFO), name, buf, buf_len); return ret; } -static inline long sc_su_uid_nums(const char *key) +/** + * @brief Get current superkey + * + * @param key : superkey + * @param out_key + * @param outlen + * @return long : 0 if succeed + */ +static inline long sc_skey_get(const char *key, char *out_key, int outlen) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_NUMS)); + if (outlen < SUPERCALL_KEY_MAX_LEN) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_GET), out_key, outlen); return ret; } -static inline long sc_su_allow_uids(const char *key, uid_t *buf, int num) +/** + * @brief Reset current superkey + * + * @param key : superkey + * @param new_key + * @return long : 0 if succeed + */ +static inline long sc_skey_set(const char *key, const char *new_key) { if (!key || !key[0]) return -EINVAL; - if (!buf || num <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_LIST), buf, num); + if (!new_key || !new_key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_SET), new_key); return ret; } -static inline long sc_su_uid_profile(const char *key, uid_t uid, struct su_profile *out_profile) +/** + * @brief Whether to enable hash verification for root superkey. + * + * @param key : superkey + * @param enable + * @return long + */ +static inline long sc_skey_root_enable(const char *key, bool enable) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_PROFILE), uid, out_profile); + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_ROOT_ENABLE), (long)enable); return ret; } -static inline long sc_su_reset_path(const char *key, const char *path) +// todo +static inline long sc_pid_virt_to_phys(const char *key, pid_t pid, unsigned long vaddr) { if (!key || !key[0]) return -EINVAL; - if (!path || !path[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_RESET_PATH), path); + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_MEM_PHYS), pid, vaddr); return ret; } -static inline long sc_su_get_path(const char *key, char *buf, int buf_size) +static inline long sc_bootlog(const char *key) { - if (!key || !key[0]) return -EINVAL; - if (!buf || buf_size <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_PATH), buf, buf_size); + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_BOOTLOG)); return ret; } -#endif +static inline long sc_panic(const char *key) +{ + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_PANIC)); + return ret; +} + +static inline long __sc_test(const char *key, long a1, long a2, long a3) +{ + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_TEST), a1, a2, a3); + return ret; +} #endif \ No newline at end of file diff --git a/user_deprecated/.gitignore b/user_deprecated/.gitignore new file mode 100644 index 00000000..e755c739 --- /dev/null +++ b/user_deprecated/.gitignore @@ -0,0 +1,39 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + + +build/* + +uapi +version +kpatch + +build_android.sh + diff --git a/user/CMakeLists.txt b/user_deprecated/CMakeLists.txt similarity index 100% rename from user/CMakeLists.txt rename to user_deprecated/CMakeLists.txt diff --git a/user/Makefile b/user_deprecated/Makefile similarity index 100% rename from user/Makefile rename to user_deprecated/Makefile diff --git a/user/android/android_user.c b/user_deprecated/android/android_user.c similarity index 97% rename from user/android/android_user.c rename to user_deprecated/android/android_user.c index fa9a16ae..c2470654 100644 --- a/user/android/android_user.c +++ b/user_deprecated/android/android_user.c @@ -29,9 +29,9 @@ struct allow_pkg_info const char sctx[SUPERCALL_SCONTEXT_LEN]; }; -static char magiskpolicy_path[] = APATCH_BIN_FLODER "magiskpolicy"; -static char pkg_cfg_path[] = APATCH_FLODER "package_config"; -static char su_path_path[] = APATCH_FLODER "su_path"; +static char magiskpolicy_path[] = AP_BIN_DIR "magiskpolicy"; +static char pkg_cfg_path[] = AP_DIR "package_config"; +static char su_path_path[] = AP_DIR "su_path"; extern const char *key; static bool from_kernel = false; @@ -237,7 +237,7 @@ static void post_fs_data_init() return; } - if (access(APATCH_FLODER, F_OK)) mkdir(APATCH_FLODER, 0700); + if (access(AP_DIR, F_OK)) mkdir(AP_DIR, 0700); if (access(APATCH_LOG_FLODER, F_OK)) mkdir(APATCH_LOG_FLODER, 0700); char *log_args[] = { "/system/bin/cp", "-f", EARLY_INIT_LOG_0, APATCH_LOG_FLODER, NULL }; diff --git a/user/android/android_user.h b/user_deprecated/android/android_user.h similarity index 100% rename from user/android/android_user.h rename to user_deprecated/android/android_user.h diff --git a/user/android/apjni.cpp b/user_deprecated/android/apjni.cpp similarity index 100% rename from user/android/apjni.cpp rename to user_deprecated/android/apjni.cpp diff --git a/user/android/sumgr.c b/user_deprecated/android/sumgr.c similarity index 98% rename from user/android/sumgr.c rename to user_deprecated/android/sumgr.c index 3f168829..de7f01a1 100644 --- a/user/android/sumgr.c +++ b/user_deprecated/android/sumgr.c @@ -12,7 +12,7 @@ #include "../supercall.h" -int su_grant(const char *key, uid_t uid, uid_t to_uid, const char *scontext) +int su_grant(const char *key, uid_t to_uid, const char *scontext) { struct su_profile profile = { 0 }; profile.uid = uid; diff --git a/user/android/sumgr.h b/user_deprecated/android/sumgr.h similarity index 100% rename from user/android/sumgr.h rename to user_deprecated/android/sumgr.h diff --git a/user/kpatch.c b/user_deprecated/kpatch.c similarity index 100% rename from user/kpatch.c rename to user_deprecated/kpatch.c diff --git a/user/kpatch.h b/user_deprecated/kpatch.h similarity index 100% rename from user/kpatch.h rename to user_deprecated/kpatch.h diff --git a/user/kpm.c b/user_deprecated/kpm.c similarity index 100% rename from user/kpm.c rename to user_deprecated/kpm.c diff --git a/user/kpm.h b/user_deprecated/kpm.h similarity index 100% rename from user/kpm.h rename to user_deprecated/kpm.h diff --git a/user/main.c b/user_deprecated/main.c similarity index 100% rename from user/main.c rename to user_deprecated/main.c diff --git a/user/su.c b/user_deprecated/su.c similarity index 99% rename from user/su.c rename to user_deprecated/su.c index e0421899..3b74df60 100644 --- a/user/su.c +++ b/user_deprecated/su.c @@ -36,8 +36,8 @@ enum #define DEFAULT_SHELL "/system/bin/sh" #define DEFAULT_PATH "/product/bin:/apex/com.android.runtime/bin:/system/bin:/odm/bin:/vendor/bin:/usr/bin" #define DEFAULT_ROOT_PATH \ - APATCH_BIN_FLODER \ - ":" ADB_FLODER \ + AP_BIN_DIR \ + ":" ADB_DIR \ ":/sbin:/system/sbin:/product/bin:/apex/com.android.runtime/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin:/usr/bin:/user/sbin" #else diff --git a/user/su.h b/user_deprecated/su.h similarity index 100% rename from user/su.h rename to user_deprecated/su.h diff --git a/user_deprecated/supercall.h b/user_deprecated/supercall.h new file mode 100644 index 00000000..4f594900 --- /dev/null +++ b/user_deprecated/supercall.h @@ -0,0 +1,411 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2023 bmax121. All Rights Reserved. + */ + +#ifndef _KPU_SUPERCALL_H_ +#define _KPU_SUPERCALL_H_ + +#include +#include +#include +#include +#include +#include + +#include "uapi/scdefs.h" +#include "../version" + +/// @deprecated +/// KernelPatch version less than 0xa05 +static inline long hash_key_cmd(const char *key, long cmd) +{ + long hash = hash_key(key); + return hash & 0xFFFF0000 | cmd; +} + +/// KernelPatch version is greater than or equal to 0x0a05 +static inline long ver_and_cmd(const char *key, long cmd) +{ + uint32_t version_code = (MAJOR << 16) + (MINOR << 8) + PATCH; + return ((long)version_code << 32) | (0x1158 << 16) | (cmd & 0xFFFF); +} + +static inline long compact_cmd(const char *key, long cmd) +{ +#if 1 + long ver = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KERNELPATCH_VER)); + if (ver >= 0xa05) return ver_and_cmd(key, cmd); +#endif + return hash_key_cmd(key, cmd); +} + +/** + * @brief If KernelPatch installed, @see SUPERCALL_HELLO_ECHO will echoed. + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @return long + */ +static inline long sc_hello(const char *key) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_HELLO)); + return ret; +} + +/** + * @brief Is KernelPatch installed? + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @return true + * @return false + */ +static inline bool sc_ready(const char *key) +{ + return sc_hello(key) == SUPERCALL_HELLO_MAGIC; +} + +/** + * @brief Print messages by printk in the kernel + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param msg + * @return long + */ +static inline long sc_klog(const char *key, const char *msg) +{ + if (!key || !key[0]) return -EINVAL; + if (!msg || strlen(msg) <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KLOG), msg); + return ret; +} + +/** + * @brief KernelPatch version number + * + * @param key + * @return uint32_t + */ +static inline uint32_t sc_kp_ver(const char *key) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KERNELPATCH_VER)); + return (uint32_t)ret; +} + +/** + * @brief Kernel version number + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @return uint32_t + */ +static inline uint32_t sc_k_ver(const char *key) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KERNEL_VER)); + return (uint32_t)ret; +} + +/** + * @brief Substitute user of current thread + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param profile + * @return long : 0 if succeed + */ +static inline long sc_su(const char *key, struct su_profile *profile) +{ + if (!key || !key[0]) return -EINVAL; + if (strlen(profile->scontext) >= SUPERCALL_SCONTEXT_LEN) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU), profile); + return ret; +} + +/** + * @brief Substitute user of tid specfied + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param tid : target thread id + * @param profile + * @return long : 0 if succeed + */ +static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *profile) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_TASK), tid, profile); + return ret; +} + +/** + * @brief Grant su permission + * + * @param key + * @param profile + * @return long : 0 if succeed + */ +static inline long sc_su_grant_uid(const char *key, struct su_profile *profile) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GRANT_UID), profile); + return ret; +} + +/** + * @brief Revoke su permission + * + * @param key + * @param uid + * @return long 0 if succeed + */ +static inline long sc_su_revoke_uid(const char *key, uid_t uid) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_REVOKE_UID), uid); + return ret; +} + +/** + * @brief Get numbers of su allowed uids + * + * @param key + * @return long + */ +static inline long sc_su_uid_nums(const char *key) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_NUMS)); + return ret; +} + +/** + * @brief + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param buf + * @param num + * @return long : The numbers of uids if succeed, nagative value if failed + */ +static inline long sc_su_allow_uids(const char *key, uid_t *buf, int num) +{ + if (!key || !key[0]) return -EINVAL; + if (!buf || num <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_LIST), buf, num); + return ret; +} + +/** + * @brief Get su profile of specified uid + * + * @param key + * @param uid + * @param out_profile + * @return long : 0 if succeed + */ +static inline long sc_su_uid_profile(const char *key, uid_t uid, struct su_profile *out_profile) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_PROFILE), uid, out_profile); + return ret; +} + +/** + * @brief Reset full path of 'su' command + * + * @param key + * @param path + * @return long : 0 if succeed + */ +static inline long sc_su_reset_path(const char *key, const char *path) +{ + if (!key || !key[0]) return -EINVAL; + if (!path || !path[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_RESET_PATH), path); + return ret; +} + +/** + * @brief Get full path of current 'su' command + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param buf + * @param buf_size + * @return long : The length of result string if succeed, negative if failed + */ +static inline long sc_su_get_path(const char *key, char *buf, int buf_size) +{ + if (!key || !key[0]) return -EINVAL; + if (!buf || buf_size <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_PATH), buf, buf_size); + return ret; +} + +/** + * @brief Load module + * + * @param key : superkey + * @param path + * @param args + * @param reserved + * @return long : 0 if succeed + */ +static inline long sc_kpm_load(const char *key, const char *path, const char *args, void *reserved) +{ + if (!key || !key[0]) return -EINVAL; + if (!path || strlen(path) <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_LOAD), path, args, reserved); + return ret; +} + +/** + * @brief Control module with arguments + * + * @param key : superkey + * @param name : module name + * @param ctl_args : control argument + * @param out_msg : output message buffer + * @param outlen : buffer length of out_msg + * @return long : 0 if succeed + */ +static inline long sc_kpm_control(const char *key, const char *name, const char *ctl_args, char *out_msg, long outlen) +{ + if (!key || !key[0]) return -EINVAL; + if (!name || strlen(name) <= 0) return -EINVAL; + if (!ctl_args || strlen(ctl_args) <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_CONTROL), name, ctl_args, out_msg, outlen); + return ret; +} + +/** + * @brief Unload module + * + * @param key : superkey + * @param name : module name + * @param reserved + * @return long : 0 if succeed + */ +static inline long sc_kpm_unload(const char *key, const char *name, void *reserved) +{ + if (!key || !key[0]) return -EINVAL; + if (!name || strlen(name) <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_UNLOAD), name, reserved); + return ret; +} + +/** + * @brief Current loaded module numbers + * + * @param key : superkey + * @return long + */ +static inline long sc_kpm_nums(const char *key) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_NUMS)); + return ret; +} + +/** + * @brief List names of current loaded modules, splited with '\n' + * + * @param key : superkey + * @param names_buf : output buffer + * @param buf_len : the length of names_buf + * @return long : the length of result string if succeed, negative if failed + */ +static inline long sc_kpm_list(const char *key, char *names_buf, int buf_len) +{ + if (!key || !key[0]) return -EINVAL; + if (!names_buf || buf_len <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_LIST), names_buf, buf_len); + return ret; +} + +/** + * @brief Get module information. + * + * @param key : superkey + * @param name : module name + * @param buf : + * @param buf_len : + * @return long : The length of result string if succeed, negative if failed + */ +static inline long sc_kpm_info(const char *key, const char *name, char *buf, int buf_len) +{ + if (!key || !key[0]) return -EINVAL; + if (!buf || buf_len <= 0) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_INFO), name, buf, buf_len); + return ret; +} + +/** + * @brief Get current superkey + * + * @param key : superkey + * @param out_key + * @param outlen + * @return long : 0 if succeed + */ +static inline long sc_skey_get(const char *key, char *out_key, int outlen) +{ + if (!key || !key[0]) return -EINVAL; + if (outlen < SUPERCALL_KEY_MAX_LEN) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_GET), out_key, outlen); + return ret; +} + +/** + * @brief Reset current superkey + * + * @param key : superkey + * @param new_key + * @return long : 0 if succeed + */ +static inline long sc_skey_set(const char *key, const char *new_key) +{ + if (!key || !key[0]) return -EINVAL; + if (!new_key || !new_key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_SET), new_key); + return ret; +} + +/** + * @brief Whether to enable hash verification for root superkey. + * + * @param key : superkey + * @param enable + * @return long + */ +static inline long sc_skey_root_enable(const char *key, bool enable) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_ROOT_ENABLE), (long)enable); + return ret; +} + +// todo +static inline long sc_pid_virt_to_phys(const char *key, pid_t pid, unsigned long vaddr) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_MEM_PHYS), pid, vaddr); + return ret; +} + +static inline long sc_bootlog(const char *key) +{ + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_BOOTLOG)); + return ret; +} + +static inline long sc_panic(const char *key) +{ + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_PANIC)); + return ret; +} + +static inline long __sc_test(const char *key, long a1, long a2, long a3) +{ + long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_TEST), a1, a2, a3); + return ret; +} + +#endif \ No newline at end of file diff --git a/user/supercall_ge0a04.h b/user_deprecated/supercall_ge0a04.h similarity index 95% rename from user/supercall_ge0a04.h rename to user_deprecated/supercall_ge0a04.h index ff427b68..bf272394 100644 --- a/user/supercall_ge0a04.h +++ b/user_deprecated/supercall_ge0a04.h @@ -53,30 +53,30 @@ static inline uint32_t sc_k_ver(const char *key) { if (!key || !key[0]) return -EINVAL; long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KERNEL_VER)); - return (uint32_t)ret; + return (int32_t)ret; } -static inline uint32_t sc_skey_get(const char *key, char *out_key, int outlen) +static inline long sc_skey_get(const char *key, char *out_key, int outlen) { if (!key || !key[0]) return -EINVAL; if (outlen < SUPERCALL_KEY_MAX_LEN) return -EINVAL; long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_GET), out_key, outlen); - return (uint32_t)ret; + return ret; } -static inline uint32_t sc_skey_set(const char *key, const char *new_key) +static inline long sc_skey_set(const char *key, const char *new_key) { if (!key || !key[0]) return -EINVAL; if (!new_key || !new_key[0]) return -EINVAL; long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_SET), new_key); - return (uint32_t)ret; + return ret; } -static inline uint32_t sc_skey_root_enable(const char *key, bool enable) +static inline long sc_skey_root_enable(const char *key, bool enable) { if (!key || !key[0]) return -EINVAL; long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_ROOT_ENABLE), (long)enable); - return (uint32_t)ret; + return ret; } static inline long sc_su(const char *key, struct su_profile *profile) @@ -167,7 +167,6 @@ static inline long __sc_test(const char *key, long a1, long a2, long a3) return ret; } -#ifdef ANDROID static inline long sc_su_grant_uid(const char *key, uid_t uid, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL; @@ -220,6 +219,4 @@ static inline long sc_su_get_path(const char *key, char *buf, int buf_size) return ret; } -#endif - #endif \ No newline at end of file diff --git a/version b/version index 462caf73..bb8bb10b 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ #define MAJOR 0 -#define MINOR 10 -#define PATCH 7 +#define MINOR 11 +#define PATCH 0 From 20de5905daee5f249059760a46ba578c74715196 Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 16 May 2024 19:18:13 +0800 Subject: [PATCH 07/71] fix ci build --- .github/workflows/build_dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_dev.yml b/.github/workflows/build_dev.yml index c99057c7..8c68c33f 100644 --- a/.github/workflows/build_dev.yml +++ b/.github/workflows/build_dev.yml @@ -55,10 +55,10 @@ jobs: mv kpimg.elf kpimg.elf-android unset ANDROID + make clean make mv kpimg kpimg-linux mv kpimg.elf kpimg.elf-linux - make clean cd .. cd kpms From 537bec46bdf6109e13cb7e0b0e2cf2f579a2bc9e Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 16 May 2024 19:19:40 +0800 Subject: [PATCH 08/71] fix ci build --- .github/workflows/build_dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_dev.yml b/.github/workflows/build_dev.yml index 8c68c33f..a4ae524c 100644 --- a/.github/workflows/build_dev.yml +++ b/.github/workflows/build_dev.yml @@ -4,7 +4,7 @@ on: push: branches: ["dev"] paths: - - ".github/workflows/build.yml" + - ".github/workflows/build_dev.yml" - "kernel/**" - "user/**" - "tools/**" @@ -12,7 +12,7 @@ on: pull_request: branches: ["dev"] paths: - - ".github/workflows/build.yml" + - ".github/workflows/build_dev.yml" - "kernel/**" - "user/**" - "tools/**" From fb450ed23b23f3b0b7bf1a8e9426702e8cebf25a Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 16 May 2024 19:28:37 +0800 Subject: [PATCH 09/71] update dev ci --- .github/workflows/build_dev.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build_dev.yml b/.github/workflows/build_dev.yml index a4ae524c..bcb8b587 100644 --- a/.github/workflows/build_dev.yml +++ b/.github/workflows/build_dev.yml @@ -88,7 +88,6 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ steps.parse_version.outputs.VERSION }}-dev - commit: dev artifacts: | kernel/kpimg-linux kernel/kpimg-android @@ -130,7 +129,6 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ steps.parse_version.outputs.VERSION }}-dev - commit: dev artifacts: | kpuser.zip allowUpdates: true @@ -188,7 +186,6 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ steps.parse_version.outputs.VERSION }}-dev - commit: dev artifacts: | user/build/android/kpatch-android user/build/android/libapjni.so @@ -234,7 +231,6 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ steps.parse_version.outputs.VERSION }}-dev - commit: dev artifacts: | tools/build/kptools-linux allowUpdates: true @@ -277,7 +273,6 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ steps.parse_version.outputs.VERSION }}-dev - commit: dev artifacts: | tools/build/kptools-mac allowUpdates: true From 50a65d3bfb806259bdde4d456064d2441ce2ab38 Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 16 May 2024 19:32:40 +0800 Subject: [PATCH 10/71] update ci --- .github/workflows/build.yml | 3 +-- .github/workflows/build_dev.yml | 5 ++--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2de32c87..a667ca7c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,6 +44,7 @@ jobs: make mv kpimg kpimg-android mv kpimg.elf kpimg.elf-android + make clean unset ANDROID make @@ -179,8 +180,6 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ steps.parse_version.outputs.VERSION }} artifacts: | - user/build/android/kpatch-android - user/build/android/libapjni.so tools/build/android/kptools-android allowUpdates: true replacesArtifacts: true diff --git a/.github/workflows/build_dev.yml b/.github/workflows/build_dev.yml index bcb8b587..312494b8 100644 --- a/.github/workflows/build_dev.yml +++ b/.github/workflows/build_dev.yml @@ -53,12 +53,13 @@ jobs: make mv kpimg kpimg-android mv kpimg.elf kpimg.elf-android + make clean unset ANDROID - make clean make mv kpimg kpimg-linux mv kpimg.elf kpimg.elf-linux + make clean cd .. cd kpms @@ -187,8 +188,6 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} tag: ${{ steps.parse_version.outputs.VERSION }}-dev artifacts: | - user/build/android/kpatch-android - user/build/android/libapjni.so tools/build/android/kptools-android allowUpdates: true replacesArtifacts: true From d8f84fe71b57291e06661c1201a81198bb28a511 Mon Sep 17 00:00:00 2001 From: bmax Date: Tue, 21 May 2024 19:25:45 +0800 Subject: [PATCH 11/71] a --- kernel/base/predata.c | 4 +- kernel/include/predata.h | 2 +- kernel/include/preset.h | 1 - kernel/linux/include/linux/cred.h | 90 ++++++++++--------------------- kernel/patch/android/userd.c | 65 +++++++++++----------- kernel/patch/common/accctl.c | 17 +++--- kernel/patch/common/supercmd.c | 32 ++++++----- kernel/patch/common/syscall.c | 2 +- kernel/patch/include/accctl.h | 1 - kernel/patch/include/hotpatch.h | 2 - 10 files changed, 88 insertions(+), 128 deletions(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 0950039e..f852d435 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -21,7 +21,7 @@ static struct patch_symbol *patch_symbol = 0; static const char bstr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; static uint64_t _rand_next = 1000000007; -static int enable_root_key = 1; +static bool enable_root_key = true; int auth_superkey(const char *key) { @@ -55,7 +55,7 @@ void reset_superkey(const char *key) dsb(ish); } -void enable_auth_root_key(int enable) +void enable_auth_root_key(bool enable) { enable_root_key = enable; } diff --git a/kernel/include/predata.h b/kernel/include/predata.h index 56ae5bd4..5d02451c 100644 --- a/kernel/include/predata.h +++ b/kernel/include/predata.h @@ -11,7 +11,7 @@ int auth_superkey(const char *key); void reset_superkey(const char *key); -void enable_auth_root_key(int enable); +void enable_auth_root_key(bool enable); const char *get_superkey(); uint64_t rand_next(); diff --git a/kernel/include/preset.h b/kernel/include/preset.h index 1970d33e..b63772de 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -106,7 +106,6 @@ struct patch_symbol { uint64_t kallsyms_lookup_name; uint64_t printk; - uint64_t vm_area_add_early; uint64_t panic; uint64_t rest_init; diff --git a/kernel/linux/include/linux/cred.h b/kernel/linux/include/linux/cred.h index 6af545fa..b36d5f77 100644 --- a/kernel/linux/include/linux/cred.h +++ b/kernel/linux/include/linux/cred.h @@ -97,118 +97,82 @@ extern bool kfunc_def(creds_are_invalid)(const struct cred *cred); static inline void __put_cred(struct cred *cred) { - kfunc_call(__put_cred, cred); - kfunc_not_found(); + kfunc_direct_call(__put_cred, cred); } + static inline void exit_creds(struct task_struct *task) { - kfunc_call(exit_creds, task); - kfunc_not_found(); + kfunc_direct_call_void(exit_creds, task); } + static inline int copy_creds(struct task_struct *p, unsigned long clone_flags) { - kfunc_call(copy_creds, p, clone_flags); - kfunc_not_found(); - return 0; + kfunc_direct_call(copy_creds, p, clone_flags); } + static inline const struct cred *get_task_cred(struct task_struct *task) { - kfunc_call(get_task_cred, task); - kfunc_not_found(); - return 0; + kfunc_direct_call(get_task_cred, task); } + static inline struct cred *cred_alloc_blank(void) { - kfunc_call(cred_alloc_blank); - kfunc_not_found(); - return 0; + kfunc_direct_call(cred_alloc_blank); } + static inline struct cred *prepare_creds(void) { - kfunc_call(prepare_creds); - kfunc_not_found(); - return 0; + kfunc_direct_call(prepare_creds); } + static inline struct cred *prepare_exec_creds(void) { - kfunc_call(prepare_exec_creds); - kfunc_not_found(); - return 0; + kfunc_direct_call(prepare_exec_creds); } + static inline int commit_creds(struct cred *new) { - kfunc_call(commit_creds, new); - kfunc_not_found(); - return 0; + kfunc_direct_call(commit_creds, new); } + static inline void abort_creds(struct cred *new) { - kfunc_call(abort_creds, new); - kfunc_not_found(); + kfunc_direct_call_void(abort_creds, new); } + static inline const struct cred *override_creds(const struct cred *new) { - kfunc_call(override_creds, new); - kfunc_not_found(); - return 0; + kfunc_direct_call(override_creds, new); } + static inline void revert_creds(const struct cred *old) { - kfunc_call(revert_creds, old); - kfunc_not_found(); + kfunc_direct_call(revert_creds, old); } + static inline struct cred *prepare_kernel_cred(struct task_struct *daemon) { - kfunc_call(prepare_kernel_cred, daemon); - kfunc_not_found(); - return 0; -} - -static inline int change_create_files_as(struct cred *cred, struct inode *inode) -{ - kfunc_call(change_create_files_as, cred, inode); - kfunc_not_found(); - return 0; + kfunc_direct_call(prepare_kernel_cred, daemon); } static inline int set_security_override(struct cred *new, u32 secid) { - kfunc_call(set_security_override, new, secid); - return 0; + kfunc_direct_call(set_security_override, new, secid); } static inline int set_security_override_from_ctx(struct cred *new, const char *secctx) { - kfunc_call(set_security_override_from_ctx, new, secctx); - kfunc_not_found(); - return 0; -} - -static inline int set_create_files_as(struct cred *new, struct inode *inode) -{ - kfunc_call(set_create_files_as, new, inode); - kfunc_not_found(); - return 0; + kfunc_direct_call(set_security_override_from_ctx, new, secctx); } static inline int cred_fscmp(const struct cred *a, const struct cred *b) { - kfunc_call(cred_fscmp, a, b); - kfunc_not_found(); - return 0; -} - -static inline void cred_init(void) -{ - kfunc_call(cred_init); - kfunc_not_found(); + kfunc_direct_call(cred_fscmp, a, b); } static inline bool creds_are_invalid(const struct cred *cred) { - kfunc_call(creds_are_invalid, cred); - kfunc_not_found(); - return 0; + kfunc_direct_call(creds_are_invalid, cred); } #endif diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 16c99253..9eb9daa0 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -55,29 +55,29 @@ static const void *kernel_read_file(const char *path, loff_t *len) return data; } -static loff_t kernel_write_file(const char *path, const void *data, loff_t len, umode_t mode) -{ - loff_t off = 0; - set_priv_sel_allow(current, true); - - struct file *fp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); - if (!fp || IS_ERR(fp)) { - log_boot("create file %s error: %d\n", path, PTR_ERR(fp)); - goto out; - } - kernel_write(fp, data, len, &off); - if (off != len) { - log_boot("write file %s error: %x\n", path, off); - goto free; - } - -free: - filp_close(fp, 0); - -out: - set_priv_sel_allow(current, false); - return off; -} +// static loff_t kernel_write_file(const char *path, const void *data, loff_t len, umode_t mode) +// { +// loff_t off = 0; +// set_priv_sel_allow(current, true); + +// struct file *fp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); +// if (!fp || IS_ERR(fp)) { +// log_boot("create file %s error: %d\n", path, PTR_ERR(fp)); +// goto out; +// } +// kernel_write(fp, data, len, &off); +// if (off != len) { +// log_boot("write file %s error: %x\n", path, off); +// goto free; +// } + +// free: +// filp_close(fp, 0); + +// out: +// set_priv_sel_allow(current, false); +// return off; +// } static void pre_user_exec_init() { @@ -226,21 +226,17 @@ static void after_execveat(hook_fargs5_t *args, void *udata) static const char user_rc_data[] = { // "\n" "on post-fs-data\n" - " exec -- " SUPERCMD " %s exec " AP_BIN_DIR "magiskpolicy --live --magisk\n" - " exec -- " SUPERCMD " %s exec " APD_PATH " post-fs-data\n" + " exec -- " SUPERCMD " %s exec " APD_PATH " -s %s post-fs-data\n" "on nonencrypted\n" - " exec -- " SUPERCMD " %s exec " APD_PATH " services\n" + " exec -- " SUPERCMD " %s exec " APD_PATH " -s %s services\n" "on property:vold.decrypt=trigger_restart_framework\n" - " exec -- " SUPERCMD " %s exec " APD_PATH " services\n" + " exec -- " SUPERCMD " %s exec " APD_PATH " -s %s services\n" "on property:sys.boot_completed=1\n" - " exec -- " SUPERCMD " %s exec " APD_PATH " boot-completed\n" + " exec -- " SUPERCMD " %s exec " APD_PATH " -s %s boot-completed\n" "\n" "" }; -// todo: struct file *do_filp_open(int dfd, struct filename *pathname, const struct open_flags *op) -// todo: import rc - // https://elixir.bootlin.com/linux/v6.1/source/fs/open.c#L1337 // SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode) static void before_openat(hook_fargs4_t *args, void *udata) @@ -257,7 +253,8 @@ static void before_openat(hook_fargs4_t *args, void *udata) const char __user *filename = (typeof(filename))syscall_argn(args, 1); char buf[32]; - compat_strncpy_from_user(buf, filename, sizeof(buf)); + int rc = compat_strncpy_from_user(buf, filename, sizeof(buf)); + if (IS_ERR(rc)) return; if (strcmp(ORIGIN_RC_FILE, buf)) return; replaced = 1; @@ -278,9 +275,9 @@ static void before_openat(hook_fargs4_t *args, void *udata) goto free; } - char added_rc_data[2048]; + char added_rc_data[4096]; const char *sk = get_superkey(); - sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk, sk); + sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk, sk, sk, sk); kernel_write(newfp, added_rc_data, strlen(added_rc_data), &off); if (off != strlen(added_rc_data) + ori_len) { diff --git a/kernel/patch/common/accctl.c b/kernel/patch/common/accctl.c index 58e6a8cf..73d39958 100644 --- a/kernel/patch/common/accctl.c +++ b/kernel/patch/common/accctl.c @@ -27,8 +27,7 @@ #include char all_allow_sctx[SUPERCALL_SCONTEXT_LEN] = { '\0' }; -int allow_sid_enable = 0; -uint32_t all_allow_sid = 0; +uint32_t all_allow_sid = SECSID_NULL; static void su_cred(struct cred *cred, uid_t uid) { @@ -53,21 +52,17 @@ int set_all_allow_sctx(const char *sctx) { if (!sctx || !sctx[0]) { all_allow_sctx[0] = 0; - all_allow_sid = 0; - dsb(ish); - allow_sid_enable = 0; + all_allow_sid = SECSID_NULL; dsb(ish); logkfd("clear all allow sconetxt\n"); return 0; } int rc = security_secctx_to_secid(sctx, strlen(sctx), &all_allow_sid); - if (!rc) { + if (!rc && all_allow_sid != SECSID_NULL) { strncpy(all_allow_sctx, sctx, sizeof(all_allow_sctx) - 1); all_allow_sctx[sizeof(all_allow_sctx) - 1] = '\0'; dsb(ish); - allow_sid_enable = 1; - dsb(ish); logkfd("set all allow sconetxt: %s, sid: %d\n", all_allow_sctx, all_allow_sid); } return rc; @@ -122,7 +117,7 @@ int commit_common_su(uid_t to_uid, const char *sctx) int commit_su(uid_t to_uid, const char *sctx) { - if (unlikely(allow_sid_enable) && !to_uid) { + if (all_allow_sid != SECSID_NULL && !to_uid) { return commit_kernel_su(); } else { return commit_common_su(to_uid, sctx); @@ -181,7 +176,7 @@ static int (*avc_denied_backup)(struct selinux_state *state, void *ssid, void *t static int avc_denied_replace(struct selinux_state *_state, void *_ssid, void *_tsid, void *_tclass, void *_requested, void *_driver, void *_xperm, void *_flags, struct av_decision *_avd) { - if (unlikely(allow_sid_enable)) { + if (all_allow_sid != SECSID_NULL) { u32 ssid = (u32)(u64)_ssid; if ((uint64_t)_state <= 0xffffffffL) { ssid = (u32)(u64)_state; @@ -218,7 +213,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi void *_requested, void *_audited, void *_denied, void *_result, struct common_audit_data *_a) { - if (allow_sid_enable) { + if (all_allow_sid != SECSID_NULL) { u32 ssid = (u64)_ssid; if ((uint64_t)_state <= 0xffffffffL) { ssid = (u64)_state; diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 090eb7ad..a3bfa0ce 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -123,18 +123,17 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) #define SUPERCMD_ARGS_NO 16 - // args + // copy args const char *parr[SUPERCMD_ARGS_NO + 4] = { 0 }; for (int i = 2; i < SUPERCMD_ARGS_NO; i++) { const char __user *ua = get_user_arg_ptr(0, *uargv, i); - if (!ua || IS_ERR(ua)) break; + if (IS_ERR(ua)) break; const char *a = strndup_user(ua, 512); if (IS_ERR(a)) break; - // ignore after -c or exec - if (a[0] == '-' && a[1] == 'c') break; - if (!strcmp("exec", a)) break; parr[i] = a; + // ignore after -c + if (a[0] == '-' && a[1] == 'c') break; } uint64_t sp = current_user_stack_pointer(); @@ -180,12 +179,10 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } break; default: - goto out_opt; + break; } } -out_opt: - commit_su(profile.to_uid, profile.scontext); int rc = 0; @@ -196,7 +193,14 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) // command const char **carr = parr + pi; const char *cmd = 0; - if (pi < SUPERCMD_ARGS_NO - 1) cmd = carr[0]; + + if (pi < SUPERCMD_ARGS_NO - 1) { + cmd = carr[0]; + } else { + err_msg = "too many args\n"; + goto echo; + } + if (!cmd) { supercmd_exec(u_filename_p, sh_path, &sp); *uargv += pi * 8; @@ -208,15 +212,18 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } else if (!strcmp("-c", cmd)) { supercmd_exec(u_filename_p, sh_path, &sp); *uargv += (carr - parr - 1) * 8; + goto free; } else if (!strcmp("exec", cmd)) { if (!carr[1]) { err_msg = "invalid commmand path"; goto echo; } supercmd_exec(u_filename_p, carr[1], &sp); - *uargv += 3 * 8; + *uargv += (carr - parr + 1) * 8; + goto free; } else if (!strcmp("version", cmd)) { supercmd_echo(u_filename_p, uargv, &sp, "%x,%x", kver, kpver); + goto free; } else if (!strcmp("sumgr", cmd)) { const char *sub_cmd = carr[1]; if (!sub_cmd) sub_cmd = ""; @@ -231,6 +238,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) if (carr[4]) scontext = carr[4]; su_add_allow_uid(uid, to_uid, scontext, 1); supercmd_echo(u_filename_p, uargv, &sp, "supercmd: grant %d, %d, %s", uid, to_uid, scontext); + goto free; } else if (!strcmp(sub_cmd, "revoke")) { const char *suid = carr[2]; unsigned long long uid; @@ -316,10 +324,10 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) const char *able = carr[2]; if (!strcmp("enable", able) || !strcmp("disable", able)) { msg = able; - enable_auth_root_key(1); + enable_auth_root_key(true); } else if (!strcmp("disable", able)) { msg = able; - enable_auth_root_key(0); + enable_auth_root_key(false); } else { err_msg = "enable or disable"; } diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index d8a6b7ca..337739a0 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -61,7 +61,7 @@ const char __user *get_user_arg_ptr(void *a0, void *a1, int nr) } native = (char __user *const __user *)((unsigned long)native + nr * size); char __user **upptr = memdup_user(native, size); - if (!upptr || IS_ERR(upptr)) return ERR_PTR((long)upptr); + if (IS_ERR(upptr)) return ERR_PTR((long)upptr); char __user *uptr; if (size == 8) { diff --git a/kernel/patch/include/accctl.h b/kernel/patch/include/accctl.h index f2607478..771a133b 100644 --- a/kernel/patch/include/accctl.h +++ b/kernel/patch/include/accctl.h @@ -16,7 +16,6 @@ #include extern char all_allow_sctx[SUPERCALL_SCONTEXT_LEN]; -extern int allow_sid_enable; extern uint32_t all_allow_sid; int set_all_allow_sctx(const char *sctx); diff --git a/kernel/patch/include/hotpatch.h b/kernel/patch/include/hotpatch.h index 983d72d0..48c405a2 100644 --- a/kernel/patch/include/hotpatch.h +++ b/kernel/patch/include/hotpatch.h @@ -8,6 +8,4 @@ #include -int patch_verify_safety(); - #endif \ No newline at end of file From f51bcb8d923cdf6fb6d7586d474e7ad9a6c12b02 Mon Sep 17 00:00:00 2001 From: bmax Date: Tue, 21 May 2024 19:27:44 +0800 Subject: [PATCH 12/71] a --- kernel/patch/android/userd.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 9eb9daa0..5bddc495 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -226,13 +226,13 @@ static void after_execveat(hook_fargs5_t *args, void *udata) static const char user_rc_data[] = { // "\n" "on post-fs-data\n" - " exec -- " SUPERCMD " %s exec " APD_PATH " -s %s post-fs-data\n" + " exec -- " SUPERCMD " su exec " APD_PATH " -s %s post-fs-data\n" "on nonencrypted\n" - " exec -- " SUPERCMD " %s exec " APD_PATH " -s %s services\n" + " exec -- " SUPERCMD " su exec " APD_PATH " -s %s services\n" "on property:vold.decrypt=trigger_restart_framework\n" - " exec -- " SUPERCMD " %s exec " APD_PATH " -s %s services\n" + " exec -- " SUPERCMD " su exec " APD_PATH " -s %s services\n" "on property:sys.boot_completed=1\n" - " exec -- " SUPERCMD " %s exec " APD_PATH " -s %s boot-completed\n" + " exec -- " SUPERCMD " su exec " APD_PATH " -s %s boot-completed\n" "\n" "" }; @@ -275,9 +275,9 @@ static void before_openat(hook_fargs4_t *args, void *udata) goto free; } - char added_rc_data[4096]; + char added_rc_data[2048]; const char *sk = get_superkey(); - sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk, sk, sk, sk); + sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk); kernel_write(newfp, added_rc_data, strlen(added_rc_data), &off); if (off != strlen(added_rc_data) + ori_len) { From 93aff590963db63aacc1448e4f3dcb5914460f38 Mon Sep 17 00:00:00 2001 From: bmax Date: Sat, 25 May 2024 18:17:22 +0800 Subject: [PATCH 13/71] make user hdr --- kernel/Makefile | 5 +++-- kernel/patch/android/userd.c | 4 ++-- user/.gitignore | 3 ++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 3dc9fdc9..0443cb27 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -68,8 +68,9 @@ ${TARGET}.elf: ${OBJS} .PHONY: hdr hdr: - cp -Rf patch/include/uapi ../user - cp -f include/preset.h ../tools + cp -Rf patch/include/uapi ../user/ + cp -f ../version ../user/ + cp -f include/preset.h ../tools/ .PHONY: clean clean: diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 5bddc495..3ebb758e 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -253,8 +253,8 @@ static void before_openat(hook_fargs4_t *args, void *udata) const char __user *filename = (typeof(filename))syscall_argn(args, 1); char buf[32]; - int rc = compat_strncpy_from_user(buf, filename, sizeof(buf)); - if (IS_ERR(rc)) return; + long rc = compat_strncpy_from_user(buf, filename, sizeof(buf)); + if (rc <= 0) return; if (strcmp(ORIGIN_RC_FILE, buf)) return; replaced = 1; diff --git a/user/.gitignore b/user/.gitignore index 94b9893e..f9663c85 100644 --- a/user/.gitignore +++ b/user/.gitignore @@ -1 +1,2 @@ -uapi \ No newline at end of file +uapi +version \ No newline at end of file From 12300786943af674ef6dc720f0b00e1d00190190 Mon Sep 17 00:00:00 2001 From: bmax Date: Sat, 25 May 2024 22:54:24 +0800 Subject: [PATCH 14/71] make user hdr --- user/supercall.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user/supercall.h b/user/supercall.h index cc54225c..ffd55b22 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -14,7 +14,7 @@ #include #include "uapi/scdefs.h" -#include "../version" +#include "version" /// @deprecated /// KernelPatch version less than 0xa05 From 24b96698781218b8749d9a0c8b2433376a7434b5 Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 26 May 2024 12:13:41 +0800 Subject: [PATCH 15/71] make user hdr --- kernel/patch/include/uapi/scdefs.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 8db8ca88..33e61f41 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -6,6 +6,15 @@ #ifndef _KP_UAPI_SCDEF_H_ #define _KP_UAPI_SCDEF_H_ +static inline long hash_key(const char *key) +{ + long hash = 1000000007; + for (int i = 0; key[i]; i++) { + hash = hash * 31 + key[i]; + } + return hash; +} + #define SUPERCALL_HELLO_ECHO "hello1158" // #define __NR_supercall __NR3264_truncate // 45 From e33d3a6e736da680748c6d0c2f9409d8830a9d39 Mon Sep 17 00:00:00 2001 From: 1f2003d5 <2652609017@qq.com> Date: Tue, 11 Jun 2024 21:00:21 +0800 Subject: [PATCH 16/71] supercall: Fix super key authentication (#99) Signed-off-by: GarfieldHan <2652609017@qq.com> --- kernel/patch/common/supercall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index d512fd09..c5a686b3 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -346,7 +346,7 @@ static void before(hook_fargs6_t *args, void *udata) int is_key_auth = 0; - if (auth_superkey(key)) { + if (!auth_superkey(key)) { is_key_auth = 1; } else if (!strcmp("su", key)) { uid_t uid = current_uid(); From 2cca05f217ea8d327d02dd20fd830a421bbcf3d2 Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 13 Jun 2024 16:52:19 +0800 Subject: [PATCH 17/71] kpm on post-fs-data, 0.. --- kernel/linux/include/linux/err.h | 7 +- kernel/patch/android/userd.c | 119 +++++++++++++++++++------------ kernel/patch/common/supercmd.c | 12 ++-- kernel/patch/common/taskob.c | 4 +- 4 files changed, 89 insertions(+), 53 deletions(-) diff --git a/kernel/linux/include/linux/err.h b/kernel/linux/include/linux/err.h index df1ea597..9f50c920 100644 --- a/kernel/linux/include/linux/err.h +++ b/kernel/linux/include/linux/err.h @@ -18,11 +18,16 @@ static inline long __must_check PTR_ERR(__force const void *ptr) return (long)ptr; } -static inline int __must_check IS_ERR(__force const void *ptr) +static inline bool __must_check IS_ERR(__force const void *ptr) { return IS_ERR_VALUE((unsigned long)ptr); } +static inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr) +{ + return unlikely(!ptr) || IS_ERR_VALUE((unsigned long)ptr); +} + static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr) { if (IS_ERR(ptr)) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 3ebb758e..1d251385 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -33,6 +33,54 @@ #include #include +#define ORIGIN_RC_FILE "/system/etc/init/atrace.rc" +#define REPLACE_RC_FILE "/dev/anduser.rc" + +#define ADB_FLODER "/data/adb/" +#define AP_DIR "/data/adb/ap/" +#define AP_BIN_DIR AP_DIR "bin/" +#define AP_LOG_DIR AP_DIR "log/" + +#define KPM_LOAD_SH "/dev/load_module.sh" + +static const char user_rc_data[] = { // + "\n" + "on post-fs-data\n" + " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s post-fs-data\n" + " exec -- " SUPERCMD " su exec " APD_PATH " -s %s post-fs-data\n" + "on nonencrypted\n" + " exec -- " SUPERCMD " su exec " APD_PATH " -s %s services\n" + "on property:vold.decrypt=trigger_restart_framework\n" + " exec -- " SUPERCMD " su exec " APD_PATH " -s %s services\n" + "on property:sys.boot_completed=1\n" + " exec -- " SUPERCMD " su exec " APD_PATH " -s %s boot-completed\n" + " exec -- " SUPERCMD " su exec /system/bin/rm " REPLACE_RC_FILE "\n" + " exec -- " SUPERCMD " su exec /system/bin/rm " KPM_LOAD_SH "\n" + "" +}; + +static const char load_module_sh[] = // + "#!/bin/sh\n" + "mods_dir=\"/data/adb/ap/kpmods/\"\n" + "if [ ! -d \"$mods_dir\" ]; then \n" + " echo \"Error: no modules\"\n" + " exit 0\n" + "fi\n" + "for dir in \"$mods_dir/*\"; do\n" + " if [ ! -d \"$dir\" ]; then continue; fi\n" + " if [ -e \"$dir/disable\" ]; then continue; fi\n" + " main_sh=\"$dir/main.sh\"\n" + " if [ -e \"$main_sh\" ]; then\n" + " touch \"$dir/disable\"\n" + " echo \"loading $dir/main.sh ...\"\n" + " . \"$main_sh\"\n" + " rm -f \"$dir/disable\"\n" + " else\n" + " echo \"Error: $main_sh not found in $dir\"\n" + " fi\n" + "done\n"; +; + static const void *kernel_read_file(const char *path, loff_t *len) { set_priv_sel_allow(current, true); @@ -55,33 +103,34 @@ static const void *kernel_read_file(const char *path, loff_t *len) return data; } -// static loff_t kernel_write_file(const char *path, const void *data, loff_t len, umode_t mode) -// { -// loff_t off = 0; -// set_priv_sel_allow(current, true); - -// struct file *fp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); -// if (!fp || IS_ERR(fp)) { -// log_boot("create file %s error: %d\n", path, PTR_ERR(fp)); -// goto out; -// } -// kernel_write(fp, data, len, &off); -// if (off != len) { -// log_boot("write file %s error: %x\n", path, off); -// goto free; -// } - -// free: -// filp_close(fp, 0); - -// out: -// set_priv_sel_allow(current, false); -// return off; -// } +static loff_t kernel_write_file(const char *path, const void *data, loff_t len, umode_t mode) +{ + loff_t off = 0; + set_priv_sel_allow(current, true); + + struct file *fp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); + if (!fp || IS_ERR(fp)) { + log_boot("create file %s error: %d\n", path, PTR_ERR(fp)); + goto out; + } + kernel_write(fp, data, len, &off); + if (off != len) { + log_boot("write file %s error: %x\n", path, off); + goto free; + } + +free: + filp_close(fp, 0); + +out: + set_priv_sel_allow(current, false); + return off; +} static void pre_user_exec_init() { log_boot("event: %s\n", EXTRA_EVENT_PRE_EXEC_INIT); + kernel_write_file(KPM_LOAD_SH, load_module_sh, sizeof(load_module_sh), 0700); } static void pre_init_second_stage() @@ -215,28 +264,6 @@ static void after_execveat(hook_fargs5_t *args, void *udata) handle_after_execve(&args->local); } -#define ORIGIN_RC_FILE "/system/etc/init/atrace.rc" -#define REPLACE_RC_FILE "/dev/anduser.rc" - -#define ADB_FLODER "/data/adb/" -#define AP_DIR "/data/adb/ap/" -#define AP_BIN_DIR AP_DIR "bin/" -#define AP_LOG_DIR AP_DIR "log/" - -static const char user_rc_data[] = { // - "\n" - "on post-fs-data\n" - " exec -- " SUPERCMD " su exec " APD_PATH " -s %s post-fs-data\n" - "on nonencrypted\n" - " exec -- " SUPERCMD " su exec " APD_PATH " -s %s services\n" - "on property:vold.decrypt=trigger_restart_framework\n" - " exec -- " SUPERCMD " su exec " APD_PATH " -s %s services\n" - "on property:sys.boot_completed=1\n" - " exec -- " SUPERCMD " su exec " APD_PATH " -s %s boot-completed\n" - "\n" - "" -}; - // https://elixir.bootlin.com/linux/v6.1/source/fs/open.c#L1337 // SYSCALL_DEFINE4(openat, int, dfd, const char __user *, filename, int, flags, umode_t, mode) static void before_openat(hook_fargs4_t *args, void *udata) @@ -277,7 +304,7 @@ static void before_openat(hook_fargs4_t *args, void *udata) char added_rc_data[2048]; const char *sk = get_superkey(); - sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk); + sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk); kernel_write(newfp, added_rc_data, strlen(added_rc_data), &off); if (off != strlen(added_rc_data) + ori_len) { diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index a3bfa0ce..b7f4eca7 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -94,7 +94,7 @@ static const char supercmd_help[] = " key [...]: Superkey manager\n" " SubCommand:\n" " key [SUPERKEY]: Get or Reset current superkey\n" - " hash [enable|disable]: Whether to use hash to verify the root superkey.\n" + " hash : Whether to use hash to verify the root superkey.\n" ""; void handle_supercmd(char **__user u_filename_p, char **__user uargv) @@ -322,17 +322,19 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) reset_superkey(key); } else if (!strcmp("hash", sub_cmd)) { const char *able = carr[2]; - if (!strcmp("enable", able) || !strcmp("disable", able)) { + if (able && !strcmp("enable", able)) { msg = able; enable_auth_root_key(true); - } else if (!strcmp("disable", able)) { + } else if (able && !strcmp("disable", able)) { msg = able; enable_auth_root_key(false); } else { - err_msg = "enable or disable"; + err_msg = "invalid enable or disable"; + goto echo; } } else { err_msg = "invalid subcommand"; + goto echo; } } else if (!strcmp("module", cmd)) { if (!is_key_auth) { @@ -392,9 +394,11 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) msg = buffer; } else { err_msg = "invalid subcommand"; + goto echo; } } else { err_msg = "invalid command"; + goto echo; } } diff --git a/kernel/patch/common/taskob.c b/kernel/patch/common/taskob.c index e82fa8e4..5f731658 100644 --- a/kernel/patch/common/taskob.c +++ b/kernel/patch/common/taskob.c @@ -37,7 +37,7 @@ static void prepare_task_ext(struct task_struct *new, struct task_struct *old) { struct task_ext *old_ext = get_task_ext(old); if (unlikely(!task_ext_valid(old_ext))) { - logkfe("dirty task_ext, pid(maybe dirty): %d\n", old_ext->pid); + logkfe("dirty task_ext, pid(maybe dirty): %d\n", old_ext->pid); return; } struct task_ext *new_ext = get_task_ext(new); @@ -54,7 +54,7 @@ static void prepare_task_ext(struct task_struct *new, struct task_struct *old) dsb(ish); } -int task_ext_size = (sizeof(struct task_ext) - sizeof(int)); +int task_ext_size = offsetof(struct task_ext, _magic); KP_EXPORT_SYMBOL(task_ext_size); static void after_copy_process(hook_fargs8_t *args, void *udata) From df0df40c8d9f61cc40951712ccf63cf146a0918d Mon Sep 17 00:00:00 2001 From: bmax Date: Fri, 14 Jun 2024 15:56:02 +0800 Subject: [PATCH 18/71] tmp fix rc work --- kernel/patch/android/userd.c | 37 ++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 1d251385..7ba122aa 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -40,28 +40,49 @@ #define AP_DIR "/data/adb/ap/" #define AP_BIN_DIR AP_DIR "bin/" #define AP_LOG_DIR AP_DIR "log/" +#define AP_MAGISKPOLICY_PATH AP_BIN_DIR "magiskpolicy" +#define MAGISK_SCTX "u:r:magisk:s0" #define KPM_LOAD_SH "/dev/load_module.sh" static const char user_rc_data[] = { // "\n" + // "on early-init\n" + // " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s early-init\n" + // "on init\n" + // " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s init\n" + // "on late-init\n" + // " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s late-init\n" "on post-fs-data\n" " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s post-fs-data\n" - " exec -- " SUPERCMD " su exec " APD_PATH " -s %s post-fs-data\n" + " exec -- " SUPERCMD " su -Z " MAGISK_SCTX " exec " APD_PATH " -s %s post-fs-data\n" "on nonencrypted\n" - " exec -- " SUPERCMD " su exec " APD_PATH " -s %s services\n" + " exec -- " SUPERCMD " su -Z " MAGISK_SCTX " exec " APD_PATH " -s %s services\n" "on property:vold.decrypt=trigger_restart_framework\n" - " exec -- " SUPERCMD " su exec " APD_PATH " -s %s services\n" + " exec -- " SUPERCMD " su -Z " MAGISK_SCTX " exec " APD_PATH " -s %s services\n" "on property:sys.boot_completed=1\n" - " exec -- " SUPERCMD " su exec " APD_PATH " -s %s boot-completed\n" - " exec -- " SUPERCMD " su exec /system/bin/rm " REPLACE_RC_FILE "\n" - " exec -- " SUPERCMD " su exec /system/bin/rm " KPM_LOAD_SH "\n" + " rm " REPLACE_RC_FILE "\n" + " rm " KPM_LOAD_SH "\n" + " exec -- " SUPERCMD " su -Z " MAGISK_SCTX " exec " APD_PATH " -s %s boot-completed\n" "" }; static const char load_module_sh[] = // "#!/bin/sh\n" + "SUPERKEY=\"$1\"\n" + "event=\"$2\"\n" "mods_dir=\"/data/adb/ap/kpmods/\"\n" + "handle_event() {\n" + " case \"$event\" in\n" + " post-fs-data)\n" + " /data/adb/ap/bin/magiskpolicy --magisk --live\n" + " ;;\n" + " *)\n" + " echo \"Unknown event: $event\"\n" + " ;;\n" + " esac\n" + "}\n" + "handle_event\n" "if [ ! -d \"$mods_dir\" ]; then \n" " echo \"Error: no modules\"\n" " exit 0\n" @@ -302,9 +323,9 @@ static void before_openat(hook_fargs4_t *args, void *udata) goto free; } - char added_rc_data[2048]; + char added_rc_data[4096]; const char *sk = get_superkey(); - sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk); + sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk, sk); kernel_write(newfp, added_rc_data, strlen(added_rc_data), &off); if (off != strlen(added_rc_data) + ori_len) { From 6c59ee8f4250a88ced6284c507199bb9ec405ed3 Mon Sep 17 00:00:00 2001 From: 1f2003d5 <2652609017@qq.com> Date: Sat, 15 Jun 2024 16:05:07 +0800 Subject: [PATCH 19/71] supercall: Add SUPERCALL_SU_GET_SAFEMODE (#101) Signed-off-by: GarfieldHan <2652609017@qq.com> --- kernel/patch/android/userd.c | 2 -- kernel/patch/common/supercall.c | 14 ++++++++++++++ kernel/patch/include/uapi/scdefs.h | 1 + user/supercall.h | 12 ++++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 7ba122aa..0cd75114 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -383,8 +383,6 @@ static void before_input_handle_event(hook_fargs4_t *args, void *udata) if (volumedown_pressed_count == 3) { log_boot("entering safemode ..."); android_is_safe_mode = 1; - struct file *filp = filp_open(SAFE_MODE_FLAG_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0666); - if (filp && !IS_ERR(filp)) filp_close(filp, 0); } } } diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index c5a686b3..53a64a7e 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -199,6 +199,16 @@ static long call_su_allow_uid_nums() return su_allow_uid_nums(); } +#ifdef ANDROID +extern int android_is_safe_mode; +static long call_su_get_safemode() +{ + int result = android_is_safe_mode; + logkfd("[call_su_get_safemode] %d\n", result); + return result; +} +#endif + static long call_su_list_allow_uid(uid_t *__user uids, int num) { return su_allow_uids(1, uids, num); @@ -276,6 +286,10 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3 return call_su_get_allow_sctx((char *__user)arg1, (int)arg2); case SUPERCALL_SU_SET_ALLOW_SCTX: return call_su_set_allow_sctx((char *__user)arg1); +#ifdef ANDROID + case SUPERCALL_SU_GET_SAFEMODE: + return call_su_get_safemode(); +#endif default: break; } diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 33e61f41..b1392ad4 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -95,6 +95,7 @@ struct su_profile #define SUPERCALL_SU_SET_ALLOW_SCTX 0x1106 #define SUPERCALL_SU_GET_PATH 0x1110 #define SUPERCALL_SU_RESET_PATH 0x1111 +#define SUPERCALL_SU_GET_SAFEMODE 0x1112 #define SUPERCALL_MAX 0x1200 diff --git a/user/supercall.h b/user/supercall.h index ffd55b22..769d3a1d 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -416,6 +416,18 @@ static inline long sc_skey_root_enable(const char *key, bool enable) return ret; } +/** + * @brief Get whether in safe mode + * + * @param key + * @return long + */ +static inline long sc_su_get_safemode(const char *key) +{ + if (!key || !key[0]) return -EINVAL; + return syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_SAFEMODE)); +} + // todo static inline long sc_pid_virt_to_phys(const char *key, pid_t pid, unsigned long vaddr) { From dd63febc4cbdfa7644ab9305d1e3fe7e52d62d4c Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 8 Jul 2024 19:51:44 +0800 Subject: [PATCH 20/71] a --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index a7005cf7..f09ca221 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,4 @@ build test -.test - +script From b8deb4950d2c4d1d18fbabc52031f2205ba61d91 Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 14 Jul 2024 21:54:29 +0800 Subject: [PATCH 21/71] a --- doc/en/super-command.md | 3 ++ kernel/patch/android/gen.sh | 19 ++++++++ kernel/patch/android/gen/user_init.c | 1 + kernel/patch/android/user_init.sh | 55 ++++++++++++++++++++++ kernel/patch/android/userd.c | 68 +++++++--------------------- 5 files changed, 95 insertions(+), 51 deletions(-) create mode 100644 doc/en/super-command.md create mode 100755 kernel/patch/android/gen.sh create mode 100644 kernel/patch/android/gen/user_init.c create mode 100644 kernel/patch/android/user_init.sh diff --git a/doc/en/super-command.md b/doc/en/super-command.md new file mode 100644 index 00000000..bb18a9d5 --- /dev/null +++ b/doc/en/super-command.md @@ -0,0 +1,3 @@ +# Super Command + +truncate SUPERKEY help diff --git a/kernel/patch/android/gen.sh b/kernel/patch/android/gen.sh new file mode 100755 index 00000000..50ec05f7 --- /dev/null +++ b/kernel/patch/android/gen.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +in_file="user_init.sh" +out_file="gen/user_init.c" + +c_string='static const char user_init[] = "' + +temp_string="" + +while IFS= read -r line || [[ -n "$line" ]]; do + escaped_line=$(echo "$line" | sed 's/\\/\\\\/g; s/"/\\"/g') + temp_string+="$escaped_line\\n" +done <"$in_file" + +c_string+="${temp_string}\";" + +echo "$c_string" >$out_file + +touch userd.c diff --git a/kernel/patch/android/gen/user_init.c b/kernel/patch/android/gen/user_init.c new file mode 100644 index 00000000..d8770173 --- /dev/null +++ b/kernel/patch/android/gen/user_init.c @@ -0,0 +1 @@ +static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\")\n echo \"user_init event: $event\"\n ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"service\" | \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event\n}\n\nhandle\n"; diff --git a/kernel/patch/android/user_init.sh b/kernel/patch/android/user_init.sh new file mode 100644 index 00000000..6c2d986a --- /dev/null +++ b/kernel/patch/android/user_init.sh @@ -0,0 +1,55 @@ +#!/bin/sh + +KPMS_DIR="/data/adb/ap/kpms/" +MAGISK_POLICY_PATH="/data/adb/ap/bin/magiskpolicy" +SUPERCMD="truncate" +MAGISK_SCTX="u:r:magisk:s0" +APD_PATH="/data/adb/apd" + +skey="$1" +event="$2" + +LOG_FILE="/dev/user_init_""$event"".log" + +exec >>$LOG_FILE 2>&1 + +set -x + +load_modules() { + for dir in "$KPMS_DIR/*"; do + if [ ! -d "$dir" ]; then continue; fi + if [ -e "$dir/disable" ]; then continue; fi + main_sh="$dir/main.sh" + if [ -e "$main_sh" ]; then + touch "$dir/disable" + echo "loading $dir/main.sh ..." + . "$main_sh" + rm -f "$dir/disable" + else + echo "Error: $main_sh not found in $dir" + fi + done +} + +handle() { + $SUPERCMD $skey event $event + case "$event" in + "early-init" | "init" | "late-init") + echo "user_init event: $event" + ;; + "post-fs-data") + $MAGISK_POLICY_PATH --magisk --live + load_modules $skey $event + $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event + ;; + "service" | "boot-completed") + $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event + ;; + *) + echo "unknown user_init event: $event" + ;; + esac + $SUPERCMD $skey event $event +} + +handle diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 0cd75114..a34021b7 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -34,7 +34,7 @@ #include #define ORIGIN_RC_FILE "/system/etc/init/atrace.rc" -#define REPLACE_RC_FILE "/dev/anduser.rc" +#define REPLACE_RC_FILE "/dev/user_init.rc" #define ADB_FLODER "/data/adb/" #define AP_DIR "/data/adb/ap/" @@ -42,65 +42,31 @@ #define AP_LOG_DIR AP_DIR "log/" #define AP_MAGISKPOLICY_PATH AP_BIN_DIR "magiskpolicy" #define MAGISK_SCTX "u:r:magisk:s0" +#define USER_INIT_SH_PATH "/dev/user_init.sh" -#define KPM_LOAD_SH "/dev/load_module.sh" +#include "gen/user_init.c" static const char user_rc_data[] = { // "\n" - // "on early-init\n" - // " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s early-init\n" - // "on init\n" - // " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s init\n" - // "on late-init\n" - // " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s late-init\n" + "on early-init\n" + " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s early-init\n" + "on init\n" + " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s init\n" + "on late-init\n" + " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s late-init\n" "on post-fs-data\n" - " exec -- " SUPERCMD " su exec " KPM_LOAD_SH " %s post-fs-data\n" - " exec -- " SUPERCMD " su -Z " MAGISK_SCTX " exec " APD_PATH " -s %s post-fs-data\n" + " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s post-fs-data\n" "on nonencrypted\n" - " exec -- " SUPERCMD " su -Z " MAGISK_SCTX " exec " APD_PATH " -s %s services\n" + " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s services\n" "on property:vold.decrypt=trigger_restart_framework\n" - " exec -- " SUPERCMD " su -Z " MAGISK_SCTX " exec " APD_PATH " -s %s services\n" + " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s services\n" "on property:sys.boot_completed=1\n" - " rm " REPLACE_RC_FILE "\n" - " rm " KPM_LOAD_SH "\n" - " exec -- " SUPERCMD " su -Z " MAGISK_SCTX " exec " APD_PATH " -s %s boot-completed\n" + // " rm " REPLACE_RC_FILE "\n" + // " rm " USER_INIT_SH_PATH "\n" + " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s boot-completed\n" "" }; -static const char load_module_sh[] = // - "#!/bin/sh\n" - "SUPERKEY=\"$1\"\n" - "event=\"$2\"\n" - "mods_dir=\"/data/adb/ap/kpmods/\"\n" - "handle_event() {\n" - " case \"$event\" in\n" - " post-fs-data)\n" - " /data/adb/ap/bin/magiskpolicy --magisk --live\n" - " ;;\n" - " *)\n" - " echo \"Unknown event: $event\"\n" - " ;;\n" - " esac\n" - "}\n" - "handle_event\n" - "if [ ! -d \"$mods_dir\" ]; then \n" - " echo \"Error: no modules\"\n" - " exit 0\n" - "fi\n" - "for dir in \"$mods_dir/*\"; do\n" - " if [ ! -d \"$dir\" ]; then continue; fi\n" - " if [ -e \"$dir/disable\" ]; then continue; fi\n" - " main_sh=\"$dir/main.sh\"\n" - " if [ -e \"$main_sh\" ]; then\n" - " touch \"$dir/disable\"\n" - " echo \"loading $dir/main.sh ...\"\n" - " . \"$main_sh\"\n" - " rm -f \"$dir/disable\"\n" - " else\n" - " echo \"Error: $main_sh not found in $dir\"\n" - " fi\n" - "done\n"; -; static const void *kernel_read_file(const char *path, loff_t *len) { @@ -151,7 +117,7 @@ static loff_t kernel_write_file(const char *path, const void *data, loff_t len, static void pre_user_exec_init() { log_boot("event: %s\n", EXTRA_EVENT_PRE_EXEC_INIT); - kernel_write_file(KPM_LOAD_SH, load_module_sh, sizeof(load_module_sh), 0700); + kernel_write_file(USER_INIT_SH_PATH, user_init, sizeof(user_init), 0700); } static void pre_init_second_stage() @@ -325,7 +291,7 @@ static void before_openat(hook_fargs4_t *args, void *udata) char added_rc_data[4096]; const char *sk = get_superkey(); - sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk, sk); + sprintf(added_rc_data, user_rc_data, sk, sk, sk, sk, sk, sk, sk); kernel_write(newfp, added_rc_data, strlen(added_rc_data), &off); if (off != strlen(added_rc_data) + ori_len) { From 031bcfd382ef9ff9b61fec4f075446eb94cacb1b Mon Sep 17 00:00:00 2001 From: Admire Date: Sat, 20 Jul 2024 15:51:14 +0800 Subject: [PATCH 22/71] user_init: Fix `services` typo Signed-off-by: GarfieldHan <2652609017@qq.com> --- kernel/patch/android/gen/user_init.c | 2 +- kernel/patch/android/user_init.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/patch/android/gen/user_init.c b/kernel/patch/android/gen/user_init.c index d8770173..1c962c07 100644 --- a/kernel/patch/android/gen/user_init.c +++ b/kernel/patch/android/gen/user_init.c @@ -1 +1 @@ -static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\")\n echo \"user_init event: $event\"\n ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"service\" | \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event\n}\n\nhandle\n"; +static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\")\n echo \"user_init event: $event\"\n ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\" | \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event\n}\n\nhandle\n"; diff --git a/kernel/patch/android/user_init.sh b/kernel/patch/android/user_init.sh index 6c2d986a..06973c40 100644 --- a/kernel/patch/android/user_init.sh +++ b/kernel/patch/android/user_init.sh @@ -42,7 +42,7 @@ handle() { load_modules $skey $event $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event ;; - "service" | "boot-completed") + "services" | "boot-completed") $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event ;; *) From 8fee64342a05660e1a7ecf4e1e994bac0f57aca1 Mon Sep 17 00:00:00 2001 From: GarfieldHan <2652609017@qq.com> Date: Sat, 20 Jul 2024 16:06:53 +0800 Subject: [PATCH 23/71] selinux: Fix Android specific configs handling in policydb_write() orig patch: https://android-review.googlesource.com/c/kernel/common/+/3009995 Co-authored-by: sekaiacg Co-authored-by: Wang Han Signed-off-by: GarfieldHan <2652609017@qq.com> --- kernel/include/preset.h | 1 + kernel/patch/android/sepolicy_flags.c | 58 +++++++++++++++++++++++++++ kernel/patch/include/sepolicy_flags.h | 40 ++++++++++++++++++ kernel/patch/patch.c | 10 ++++- tools/symbol.c | 1 + 5 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 kernel/patch/android/sepolicy_flags.c create mode 100644 kernel/patch/include/sepolicy_flags.h diff --git a/kernel/include/preset.h b/kernel/include/preset.h index b63772de..be6232f8 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -118,6 +118,7 @@ struct patch_symbol uint64_t cgroup_post_fork; uint64_t avc_denied; uint64_t slow_avc_audit; + uint64_t policydb_write; uint64_t input_handle_event; }; char _cap[PATCH_SYMBOL_LEN]; diff --git a/kernel/patch/android/sepolicy_flags.c b/kernel/patch/android/sepolicy_flags.c new file mode 100644 index 00000000..5548c730 --- /dev/null +++ b/kernel/patch/android/sepolicy_flags.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024 1f2003d5. All Rights Reserved. + * Copyright (C) 2024 sekaiacg. All Rights Reserved. + */ + +#include "sepolicy_flags.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * see: https://android-review.googlesource.com/c/kernel/common/+/3009995 + * + */ + +static int (*policydb_write_backup)(struct _policydb *p, struct _policy_file *fp) = 0; +static int policydb_write_replace(struct _policydb *p, struct _policy_file *fp) +{ + char *data = fp->data; + int ret = policydb_write_backup(p, fp); + if (!ret) { + __le32 *config = (__le32 *)(data + POLICYDB_CONFIG_OFFSET); + __le32 before_config = *config; + bool android_netlink_route_exists = before_config & POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE; + bool android_netlink_getneigh_exists = before_config & POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH; + if (p->android_netlink_route == 1 && !android_netlink_route_exists) { + *config |= POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE; + } + if (p->android_netlink_getneigh == 1 && !android_netlink_getneigh_exists) { + *config |= POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH; + } + } + return ret; +} + +int android_sepolicy_flags_init() +{ + unsigned long policydb_write_addr = get_preset_patch_sym()->policydb_write; + if (likely(policydb_write_addr)) { + hook_err_t err = hook((void *)policydb_write_addr, (void *)policydb_write_replace, (void **)&policydb_write_backup); + if (unlikely(err != HOOK_NO_ERR)) { + log_boot("hook policydb_write_addr: %llx, error: %d\n", policydb_write_addr, err); + return -1; + } + } + + return 0; +} diff --git a/kernel/patch/include/sepolicy_flags.h b/kernel/patch/include/sepolicy_flags.h new file mode 100644 index 00000000..4a6b9216 --- /dev/null +++ b/kernel/patch/include/sepolicy_flags.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024 1f2003d5. All Rights Reserved. + * Copyright (C) 2024 sekaiacg. All Rights Reserved. + */ + +#ifndef _KP_SEPOLICY_FLAGS_H_ +#define _KP_SEPOLICY_FLAGS_H_ + +#include + +#define SELINUX_MAGIC 0xf97cff8c +#define POLICYDB_MAGIC SELINUX_MAGIC +#define POLICYDB_STRING "SE Linux" + +#define POLICYDB_CONFIG_MLS 1 +#define POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE (1 << 31) +#define POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH (1 << 30) + +/* + * config offset: + * __le32(POLICYDB_MAGIC) + __le32(POLICYDB_STRING_LEN) + + * char[POLICYDB_STRING_LEN] + __le32(policyvers) + */ +#define POLICYDB_CONFIG_OFFSET (2 * sizeof(__le32) + strlen(POLICYDB_STRING) + sizeof(__le32)) + +struct _policy_file +{ + char *data; + size_t len; +}; + +struct _policydb +{ + int mls_enabled; + int android_netlink_route; + int android_netlink_getneigh; +}; + +#endif \ No newline at end of file diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index d4093dfe..34330486 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -46,7 +46,10 @@ int resolve_pt_regs(); int supercall_install(); int su_compat_init(); +#ifdef ANDROID int android_user_init(); +int android_sepolicy_flags_init(); +#endif static void before_rest_init(hook_fargs4_t *args, void *udata) { @@ -62,6 +65,11 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) if ((rc = bypass_selinux())) goto out; log_boot("bypass_selinux done: %d\n", rc); +#ifdef ANDROID + rc = android_sepolicy_flags_init(); + log_boot("android_sepolicy_flags_init done: %d\n", rc); +#endif + if ((rc = task_observer())) goto out; log_boot("task_observer done: %d\n", rc); @@ -75,10 +83,8 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) log_boot("resolve_pt_regs done: %d\n", rc); #ifdef ANDROID - rc = android_user_init(); log_boot("android_user_init done: %d\n", rc); - #endif out: diff --git a/tools/symbol.c b/tools/symbol.c index d3787b90..9c5c275a 100644 --- a/tools/symbol.c +++ b/tools/symbol.c @@ -126,6 +126,7 @@ int fillin_patch_symbol(kallsym_t *kallsym, char *img_buf, int imglen, patch_sym symbol->slow_avc_audit = try_get_symbol_offset_zero(kallsym, img_buf, "slow_avc_audit"); + symbol->policydb_write = try_get_symbol_offset_zero(kallsym, img_buf, "policydb_write"); symbol->input_handle_event = get_symbol_offset_zero(kallsym, img_buf, "input_handle_event"); if ((is_be() ^ target_is_be)) { From 37a048189b79d39e30490b6e553a8100894e0879 Mon Sep 17 00:00:00 2001 From: 1f2003d5 <2652609017@qq.com> Date: Wed, 24 Jul 2024 16:19:57 +0800 Subject: [PATCH 24/71] user_init: Add `uid-listener` feature (#110) Avoid messy root list. Signed-off-by: GarfieldHan <2652609017@qq.com> --- kernel/patch/android/gen/user_init.c | 2 +- kernel/patch/android/user_init.c | 1 + kernel/patch/android/user_init.sh | 6 +++++- version | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 kernel/patch/android/user_init.c diff --git a/kernel/patch/android/gen/user_init.c b/kernel/patch/android/gen/user_init.c index 1c962c07..2f822bf1 100644 --- a/kernel/patch/android/gen/user_init.c +++ b/kernel/patch/android/gen/user_init.c @@ -1 +1 @@ -static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\")\n echo \"user_init event: $event\"\n ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\" | \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event\n}\n\nhandle\n"; +static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\")\n echo \"user_init event: $event\"\n ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n $SUPERCMD su -Z $MAGISK_SCTX exec $APD_PATH uid-listener &\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event\n}\n\nhandle\n"; diff --git a/kernel/patch/android/user_init.c b/kernel/patch/android/user_init.c new file mode 100644 index 00000000..2f822bf1 --- /dev/null +++ b/kernel/patch/android/user_init.c @@ -0,0 +1 @@ +static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\")\n echo \"user_init event: $event\"\n ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n $SUPERCMD su -Z $MAGISK_SCTX exec $APD_PATH uid-listener &\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event\n}\n\nhandle\n"; diff --git a/kernel/patch/android/user_init.sh b/kernel/patch/android/user_init.sh index 06973c40..1c83661d 100644 --- a/kernel/patch/android/user_init.sh +++ b/kernel/patch/android/user_init.sh @@ -42,9 +42,13 @@ handle() { load_modules $skey $event $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event ;; - "services" | "boot-completed") + "services") $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event ;; + "boot-completed") + $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event + $SUPERCMD su -Z $MAGISK_SCTX exec $APD_PATH uid-listener & + ;; *) echo "unknown user_init event: $event" ;; diff --git a/version b/version index bb8bb10b..126798bf 100644 --- a/version +++ b/version @@ -1,3 +1,3 @@ #define MAJOR 0 #define MINOR 11 -#define PATCH 0 +#define PATCH 1 From ec82432a8835b80a3326224b74fbb29a61595dce Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 31 Jul 2024 09:47:56 +0800 Subject: [PATCH 25/71] kptools with -s instead of -S, to avoide side-channel detection --- kernel/base/predata.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index f852d435..bec054dc 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -21,7 +21,7 @@ static struct patch_symbol *patch_symbol = 0; static const char bstr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; static uint64_t _rand_next = 1000000007; -static bool enable_root_key = true; +static bool enable_root_key = false; int auth_superkey(const char *key) { @@ -114,8 +114,11 @@ void predata_init() if (*(uint64_t *)(superkey)) _rand_next *= *(uint64_t *)(superkey); if (*(uint64_t *)(root_superkey)) _rand_next *= *(uint64_t *)(root_superkey); + enable_root_key = false; + // random key if (lib_strnlen(superkey, SUPER_KEY_LEN) <= 0) { + enable_root_key = true; int len = SUPER_KEY_LEN > 16 ? 16 : SUPER_KEY_LEN; len--; for (int i = 0; i < len; ++i) { From 6ea388d934560a0f6a37a8284fc92b3f69b331d1 Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 31 Jul 2024 19:44:37 +0800 Subject: [PATCH 26/71] disable hash superkey after reset key --- kernel/base/predata.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index bec054dc..5b7f3905 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -39,7 +39,7 @@ int auth_superkey(const char *key) int len = SHA256_BLOCK_SIZE > ROOT_SUPER_KEY_HASH_LEN ? ROOT_SUPER_KEY_HASH_LEN : SHA256_BLOCK_SIZE; rc = lib_memcmp(root_superkey, hash, len); - static int first_time = 1; + static bool first_time = true; if (!rc && first_time) { first_time = 0; reset_superkey(key); @@ -52,6 +52,7 @@ void reset_superkey(const char *key) { lib_strncpy(superkey, key, SUPER_KEY_LEN - 1); superkey[SUPER_KEY_LEN - 1] = '\0'; + enable_root_key = false; dsb(ish); } From ad4ea83383d17487ceb068c09a27e51bf9a61e56 Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 31 Jul 2024 19:50:58 +0800 Subject: [PATCH 27/71] reset superkey dont disable hash --- kernel/base/predata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 5b7f3905..882f3062 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -43,6 +43,7 @@ int auth_superkey(const char *key) if (!rc && first_time) { first_time = 0; reset_superkey(key); + enable_root_key = false; } return rc; @@ -52,7 +53,6 @@ void reset_superkey(const char *key) { lib_strncpy(superkey, key, SUPER_KEY_LEN - 1); superkey[SUPER_KEY_LEN - 1] = '\0'; - enable_root_key = false; dsb(ish); } From 73049940792472cb8c0cc80d944a3f9f916e6d1c Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 31 Jul 2024 20:52:56 +0800 Subject: [PATCH 28/71] a --- .clang-format | 2 +- kernel/base/baselib.c | 4 ++-- kernel/base/predata.c | 5 ++--- kernel/patch/common/taskob.c | 3 +-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.clang-format b/.clang-format index 4556797b..b3dd3de7 100644 --- a/.clang-format +++ b/.clang-format @@ -51,7 +51,7 @@ BreakConstructorInitializersBeforeComma: false BreakConstructorInitializers: BeforeComma BreakAfterJavaFieldAnnotations: false BreakStringLiterals: false -BreakBeforeSemicolons: None +# BreakBeforeSemicolons: None ColumnLimit: 120 CommentPragmas: "^ IWYU pragma:" CompactNamespaces: false diff --git a/kernel/base/baselib.c b/kernel/base/baselib.c index 0641b872..7bcf18ff 100644 --- a/kernel/base/baselib.c +++ b/kernel/base/baselib.c @@ -244,7 +244,7 @@ char *lib_strncat(char *dst, const char *src, size_t n) *q++ = ch = *p++; if (!ch) return dst; } - *q = '\0'; + // *q = '\0'; return dst; } @@ -277,7 +277,7 @@ char *lib_strncpy(char *dst, const char *src, size_t n) *q++ = ch = *p++; if (!ch) break; } - *q = '\0'; + // *q = '\0'; return dst; } diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 882f3062..71878bbb 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -41,7 +41,7 @@ int auth_superkey(const char *key) static bool first_time = true; if (!rc && first_time) { - first_time = 0; + first_time = false; reset_superkey(key); enable_root_key = false; } @@ -51,8 +51,7 @@ int auth_superkey(const char *key) void reset_superkey(const char *key) { - lib_strncpy(superkey, key, SUPER_KEY_LEN - 1); - superkey[SUPER_KEY_LEN - 1] = '\0'; + lib_strlcpy(superkey, key, SUPER_KEY_LEN); dsb(ish); } diff --git a/kernel/patch/common/taskob.c b/kernel/patch/common/taskob.c index 5f731658..d8fe863a 100644 --- a/kernel/patch/common/taskob.c +++ b/kernel/patch/common/taskob.c @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -37,7 +36,7 @@ static void prepare_task_ext(struct task_struct *new, struct task_struct *old) { struct task_ext *old_ext = get_task_ext(old); if (unlikely(!task_ext_valid(old_ext))) { - logkfe("dirty task_ext, pid(maybe dirty): %d\n", old_ext->pid); + logkfe("dirty task_ext, pid(maybe dirty): %d\n", old_ext->pid); return; } struct task_ext *new_ext = get_task_ext(new); From d501a847ca545777cba6eaa052e8030d9e8e3f64 Mon Sep 17 00:00:00 2001 From: bmax Date: Tue, 13 Aug 2024 22:25:41 +0800 Subject: [PATCH 29/71] a --- kernel/base/start.c | 4 +- kernel/patch/android/gen/user_init.c | 2 +- kernel/patch/android/user_init.c | 1 - kernel/patch/android/user_init.sh | 8 +- kernel/patch/android/userd.c | 3 +- kernel/patch/common/supercmd.c | 8 ++ kernel/patch/common/user_event.c | 14 ++++ kernel/patch/include/user_event.h | 11 +++ tools/kallsym.c | 115 ++++++++++++++++++--------- tools/kallsym.h | 22 +---- 10 files changed, 121 insertions(+), 67 deletions(-) delete mode 100644 kernel/patch/android/user_init.c create mode 100644 kernel/patch/common/user_event.c create mode 100644 kernel/patch/include/user_event.h diff --git a/kernel/base/start.c b/kernel/base/start.c index cb03cfbc..4ba1c03b 100644 --- a/kernel/base/start.c +++ b/kernel/base/start.c @@ -22,8 +22,8 @@ #include "setup.h" #define bits(n, high, low) (((n) << (63u - (high))) >> (63u - (high) + (low))) -#define align_floor(x, align) ((uint64_t)(x) & ~((uint64_t)(align)-1)) -#define align_ceil(x, align) (((uint64_t)(x) + (uint64_t)(align)-1) & ~((uint64_t)(align)-1)) +#define align_floor(x, align) ((uint64_t)(x) & ~((uint64_t)(align) - 1)) +#define align_ceil(x, align) (((uint64_t)(x) + (uint64_t)(align) - 1) & ~((uint64_t)(align) - 1)) start_preset_t start_preset __attribute__((section(".start.data"))); diff --git a/kernel/patch/android/gen/user_init.c b/kernel/patch/android/gen/user_init.c index 2f822bf1..b625bf16 100644 --- a/kernel/patch/android/gen/user_init.c +++ b/kernel/patch/android/gen/user_init.c @@ -1 +1 @@ -static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\")\n echo \"user_init event: $event\"\n ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n $SUPERCMD su -Z $MAGISK_SCTX exec $APD_PATH uid-listener &\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event\n}\n\nhandle\n"; +static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event \"before\"\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\") ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n $SUPERCMD su -Z $MAGISK_SCTX exec $APD_PATH uid-listener &\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event \"after\"\n}\n\nhandle\n"; diff --git a/kernel/patch/android/user_init.c b/kernel/patch/android/user_init.c deleted file mode 100644 index 2f822bf1..00000000 --- a/kernel/patch/android/user_init.c +++ /dev/null @@ -1 +0,0 @@ -static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\")\n echo \"user_init event: $event\"\n ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n $SUPERCMD su -Z $MAGISK_SCTX exec $APD_PATH uid-listener &\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event\n}\n\nhandle\n"; diff --git a/kernel/patch/android/user_init.sh b/kernel/patch/android/user_init.sh index 1c83661d..3546e269 100644 --- a/kernel/patch/android/user_init.sh +++ b/kernel/patch/android/user_init.sh @@ -32,11 +32,9 @@ load_modules() { } handle() { - $SUPERCMD $skey event $event + $SUPERCMD $skey event $event "before" case "$event" in - "early-init" | "init" | "late-init") - echo "user_init event: $event" - ;; + "early-init" | "init" | "late-init") ;; "post-fs-data") $MAGISK_POLICY_PATH --magisk --live load_modules $skey $event @@ -53,7 +51,7 @@ handle() { echo "unknown user_init event: $event" ;; esac - $SUPERCMD $skey event $event + $SUPERCMD $skey event $event "after" } handle diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index a34021b7..e03b8586 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -43,6 +43,7 @@ #define AP_MAGISKPOLICY_PATH AP_BIN_DIR "magiskpolicy" #define MAGISK_SCTX "u:r:magisk:s0" #define USER_INIT_SH_PATH "/dev/user_init.sh" +#define USER_INIT_LOG "/dev/user_init*.log" #include "gen/user_init.c" @@ -63,11 +64,11 @@ static const char user_rc_data[] = { // "on property:sys.boot_completed=1\n" // " rm " REPLACE_RC_FILE "\n" // " rm " USER_INIT_SH_PATH "\n" + // " rm " USER_INIT_LOG "\n" " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s boot-completed\n" "" }; - static const void *kernel_read_file(const char *path, loff_t *len) { set_priv_sel_allow(current, true); diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index b7f4eca7..6254cf6d 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -15,6 +15,7 @@ #include #include #include +#include static char *__user supercmd_str_to_user_sp(const char *data, uintptr_t *sp) { @@ -81,6 +82,7 @@ static const char supercmd_help[] = " profile Get the profile of the uid configuration.\n" " path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n" " sctx [SCONTEXT] Get or Reset current all allowed security context, \n" + " event Report EVENT.\n" "\n" "The command below requires superkey authentication.\n" " module [...]: KernelPatch Module manager\n" @@ -294,6 +296,12 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } else { err_msg = "invalid subcommand"; } + } else if (!strcmp("event", cmd)) { + if (carr[1]) { + rc = report_user_event(carr[1], carr[2]); + } else { + err_msg = "empty event"; + } } else if (!strcmp("bootlog", cmd)) { msg = get_boot_log(); } else if (!strcmp("test", cmd)) { diff --git a/kernel/patch/common/user_event.c b/kernel/patch/common/user_event.c new file mode 100644 index 00000000..aeac207b --- /dev/null +++ b/kernel/patch/common/user_event.c @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024 bmax121. All Rights Reserved. + */ + +#include + +#include + +int report_user_event(const char *event, const char *args) +{ + logki("user report event: %s, args: %s\n", event, args); + return 0; +} \ No newline at end of file diff --git a/kernel/patch/include/user_event.h b/kernel/patch/include/user_event.h new file mode 100644 index 00000000..c64f61bd --- /dev/null +++ b/kernel/patch/include/user_event.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024 bmax121. All Rights Reserved. + */ + +#ifndef _KP_USER_EVENT_H_ +#define _KP_USER_EVENT_H_ + +int report_user_event(const char *event, const char *args); + +#endif \ No newline at end of file diff --git a/tools/kallsym.c b/tools/kallsym.c index ebfc0219..907414ef 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -17,6 +17,24 @@ #include "insn.h" #include "common.h" +#ifdef _WIN32 +#include +static void *memmem(const void *haystack, size_t haystack_len, const void *const needle, const size_t needle_len) +{ + if (haystack == NULL) return NULL; // or assert(haystack != NULL); + if (haystack_len == 0) return NULL; + if (needle == NULL) return NULL; // or assert(needle != NULL); + if (needle_len == 0) return NULL; + + for (const char *h = haystack; haystack_len >= needle_len; ++h, --haystack_len) { + if (!memcmp(h, needle, needle_len)) { + return (void *)h; + } + } + return NULL; +} +#endif + static int find_linux_banner(kallsym_t *info, char *img, int32_t imglen) { /* @@ -203,6 +221,7 @@ static inline int get_offsets_elem_size(kallsym_t *info) static int try_find_arm64_relo_table(kallsym_t *info, char *img, int32_t imglen) { if (!info->try_relo) return 0; + uint64_t min_va = ELF64_KERNEL_MIN_VA; uint64_t max_va = ELF64_KERNEL_MAX_VA; uint64_t kernel_va = max_va; @@ -227,13 +246,12 @@ static int try_find_arm64_relo_table(kallsym_t *info, char *img, int32_t imglen) } } - if (info->elf64_kernel_base) { - tools_logi("find arm64 relocation kernel_va: 0x%" PRIx64 ", but try use: %" PRIx64 "\n", kernel_va, - info->elf64_kernel_base); - kernel_va = info->elf64_kernel_base; + if (info->kernel_base) { + tools_logi("arm64 relocation kernel_va: 0x%" PRIx64 ", try: %" PRIx64 "\n", kernel_va, info->kernel_base); + kernel_va = info->kernel_base; } else { - info->elf64_kernel_base = kernel_va; - tools_logi("find arm64 relocation kernel_va: 0x%" PRIx64 "\n", kernel_va); + info->kernel_base = kernel_va; + tools_logi("arm64 relocation kernel_va: 0x%" PRIx64 "\n", kernel_va); } int32_t cand_start = cand - 24 * rela_num; @@ -251,7 +269,7 @@ static int try_find_arm64_relo_table(kallsym_t *info, char *img, int32_t imglen) return 0; } - tools_logi("find arm64 relocation table range: [0x%08x, 0x%08x), count: 0x%08x\n", cand_start, cand_end, rela_num); + tools_logi("arm64 relocation table range: [0x%08x, 0x%08x), count: 0x%08x\n", cand_start, cand_end, rela_num); // apply relocations int32_t max_offset = imglen - 8; @@ -612,15 +630,13 @@ int arm64_verify_pid_vnr(kallsym_t *info, char *img, int32_t offset) enum aarch64_insn_encoding_class enc = aarch64_get_insn_class(insn); if (enc == AARCH64_INSN_CLS_BR_SYS) { if (aarch64_insn_extract_system_reg(insn) == AARCH64_INSN_SPCLREG_SP_EL0) { - info->elf64_current_heuris = AARCH64_INSN_SPCLREG_SP_EL0; - tools_logi("pid_vnr verfied succeed, sp_el0, insn: 0x%x\n", insn); + tools_logi("pid_vnr verfied sp_el0, insn: 0x%x\n", insn); return 0; } } else if (enc == AARCH64_INSN_CLS_DP_IMM) { u32 rn = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RN, insn); if (rn == AARCH64_INSN_REG_SP) { - info->elf64_current_heuris = AARCH64_INSN_REG_SP; - tools_logi("pid_vnr verfied succeed, sp, insn: 0x%x\n", insn); + tools_logi("pid_vnr verfied sp, insn: 0x%x\n", insn); return 0; } } @@ -658,28 +674,48 @@ static int correct_addresses_or_offsets_by_vectors(kallsym_t *info, char *img, i } int32_t elem_size = info->has_relative_base ? get_offsets_elem_size(info) : get_addresses_elem_size(info); - uint64_t first_elem_val = uint_unpack(img + info->_approx_addresses_or_offsets_offset, elem_size, info->is_be); - // we need some buffer, for some kernel _head(stripped) is ffffff8008080000 and stext (first symbol) is ffffff8008080800, + uint64_t base_cand[3] = { 0 }; + int base_cand_num = 1; + + if (!info->has_relative_base) { + uint64_t base = uint_unpack(img + info->_approx_addresses_or_offsets_offset, elem_size, info->is_be); + base_cand[0] = base; + if (info->kernel_base) { + base_cand[++base_cand_num] = info->kernel_base; + } + if (info->kernel_base != ELF64_KERNEL_MIN_VA) { + base_cand[++base_cand_num] = ELF64_KERNEL_MIN_VA; + } + } + int32_t search_start = info->_approx_addresses_or_offsets_offset; int32_t search_end = info->_approx_addresses_or_offsets_end - pid_vnr_index * elem_size; - // search - for (pos = search_start; pos < search_end; pos += elem_size) { - int32_t vector_offset = - uint_unpack(img + pos + vector_index * elem_size, elem_size, info->is_be) - first_elem_val; - int32_t vector_next_offset = - uint_unpack(img + pos + vector_index * elem_size + elem_size, elem_size, info->is_be) - first_elem_val; - if (vector_next_offset - vector_offset >= 0x600 && (vector_offset & ((1 << 11) - 1)) == 0) { - int32_t pid_vnr_offset = - uint_unpack(img + pos + pid_vnr_index * elem_size, elem_size, info->is_be) - first_elem_val; - if (!arm64_verify_pid_vnr(info, img, pid_vnr_offset)) { - tools_logi("vectors offset: 0x%08x\n", vector_offset); - tools_logi("pid_vnr offset: 0x%08x\n", pid_vnr_offset); - break; + int break_flag = 0; + for (int i = 0; i < base_cand_num; i++) { + uint64_t base = base_cand[i]; + + for (pos = search_start; pos < search_end; pos += elem_size) { + int32_t vector_offset = uint_unpack(img + pos + vector_index * elem_size, elem_size, info->is_be) - base; + int32_t vector_next_offset = + uint_unpack(img + pos + vector_index * elem_size + elem_size, elem_size, info->is_be) - base; + if (vector_next_offset - vector_offset >= 0x600 && (vector_offset & ((1 << 11) - 1)) == 0) { + int32_t pid_vnr_offset = + uint_unpack(img + pos + pid_vnr_index * elem_size, elem_size, info->is_be) - base; + if (!arm64_verify_pid_vnr(info, img, pid_vnr_offset)) { + tools_logi("vectors index: %d, offset: 0x%08x\n", vector_index, vector_offset); + tools_logi("pid_vnr offset: 0x%08x\n", pid_vnr_offset); + info->kernel_base = base; + break_flag = 1; + break; + } } } + + if (break_flag) break; } + if (pos >= search_end) { tools_loge("can't locate vectors\n"); return -1; @@ -691,6 +727,7 @@ static int correct_addresses_or_offsets_by_vectors(kallsym_t *info, char *img, i } else { info->kallsyms_addresses_offset = pos; tools_logi("kallsyms_addresses offset: 0x%08x\n", pos); + tools_logi("kernel base address: 0x%08llx\n", info->kernel_base); } return 0; @@ -730,8 +767,8 @@ static int correct_addresses_or_offsets_by_banner(kallsym_t *info, char *img, in int32_t end = pos + 4096 + elem_size; for (; pos < end; pos += elem_size) { - uint64_t first_elem_val = uint_unpack(img + pos, elem_size, info->is_be); - int32_t offset = uint_unpack(img + pos + index * elem_size, elem_size, info->is_be) - first_elem_val; + uint64_t base = uint_unpack(img + pos, elem_size, info->is_be); + int32_t offset = uint_unpack(img + pos + index * elem_size, elem_size, info->is_be) - base; if (offset == target_offset) break; } if (pos < end) { @@ -741,16 +778,20 @@ static int correct_addresses_or_offsets_by_banner(kallsym_t *info, char *img, in } } if (info->symbol_banner_idx < 0) { - tools_loge("correct addressed or offsets error\n"); + tools_loge("correct address or offsets error\n"); return -1; } + int32_t elem_size = info->has_relative_base ? get_offsets_elem_size(info) : get_addresses_elem_size(info); + if (info->has_relative_base) { info->kallsyms_offsets_offset = pos; tools_logi("kallsyms_offsets offset: 0x%08x\n", pos); } else { info->kallsyms_addresses_offset = pos; tools_logi("kallsyms_addresses offset: 0x%08x\n", pos); + info->kernel_base = uint_unpack(img + info->kallsyms_addresses_offset, elem_size, info->is_be); + tools_logi("kernel base address: 0x%llx\n", info->kernel_base); } return 0; } @@ -787,7 +828,7 @@ void init_not_tested_arch_kallsym_t(kallsym_t *info, int32_t is_64) if (is_64) info->asm_PTR_size = 8; } -int retry_relo_retry(kallsym_t *info, char *img, int32_t imglen) +static int retry_relo(kallsym_t *info, char *img, int32_t imglen) { int rc = -1; static int32_t (*funcs[])(kallsym_t *, char *, int32_t) = { @@ -834,21 +875,21 @@ int analyze_kallsym_info(kallsym_t *info, char *img, int32_t imglen, enum arch_t memcpy(copied_img, img, imglen); // 1st - rc = retry_relo_retry(info, copied_img, imglen); + rc = retry_relo(info, copied_img, imglen); if (!rc) goto out; // 2nd if (!info->try_relo) { memcpy(copied_img, img, imglen); - rc = retry_relo_retry(info, copied_img, imglen); + rc = retry_relo(info, copied_img, imglen); if (!rc) goto out; } // 3rd - if (info->elf64_kernel_base != ELF64_KERNEL_MIN_VA) { - info->elf64_kernel_base = ELF64_KERNEL_MIN_VA; + if (info->kernel_base != ELF64_KERNEL_MIN_VA) { + info->kernel_base = ELF64_KERNEL_MIN_VA; memcpy(copied_img, img, imglen); - rc = retry_relo_retry(info, copied_img, imglen); + rc = retry_relo(info, copied_img, imglen); } out: @@ -868,9 +909,9 @@ int32_t get_symbol_index_offset(kallsym_t *info, char *img, int32_t index) elem_size = get_addresses_elem_size(info); pos = info->kallsyms_addresses_offset; } - uint64_t first = uint_unpack(img + pos, elem_size, info->is_be); uint64_t target = uint_unpack(img + pos + index * elem_size, elem_size, info->is_be); - return (int32_t)(target - first); + if (info->has_relative_base) return target; + return (int32_t)(target - info->kernel_base); } int get_symbol_offset_and_size(kallsym_t *info, char *img, char *symbol, int32_t *size) diff --git a/tools/kallsym.h b/tools/kallsym.h index 4643b162..da9d494a 100644 --- a/tools/kallsym.h +++ b/tools/kallsym.h @@ -98,31 +98,13 @@ typedef struct int32_t try_relo; int32_t relo_applied; + uint64_t kernel_base; + int32_t elf64_rela_num; int32_t elf64_rela_offset; - uint64_t elf64_kernel_base; - int32_t elf64_current_heuris; } kallsym_t; -#ifdef _WIN32 -#include -static void *memmem(const void *haystack, size_t haystack_len, const void *const needle, const size_t needle_len) -{ - if (haystack == NULL) return NULL; // or assert(haystack != NULL); - if (haystack_len == 0) return NULL; - if (needle == NULL) return NULL; // or assert(needle != NULL); - if (needle_len == 0) return NULL; - - for (const char *h = haystack; haystack_len >= needle_len; ++h, --haystack_len) { - if (!memcmp(h, needle, needle_len)) { - return (void *)h; - } - } - return NULL; -} -#endif - int analyze_kallsym_info(kallsym_t *info, char *img, int32_t imglen, enum arch_type arch, int32_t is_64); int dump_all_symbols(kallsym_t *info, char *img); int get_symbol_index_offset(kallsym_t *info, char *img, int32_t index); From c485790f4bdd860f0c0455192978532f897d6b93 Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 18 Aug 2024 23:09:46 +0800 Subject: [PATCH 30/71] a --- kernel/include/hook.h | 17 +- kernel/patch/common/syscall.c | 116 +-- kernel/patch/common/sysname.c | 1419 ++++++++++++++++---------------- kernel/patch/include/syscall.h | 13 +- kernel/patch/patch.c | 39 +- tools/kallsym.c | 17 +- tools/kallsym.h | 9 + 7 files changed, 829 insertions(+), 801 deletions(-) diff --git a/kernel/include/hook.h b/kernel/include/hook.h index d29cbd87..b9ced847 100644 --- a/kernel/include/hook.h +++ b/kernel/include/hook.h @@ -37,7 +37,7 @@ typedef int8_t chain_item_state; #define CHAIN_ITEM_STATE_BUSY 2 #define local_offsetof(TYPE, MEMBER) ((size_t) & ((TYPE *)0)->MEMBER) -#define local_container_of(ptr, type, member) ({ (type *)((char *)(ptr)-local_offsetof(type, member)); }) +#define local_container_of(ptr, type, member) ({ (type *)((char *)(ptr) - local_offsetof(type, member)); }) #define HOOK_MEM_REGION_NUM 4 #define TRAMPOLINE_NUM 4 @@ -319,7 +319,10 @@ static inline void hook_unwrap(void *func, void *before, void *after) return hook_unwrap_remove(func, before, after, 1); } -static inline void *hook_chain_origin_func(void *hook_args) +/** + * @param hook_args + */ +static inline void *wrap_get_origin_func(void *hook_args) { hook_fargs0_t *args = (hook_fargs0_t *)hook_args; hook_chain_t *chain = (hook_chain_t *)args->chain; @@ -364,6 +367,16 @@ hook_err_t fp_hook_wrap(uintptr_t fp_addr, int32_t argno, void *before, void *af */ void fp_hook_unwrap(uintptr_t fp_addr, void *before, void *after); +/** + * + */ +static inline void *fp_get_origin_func(void *hook_args) +{ + hook_fargs0_t *args = (hook_fargs0_t *)hook_args; + fp_hook_chain_t *chain = (fp_hook_chain_t *)args->chain; + return (void *)chain->hook.origin_fp; +} + static inline void hook_chain_install(hook_chain_t *chain) { hook_install(&chain->hook); diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index 337739a0..a0217baa 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -18,6 +18,7 @@ #include #include #include +#include #include uintptr_t *sys_call_table = 0; @@ -99,6 +100,49 @@ typedef long (*raw_syscall4_f)(long arg0, long arg1, long arg2, long arg3); typedef long (*raw_syscall5_f)(long arg0, long arg1, long arg2, long arg3, long arg4); typedef long (*raw_syscall6_f)(long arg0, long arg1, long arg2, long arg3, long arg4, long arg5); +uintptr_t syscalln_name_addr(int nr, int is_compat) +{ + const char *name = 0; + if (!is_compat) { + if (syscall_name_table[nr].addr) { + return syscall_name_table[nr].addr; + } + name = syscall_name_table[nr].name; + } else { + if (compat_syscall_name_table[nr].addr) { + return compat_syscall_name_table[nr].addr; + } + name = compat_syscall_name_table[nr].name; + } + if (!name) return 0; + + static const char *prefix[2] = { "__arm64_", "" }; + static const char *suffix[3] = { ".cfi_jt", ".cfi", "" }; + + uintptr_t addr = 0; + + char buffer[256]; + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 3; j++) { + snprintf(buffer, sizeof(buffer), "%s%s%s", prefix[i], name, suffix[j]); + addr = kallsyms_lookup_name(buffer); + if (addr) break; + } + } + if (!is_compat) { + syscall_name_table[nr].addr = addr; + } else { + compat_syscall_name_table[nr].addr = addr; + } + return addr; +} + +uintptr_t syscalln_addr(int nr, int is_compat) +{ + if (sys_call_table) return sys_call_table[nr]; + return syscalln_name_addr(nr, ); +} + long raw_syscall0(long nr) { uintptr_t addr = sys_call_table[nr]; @@ -205,22 +249,6 @@ long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 return ((raw_syscall6_f)addr)(arg0, arg1, arg2, arg3, arg4, arg5); } -uintptr_t syscalln_name_addr(int nr, int is_compat) -{ - const char *name = 0; - if (!is_compat) { - name = syscall_name_table[nr]; - } else { - name = compat_syscall_name_table[nr]; - } - if (!name) return 0; - char buffer[128] = "__arm64_"; - strlcat(buffer, name, 64); - uintptr_t addr = kallsyms_lookup_name(buffer); - if (!addr) addr = kallsyms_lookup_name(name); - return addr; -} - hook_err_t __inline_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) { uintptr_t addr = syscalln_name_addr(nr, is_compat); @@ -235,63 +263,10 @@ void __inline_unhook_syscalln(int nr, int is_compat, void *before, void *after) hook_unwrap((void *)addr, before, after); } -static uint64_t search_sys_call_table_addr() -{ - uint64_t addr = kernel_va; - uint64_t _etext = kallsyms_lookup_name("_etext"); - addr = addr > _etext ? addr : _etext; - - char *prefix[2]; - prefix[0] = "__arm64_"; - prefix[1] = ""; - - char *io_setup = "sys_io_setup"; - char *io_destory = "sys_io_destroy"; - - char *suffix[3]; - suffix[0] = ".cfi_jt"; - suffix[1] = ".cfi"; - suffix[2] = ""; - - char buf[128]; - - uint64_t sc0_addr = 0; - uint64_t sc1_addr = 0; - - int i = 0, k = 0; - - for (; k < 3; k++) { - i = 0; - for (; i < 2; i++) { - buf[0] = '\0'; - strcat(buf, prefix[i]); - strcat(buf, io_setup); - strcat(buf, suffix[k]); - sc0_addr = kallsyms_lookup_name(buf); - if (!sc0_addr) continue; - - buf[0] = '\0'; - strcat(buf, prefix[i]); - strcat(buf, io_destory); - strcat(buf, suffix[k]); - sc1_addr = kallsyms_lookup_name(buf); - if (!sc1_addr) return 0; - } - } - - for (; addr < kernel_va + kernel_size; addr += 8) { - uint64_t val0 = *(uint64_t *)addr; - if (val0 != sc0_addr) continue; - uint64_t val1 = *(uint64_t *)(addr + 8); - if (val1 == sc1_addr) return addr; - } - return 0; -} - void syscall_init() { for (int i = 0; i < sizeof(syscall_name_table) / sizeof(syscall_name_table[0]); i++) { - uintptr_t *addr = (uintptr_t *)syscall_name_table + i; + uintptr_t *addr = syscall_name_table[i].name; *addr = link2runtime(*addr); } @@ -301,7 +276,6 @@ void syscall_init() } sys_call_table = (typeof(sys_call_table))kallsyms_lookup_name("sys_call_table"); - if (!sys_call_table) sys_call_table = (typeof(sys_call_table))search_sys_call_table_addr(); log_boot("sys_call_table addr: %llx\n", sys_call_table); compat_sys_call_table = (typeof(compat_sys_call_table))kallsyms_lookup_name("compat_sys_call_table"); diff --git a/kernel/patch/common/sysname.c b/kernel/patch/common/sysname.c index 21e28f01..3a838a3f 100644 --- a/kernel/patch/common/sysname.c +++ b/kernel/patch/common/sysname.c @@ -1,712 +1,721 @@ #include +#include -const char *syscall_name_table[460] = { - [0] = "sys_io_setup", - [1] = "sys_io_destroy", - [2] = "sys_io_submit", - [3] = "sys_io_cancel", - [4] = "sys_io_getevents", - [5] = "sys_setxattr", - [6] = "sys_lsetxattr", - [7] = "sys_fsetxattr", - [8] = "sys_getxattr", - [9] = "sys_lgetxattr", - [10] = "sys_fgetxattr", - [11] = "sys_listxattr", - [12] = "sys_llistxattr", - [13] = "sys_flistxattr", - [14] = "sys_removexattr", - [15] = "sys_lremovexattr", - [16] = "sys_fremovexattr", - [17] = "sys_getcwd", - [19] = "sys_eventfd2", - [20] = "sys_epoll_create1", - [21] = "sys_epoll_ctl", - [22] = "sys_epoll_pwait", - [23] = "sys_dup", - [24] = "sys_dup3", - [25] = "sys_fcntl", - [26] = "sys_inotify_init1", - [27] = "sys_inotify_add_watch", - [28] = "sys_inotify_rm_watch", - [29] = "sys_ioctl", - [30] = "sys_ioprio_set", - [31] = "sys_ioprio_get", - [32] = "sys_flock", - [33] = "sys_mknodat", - [34] = "sys_mkdirat", - [35] = "sys_unlinkat", - [36] = "sys_symlinkat", - [37] = "sys_linkat", - [38] = "sys_renameat", - [39] = "sys_umount", - [40] = "sys_mount", - [41] = "sys_pivot_root", - [43] = "sys_statfs", - [44] = "sys_fstatfs", - [45] = "sys_truncate", - [46] = "sys_ftruncate", - [47] = "sys_fallocate", - [48] = "sys_faccessat", - [49] = "sys_chdir", - [50] = "sys_fchdir", - [51] = "sys_chroot", - [52] = "sys_fchmod", - [53] = "sys_fchmodat", - [54] = "sys_fchownat", - [55] = "sys_fchown", - [56] = "sys_openat", - [57] = "sys_close", - [58] = "sys_vhangup", - [59] = "sys_pipe2", - [60] = "sys_quotactl", - [61] = "sys_getdents64", - [62] = "sys_lseek", - [63] = "sys_read", - [64] = "sys_write", - [65] = "sys_readv", - [66] = "sys_writev", - [67] = "sys_pread64", - [68] = "sys_pwrite64", - [69] = "sys_preadv", - [70] = "sys_pwritev", - [71] = "sys_sendfile64", - [72] = "sys_pselect6", - [73] = "sys_ppoll", - [74] = "sys_signalfd4", - [75] = "sys_vmsplice", - [76] = "sys_splice", - [77] = "sys_tee", - [78] = "sys_readlinkat", - [79] = "sys_newfstatat", - [80] = "sys_newfstat", - [81] = "sys_sync", - [82] = "sys_fsync", - [83] = "sys_fdatasync", - [84] = "sys_sync_file_range", - [85] = "sys_timerfd_create", - [86] = "sys_timerfd_settime", - [87] = "sys_timerfd_gettime", - [88] = "sys_utimensat", - [89] = "sys_acct", - [90] = "sys_capget", - [91] = "sys_capset", - [92] = "sys_arm64_personality", - [93] = "sys_exit", - [94] = "sys_exit_group", - [95] = "sys_waitid", - [96] = "sys_set_tid_address", - [97] = "sys_unshare", - [98] = "sys_futex", - [99] = "sys_set_robust_list", - [100] = "sys_get_robust_list", - [101] = "sys_nanosleep", - [102] = "sys_getitimer", - [103] = "sys_setitimer", - [104] = "sys_kexec_load", - [105] = "sys_init_module", - [106] = "sys_delete_module", - [107] = "sys_timer_create", - [108] = "sys_timer_gettime", - [109] = "sys_timer_getoverrun", - [110] = "sys_timer_settime", - [111] = "sys_timer_delete", - [112] = "sys_clock_settime", - [113] = "sys_clock_gettime", - [114] = "sys_clock_getres", - [115] = "sys_clock_nanosleep", - [116] = "sys_syslog", - [117] = "sys_ptrace", - [118] = "sys_sched_setparam", - [119] = "sys_sched_setscheduler", - [120] = "sys_sched_getscheduler", - [121] = "sys_sched_getparam", - [122] = "sys_sched_setaffinity", - [123] = "sys_sched_getaffinity", - [124] = "sys_sched_yield", - [125] = "sys_sched_get_priority_max", - [126] = "sys_sched_get_priority_min", - [127] = "sys_sched_rr_get_interval", - [128] = "sys_restart_syscall", - [129] = "sys_kill", - [130] = "sys_tkill", - [131] = "sys_tgkill", - [132] = "sys_sigaltstack", - [133] = "sys_rt_sigsuspend", - [134] = "sys_rt_sigaction", - [135] = "sys_rt_sigprocmask", - [136] = "sys_rt_sigpending", - [137] = "sys_rt_sigtimedwait", - [138] = "sys_rt_sigqueueinfo", - [139] = "sys_rt_sigreturn", - [140] = "sys_setpriority", - [141] = "sys_getpriority", - [142] = "sys_reboot", - [143] = "sys_setregid", - [144] = "sys_setgid", - [145] = "sys_setreuid", - [146] = "sys_setuid", - [147] = "sys_setresuid", - [148] = "sys_getresuid", - [149] = "sys_setresgid", - [150] = "sys_getresgid", - [151] = "sys_setfsuid", - [152] = "sys_setfsgid", - [153] = "sys_times", - [154] = "sys_setpgid", - [155] = "sys_getpgid", - [156] = "sys_getsid", - [157] = "sys_setsid", - [158] = "sys_getgroups", - [159] = "sys_setgroups", - [160] = "sys_newuname", - [161] = "sys_sethostname", - [162] = "sys_setdomainname", - [163] = "sys_getrlimit", - [164] = "sys_setrlimit", - [165] = "sys_getrusage", - [166] = "sys_umask", - [167] = "sys_prctl", - [168] = "sys_getcpu", - [169] = "sys_gettimeofday", - [170] = "sys_settimeofday", - [171] = "sys_adjtimex", - [172] = "sys_getpid", - [173] = "sys_getppid", - [174] = "sys_getuid", - [175] = "sys_geteuid", - [176] = "sys_getgid", - [177] = "sys_getegid", - [178] = "sys_gettid", - [179] = "sys_sysinfo", - [180] = "sys_mq_open", - [181] = "sys_mq_unlink", - [182] = "sys_mq_timedsend", - [183] = "sys_mq_timedreceive", - [184] = "sys_mq_notify", - [185] = "sys_mq_getsetattr", - [186] = "sys_msgget", - [187] = "sys_msgctl", - [188] = "sys_msgrcv", - [189] = "sys_msgsnd", - [190] = "sys_semget", - [191] = "sys_semctl", - [192] = "sys_semtimedop", - [193] = "sys_semop", - [194] = "sys_shmget", - [195] = "sys_shmctl", - [196] = "sys_shmat", - [197] = "sys_shmdt", - [198] = "sys_socket", - [199] = "sys_socketpair", - [200] = "sys_bind", - [201] = "sys_listen", - [202] = "sys_accept", - [203] = "sys_connect", - [204] = "sys_getsockname", - [205] = "sys_getpeername", - [206] = "sys_sendto", - [207] = "sys_recvfrom", - [208] = "sys_setsockopt", - [209] = "sys_getsockopt", - [210] = "sys_shutdown", - [211] = "sys_sendmsg", - [212] = "sys_recvmsg", - [213] = "sys_readahead", - [214] = "sys_brk", - [215] = "sys_munmap", - [216] = "sys_mremap", - [217] = "sys_add_key", - [218] = "sys_request_key", - [219] = "sys_keyctl", - [220] = "sys_clone", - [221] = "sys_execve", - [222] = "sys_mmap", - [223] = "sys_fadvise64_64", - [224] = "sys_swapon", - [225] = "sys_swapoff", - [226] = "sys_mprotect", - [227] = "sys_msync", - [228] = "sys_mlock", - [229] = "sys_munlock", - [230] = "sys_mlockall", - [231] = "sys_munlockall", - [232] = "sys_mincore", - [233] = "sys_madvise", - [234] = "sys_remap_file_pages", - [235] = "sys_mbind", - [236] = "sys_get_mempolicy", - [237] = "sys_set_mempolicy", - [238] = "sys_migrate_pages", - [239] = "sys_move_pages", - [240] = "sys_rt_tgsigqueueinfo", - [241] = "sys_perf_event_open", - [242] = "sys_accept4", - [243] = "sys_recvmmsg", - [260] = "sys_wait4", - [261] = "sys_prlimit64", - [262] = "sys_fanotify_init", - [263] = "sys_fanotify_mark", - [264] = "sys_name_to_handle_at", - [265] = "sys_open_by_handle_at", - [266] = "sys_clock_adjtime", - [267] = "sys_syncfs", - [268] = "sys_setns", - [269] = "sys_sendmmsg", - [270] = "sys_process_vm_readv", - [271] = "sys_process_vm_writev", - [272] = "sys_kcmp", - [273] = "sys_finit_module", - [274] = "sys_sched_setattr", - [275] = "sys_sched_getattr", - [276] = "sys_renameat2", - [277] = "sys_seccomp", - [278] = "sys_getrandom", - [279] = "sys_memfd_create", - [280] = "sys_bpf", - [281] = "sys_execveat", - [282] = "sys_userfaultfd", - [283] = "sys_membarrier", - [284] = "sys_mlock2", - [285] = "sys_copy_file_range", - [286] = "sys_preadv2", - [287] = "sys_pwritev2", - [288] = "sys_pkey_mprotect", - [289] = "sys_pkey_alloc", - [290] = "sys_pkey_free", - [291] = "sys_statx", - [292] = "sys_io_pgetevents", - [293] = "sys_rseq", - [294] = "sys_kexec_file_load", - [424] = "sys_pidfd_send_signal", - [425] = "sys_io_uring_setup", - [426] = "sys_io_uring_enter", - [427] = "sys_io_uring_register", - [428] = "sys_open_tree", - [429] = "sys_move_mount", - [430] = "sys_fsopen", - [431] = "sys_fsconfig", - [432] = "sys_fsmount", - [433] = "sys_fspick", - [434] = "sys_pidfd_open", - [435] = "sys_clone3", - [436] = "sys_close_range", - [437] = "sys_openat2", - [438] = "sys_pidfd_getfd", - [439] = "sys_faccessat2", - [440] = "sys_process_madvise", - [441] = "sys_epoll_pwait2", - [442] = "sys_mount_setattr", - [443] = "sys_quotactl_fd", - [444] = "sys_landlock_create_ruleset", - [445] = "sys_landlock_add_rule", - [446] = "sys_landlock_restrict_self", - [447] = "sys_memfd_secret", - [448] = "sys_process_mrelease", - [449] = "sys_futex_waitv", - [450] = "sys_set_mempolicy_home_node", - [451] = "sys_cachestat", +struct +{ + const char *name; + uintptr_t addr; +} syscall_name_table[460] = { + [0] = { "sys_io_setup", 0 }, + [1] = { "sys_io_destroy", 0 }, + [2] = { "sys_io_submit", 0 }, + [3] = { "sys_io_cancel", 0 }, + [4] = { "sys_io_getevents", 0 }, + [5] = { "sys_setxattr", 0 }, + [6] = { "sys_lsetxattr", 0 }, + [7] = { "sys_fsetxattr", 0 }, + [8] = { "sys_getxattr", 0 }, + [9] = { "sys_lgetxattr", 0 }, + [10] = { "sys_fgetxattr", 0 }, + [11] = { "sys_listxattr", 0 }, + [12] = { "sys_llistxattr", 0 }, + [13] = { "sys_flistxattr", 0 }, + [14] = { "sys_removexattr", 0 }, + [15] = { "sys_lremovexattr", 0 }, + [16] = { "sys_fremovexattr", 0 }, + [17] = { "sys_getcwd", 0 }, + [19] = { "sys_eventfd2", 0 }, + [20] = { "sys_epoll_create1", 0 }, + [21] = { "sys_epoll_ctl", 0 }, + [22] = { "sys_epoll_pwait", 0 }, + [23] = { "sys_dup", 0 }, + [24] = { "sys_dup3", 0 }, + [25] = { "sys_fcntl", 0 }, + [26] = { "sys_inotify_init1", 0 }, + [27] = { "sys_inotify_add_watch", 0 }, + [28] = { "sys_inotify_rm_watch", 0 }, + [29] = { "sys_ioctl", 0 }, + [30] = { "sys_ioprio_set", 0 }, + [31] = { "sys_ioprio_get", 0 }, + [32] = { "sys_flock", 0 }, + [33] = { "sys_mknodat", 0 }, + [34] = { "sys_mkdirat", 0 }, + [35] = { "sys_unlinkat", 0 }, + [36] = { "sys_symlinkat", 0 }, + [37] = { "sys_linkat", 0 }, + [38] = { "sys_renameat", 0 }, + [39] = { "sys_umount", 0 }, + [40] = { "sys_mount", 0 }, + [41] = { "sys_pivot_root", 0 }, + [43] = { "sys_statfs", 0 }, + [44] = { "sys_fstatfs", 0 }, + [45] = { "sys_truncate", 0 }, + [46] = { "sys_ftruncate", 0 }, + [47] = { "sys_fallocate", 0 }, + [48] = { "sys_faccessat", 0 }, + [49] = { "sys_chdir", 0 }, + [50] = { "sys_fchdir", 0 }, + [51] = { "sys_chroot", 0 }, + [52] = { "sys_fchmod", 0 }, + [53] = { "sys_fchmodat", 0 }, + [54] = { "sys_fchownat", 0 }, + [55] = { "sys_fchown", 0 }, + [56] = { "sys_openat", 0 }, + [57] = { "sys_close", 0 }, + [58] = { "sys_vhangup", 0 }, + [59] = { "sys_pipe2", 0 }, + [60] = { "sys_quotactl", 0 }, + [61] = { "sys_getdents64", 0 }, + [62] = { "sys_lseek", 0 }, + [63] = { "sys_read", 0 }, + [64] = { "sys_write", 0 }, + [65] = { "sys_readv", 0 }, + [66] = { "sys_writev", 0 }, + [67] = { "sys_pread64", 0 }, + [68] = { "sys_pwrite64", 0 }, + [69] = { "sys_preadv", 0 }, + [70] = { "sys_pwritev", 0 }, + [71] = { "sys_sendfile64", 0 }, + [72] = { "sys_pselect6", 0 }, + [73] = { "sys_ppoll", 0 }, + [74] = { "sys_signalfd4", 0 }, + [75] = { "sys_vmsplice", 0 }, + [76] = { "sys_splice", 0 }, + [77] = { "sys_tee", 0 }, + [78] = { "sys_readlinkat", 0 }, + [79] = { "sys_newfstatat", 0 }, + [80] = { "sys_newfstat", 0 }, + [81] = { "sys_sync", 0 }, + [82] = { "sys_fsync", 0 }, + [83] = { "sys_fdatasync", 0 }, + [84] = { "sys_sync_file_range", 0 }, + [85] = { "sys_timerfd_create", 0 }, + [86] = { "sys_timerfd_settime", 0 }, + [87] = { "sys_timerfd_gettime", 0 }, + [88] = { "sys_utimensat", 0 }, + [89] = { "sys_acct", 0 }, + [90] = { "sys_capget", 0 }, + [91] = { "sys_capset", 0 }, + [92] = { "sys_arm64_personality", 0 }, + [93] = { "sys_exit", 0 }, + [94] = { "sys_exit_group", 0 }, + [95] = { "sys_waitid", 0 }, + [96] = { "sys_set_tid_address", 0 }, + [97] = { "sys_unshare", 0 }, + [98] = { "sys_futex", 0 }, + [99] = { "sys_set_robust_list", 0 }, + [100] = { "sys_get_robust_list", 0 }, + [101] = { "sys_nanosleep", 0 }, + [102] = { "sys_getitimer", 0 }, + [103] = { "sys_setitimer", 0 }, + [104] = { "sys_kexec_load", 0 }, + [105] = { "sys_init_module", 0 }, + [106] = { "sys_delete_module", 0 }, + [107] = { "sys_timer_create", 0 }, + [108] = { "sys_timer_gettime", 0 }, + [109] = { "sys_timer_getoverrun", 0 }, + [110] = { "sys_timer_settime", 0 }, + [111] = { "sys_timer_delete", 0 }, + [112] = { "sys_clock_settime", 0 }, + [113] = { "sys_clock_gettime", 0 }, + [114] = { "sys_clock_getres", 0 }, + [115] = { "sys_clock_nanosleep", 0 }, + [116] = { "sys_syslog", 0 }, + [117] = { "sys_ptrace", 0 }, + [118] = { "sys_sched_setparam", 0 }, + [119] = { "sys_sched_setscheduler", 0 }, + [120] = { "sys_sched_getscheduler", 0 }, + [121] = { "sys_sched_getparam", 0 }, + [122] = { "sys_sched_setaffinity", 0 }, + [123] = { "sys_sched_getaffinity", 0 }, + [124] = { "sys_sched_yield", 0 }, + [125] = { "sys_sched_get_priority_max", 0 }, + [126] = { "sys_sched_get_priority_min", 0 }, + [127] = { "sys_sched_rr_get_interval", 0 }, + [128] = { "sys_restart_syscall", 0 }, + [129] = { "sys_kill", 0 }, + [130] = { "sys_tkill", 0 }, + [131] = { "sys_tgkill", 0 }, + [132] = { "sys_sigaltstack", 0 }, + [133] = { "sys_rt_sigsuspend", 0 }, + [134] = { "sys_rt_sigaction", 0 }, + [135] = { "sys_rt_sigprocmask", 0 }, + [136] = { "sys_rt_sigpending", 0 }, + [137] = { "sys_rt_sigtimedwait", 0 }, + [138] = { "sys_rt_sigqueueinfo", 0 }, + [139] = { "sys_rt_sigreturn", 0 }, + [140] = { "sys_setpriority", 0 }, + [141] = { "sys_getpriority", 0 }, + [142] = { "sys_reboot", 0 }, + [143] = { "sys_setregid", 0 }, + [144] = { "sys_setgid", 0 }, + [145] = { "sys_setreuid", 0 }, + [146] = { "sys_setuid", 0 }, + [147] = { "sys_setresuid", 0 }, + [148] = { "sys_getresuid", 0 }, + [149] = { "sys_setresgid", 0 }, + [150] = { "sys_getresgid", 0 }, + [151] = { "sys_setfsuid", 0 }, + [152] = { "sys_setfsgid", 0 }, + [153] = { "sys_times", 0 }, + [154] = { "sys_setpgid", 0 }, + [155] = { "sys_getpgid", 0 }, + [156] = { "sys_getsid", 0 }, + [157] = { "sys_setsid", 0 }, + [158] = { "sys_getgroups", 0 }, + [159] = { "sys_setgroups", 0 }, + [160] = { "sys_newuname", 0 }, + [161] = { "sys_sethostname", 0 }, + [162] = { "sys_setdomainname", 0 }, + [163] = { "sys_getrlimit", 0 }, + [164] = { "sys_setrlimit", 0 }, + [165] = { "sys_getrusage", 0 }, + [166] = { "sys_umask", 0 }, + [167] = { "sys_prctl", 0 }, + [168] = { "sys_getcpu", 0 }, + [169] = { "sys_gettimeofday", 0 }, + [170] = { "sys_settimeofday", 0 }, + [171] = { "sys_adjtimex", 0 }, + [172] = { "sys_getpid", 0 }, + [173] = { "sys_getppid", 0 }, + [174] = { "sys_getuid", 0 }, + [175] = { "sys_geteuid", 0 }, + [176] = { "sys_getgid", 0 }, + [177] = { "sys_getegid", 0 }, + [178] = { "sys_gettid", 0 }, + [179] = { "sys_sysinfo", 0 }, + [180] = { "sys_mq_open", 0 }, + [181] = { "sys_mq_unlink", 0 }, + [182] = { "sys_mq_timedsend", 0 }, + [183] = { "sys_mq_timedreceive", 0 }, + [184] = { "sys_mq_notify", 0 }, + [185] = { "sys_mq_getsetattr", 0 }, + [186] = { "sys_msgget", 0 }, + [187] = { "sys_msgctl", 0 }, + [188] = { "sys_msgrcv", 0 }, + [189] = { "sys_msgsnd", 0 }, + [190] = { "sys_semget", 0 }, + [191] = { "sys_semctl", 0 }, + [192] = { "sys_semtimedop", 0 }, + [193] = { "sys_semop", 0 }, + [194] = { "sys_shmget", 0 }, + [195] = { "sys_shmctl", 0 }, + [196] = { "sys_shmat", 0 }, + [197] = { "sys_shmdt", 0 }, + [198] = { "sys_socket", 0 }, + [199] = { "sys_socketpair", 0 }, + [200] = { "sys_bind", 0 }, + [201] = { "sys_listen", 0 }, + [202] = { "sys_accept", 0 }, + [203] = { "sys_connect", 0 }, + [204] = { "sys_getsockname", 0 }, + [205] = { "sys_getpeername", 0 }, + [206] = { "sys_sendto", 0 }, + [207] = { "sys_recvfrom", 0 }, + [208] = { "sys_setsockopt", 0 }, + [209] = { "sys_getsockopt", 0 }, + [210] = { "sys_shutdown", 0 }, + [211] = { "sys_sendmsg", 0 }, + [212] = { "sys_recvmsg", 0 }, + [213] = { "sys_readahead", 0 }, + [214] = { "sys_brk", 0 }, + [215] = { "sys_munmap", 0 }, + [216] = { "sys_mremap", 0 }, + [217] = { "sys_add_key", 0 }, + [218] = { "sys_request_key", 0 }, + [219] = { "sys_keyctl", 0 }, + [220] = { "sys_clone", 0 }, + [221] = { "sys_execve", 0 }, + [222] = { "sys_mmap", 0 }, + [223] = { "sys_fadvise64_64", 0 }, + [224] = { "sys_swapon", 0 }, + [225] = { "sys_swapoff", 0 }, + [226] = { "sys_mprotect", 0 }, + [227] = { "sys_msync", 0 }, + [228] = { "sys_mlock", 0 }, + [229] = { "sys_munlock", 0 }, + [230] = { "sys_mlockall", 0 }, + [231] = { "sys_munlockall", 0 }, + [232] = { "sys_mincore", 0 }, + [233] = { "sys_madvise", 0 }, + [234] = { "sys_remap_file_pages", 0 }, + [235] = { "sys_mbind", 0 }, + [236] = { "sys_get_mempolicy", 0 }, + [237] = { "sys_set_mempolicy", 0 }, + [238] = { "sys_migrate_pages", 0 }, + [239] = { "sys_move_pages", 0 }, + [240] = { "sys_rt_tgsigqueueinfo", 0 }, + [241] = { "sys_perf_event_open", 0 }, + [242] = { "sys_accept4", 0 }, + [243] = { "sys_recvmmsg", 0 }, + [260] = { "sys_wait4", 0 }, + [261] = { "sys_prlimit64", 0 }, + [262] = { "sys_fanotify_init", 0 }, + [263] = { "sys_fanotify_mark", 0 }, + [264] = { "sys_name_to_handle_at", 0 }, + [265] = { "sys_open_by_handle_at", 0 }, + [266] = { "sys_clock_adjtime", 0 }, + [267] = { "sys_syncfs", 0 }, + [268] = { "sys_setns", 0 }, + [269] = { "sys_sendmmsg", 0 }, + [270] = { "sys_process_vm_readv", 0 }, + [271] = { "sys_process_vm_writev", 0 }, + [272] = { "sys_kcmp", 0 }, + [273] = { "sys_finit_module", 0 }, + [274] = { "sys_sched_setattr", 0 }, + [275] = { "sys_sched_getattr", 0 }, + [276] = { "sys_renameat2", 0 }, + [277] = { "sys_seccomp", 0 }, + [278] = { "sys_getrandom", 0 }, + [279] = { "sys_memfd_create", 0 }, + [280] = { "sys_bpf", 0 }, + [281] = { "sys_execveat", 0 }, + [282] = { "sys_userfaultfd", 0 }, + [283] = { "sys_membarrier", 0 }, + [284] = { "sys_mlock2", 0 }, + [285] = { "sys_copy_file_range", 0 }, + [286] = { "sys_preadv2", 0 }, + [287] = { "sys_pwritev2", 0 }, + [288] = { "sys_pkey_mprotect", 0 }, + [289] = { "sys_pkey_alloc", 0 }, + [290] = { "sys_pkey_free", 0 }, + [291] = { "sys_statx", 0 }, + [292] = { "sys_io_pgetevents", 0 }, + [293] = { "sys_rseq", 0 }, + [294] = { "sys_kexec_file_load", 0 }, + [424] = { "sys_pidfd_send_signal", 0 }, + [425] = { "sys_io_uring_setup", 0 }, + [426] = { "sys_io_uring_enter", 0 }, + [427] = { "sys_io_uring_register", 0 }, + [428] = { "sys_open_tree", 0 }, + [429] = { "sys_move_mount", 0 }, + [430] = { "sys_fsopen", 0 }, + [431] = { "sys_fsconfig", 0 }, + [432] = { "sys_fsmount", 0 }, + [433] = { "sys_fspick", 0 }, + [434] = { "sys_pidfd_open", 0 }, + [435] = { "sys_clone3", 0 }, + [436] = { "sys_close_range", 0 }, + [437] = { "sys_openat2", 0 }, + [438] = { "sys_pidfd_getfd", 0 }, + [439] = { "sys_faccessat2", 0 }, + [440] = { "sys_process_madvise", 0 }, + [441] = { "sys_epoll_pwait2", 0 }, + [442] = { "sys_mount_setattr", 0 }, + [443] = { "sys_quotactl_fd", 0 }, + [444] = { "sys_landlock_create_ruleset", 0 }, + [445] = { "sys_landlock_add_rule", 0 }, + [446] = { "sys_landlock_restrict_self", 0 }, + [447] = { "sys_memfd_secret", 0 }, + [448] = { "sys_process_mrelease", 0 }, + [449] = { "sys_futex_waitv", 0 }, + [450] = { "sys_set_mempolicy_home_node", 0 }, + [451] = { "sys_cachestat", 0 }, }; KP_EXPORT_SYMBOL(syscall_name_table); -const char *compat_syscall_name_table[460] = { - [0] = "sys_restart_syscall", - [1] = "sys_exit", - [2] = "sys_fork", - [3] = "sys_read", - [4] = "sys_write", - [5] = "sys_open", - [6] = "sys_close", - [8] = "sys_creat", - [9] = "sys_link", - [10] = "sys_unlink", - [11] = "sys_execve", - [12] = "sys_chdir", - [14] = "sys_mknod", - [15] = "sys_chmod", - [16] = "sys_lchown16", - [19] = "sys_lseek", - [20] = "sys_getpid", - [21] = "sys_mount", - [23] = "sys_setuid16", - [24] = "sys_getuid16", - [26] = "sys_ptrace", - [29] = "sys_pause", - [33] = "sys_access", - [34] = "sys_nice", - [36] = "sys_sync", - [37] = "sys_kill", - [38] = "sys_rename", - [39] = "sys_mkdir", - [40] = "sys_rmdir", - [41] = "sys_dup", - [42] = "sys_pipe", - [43] = "sys_times", - [45] = "sys_brk", - [46] = "sys_setgid16", - [47] = "sys_getgid16", - [49] = "sys_geteuid16", - [50] = "sys_getegid16", - [51] = "sys_acct", - [52] = "sys_umount", - [54] = "sys_ioctl", - [55] = "sys_fcntl", - [57] = "sys_setpgid", - [60] = "sys_umask", - [61] = "sys_chroot", - [62] = "sys_ustat", - [63] = "sys_dup2", - [64] = "sys_getppid", - [65] = "sys_getpgrp", - [66] = "sys_setsid", - [67] = "sys_sigaction", - [70] = "sys_setreuid16", - [71] = "sys_setregid16", - [72] = "sys_sigsuspend", - [73] = "sys_sigpending", - [74] = "sys_sethostname", - [75] = "sys_setrlimit", - [77] = "sys_getrusage", - [78] = "sys_gettimeofday", - [79] = "sys_settimeofday", - [80] = "sys_getgroups16", - [81] = "sys_setgroups16", - [83] = "sys_symlink", - [85] = "sys_readlink", - [86] = "sys_uselib", - [87] = "sys_swapon", - [88] = "sys_reboot", - [91] = "sys_munmap", - [92] = "sys_truncate", - [93] = "sys_ftruncate", - [94] = "sys_fchmod", - [95] = "sys_fchown16", - [96] = "sys_getpriority", - [97] = "sys_setpriority", - [99] = "sys_statfs", - [100] = "sys_fstatfs", - [103] = "sys_syslog", - [104] = "sys_setitimer", - [105] = "sys_getitimer", - [106] = "sys_newstat", - [107] = "sys_newlstat", - [108] = "sys_newfstat", - [111] = "sys_vhangup", - [114] = "sys_wait4", - [115] = "sys_swapoff", - [116] = "sys_sysinfo", - [118] = "sys_fsync", - [119] = "sys_sigreturn", - [120] = "sys_clone", - [121] = "sys_setdomainname", - [122] = "sys_newuname", - [124] = "sys_adjtimex_time32", - [125] = "sys_mprotect", - [126] = "sys_sigprocmask", - [128] = "sys_init_module", - [129] = "sys_delete_module", - [131] = "sys_quotactl", - [132] = "sys_getpgid", - [133] = "sys_fchdir", - [135] = "sys_sysfs", - [136] = "sys_personality", - [138] = "sys_setfsuid16", - [139] = "sys_setfsgid16", - [140] = "sys_llseek", - [141] = "sys_getdents", - [142] = "sys_select", - [143] = "sys_flock", - [144] = "sys_msync", - [145] = "sys_readv", - [146] = "sys_writev", - [147] = "sys_getsid", - [148] = "sys_fdatasync", - [150] = "sys_mlock", - [151] = "sys_munlock", - [152] = "sys_mlockall", - [153] = "sys_munlockall", - [154] = "sys_sched_setparam", - [155] = "sys_sched_getparam", - [156] = "sys_sched_setscheduler", - [157] = "sys_sched_getscheduler", - [158] = "sys_sched_yield", - [159] = "sys_sched_get_priority_max", - [160] = "sys_sched_get_priority_min", - [161] = "sys_sched_rr_get_interval_time32", - [162] = "sys_nanosleep_time32", - [163] = "sys_mremap", - [164] = "sys_setresuid16", - [165] = "sys_getresuid16", - [168] = "sys_poll", - [170] = "sys_setresgid16", - [171] = "sys_getresgid16", - [172] = "sys_prctl", - [173] = "sys_rt_sigreturn", - [174] = "sys_rt_sigaction", - [175] = "sys_rt_sigprocmask", - [176] = "sys_rt_sigpending", - [177] = "sys_rt_sigtimedwait_time32", - [178] = "sys_rt_sigqueueinfo", - [179] = "sys_rt_sigsuspend", - [180] = "sys_aarch32_pread64", - [181] = "sys_aarch32_pwrite64", - [182] = "sys_chown16", - [183] = "sys_getcwd", - [184] = "sys_capget", - [185] = "sys_capset", - [186] = "sys_sigaltstack", - [187] = "sys_sendfile", - [190] = "sys_vfork", - [191] = "sys_getrlimit", - [192] = "sys_aarch32_mmap2", - [193] = "sys_aarch32_truncate64", - [194] = "sys_aarch32_ftruncate64", - [195] = "sys_stat64", - [196] = "sys_lstat64", - [197] = "sys_fstat64", - [198] = "sys_lchown", - [199] = "sys_getuid", - [200] = "sys_getgid", - [201] = "sys_geteuid", - [202] = "sys_getegid", - [203] = "sys_setreuid", - [204] = "sys_setregid", - [205] = "sys_getgroups", - [206] = "sys_setgroups", - [207] = "sys_fchown", - [208] = "sys_setresuid", - [209] = "sys_getresuid", - [210] = "sys_setresgid", - [211] = "sys_getresgid", - [212] = "sys_chown", - [213] = "sys_setuid", - [214] = "sys_setgid", - [215] = "sys_setfsuid", - [216] = "sys_setfsgid", - [217] = "sys_getdents64", - [218] = "sys_pivot_root", - [219] = "sys_mincore", - [220] = "sys_madvise", - [221] = "sys_fcntl64", - [224] = "sys_gettid", - [225] = "sys_aarch32_readahead", - [226] = "sys_setxattr", - [227] = "sys_lsetxattr", - [228] = "sys_fsetxattr", - [229] = "sys_getxattr", - [230] = "sys_lgetxattr", - [231] = "sys_fgetxattr", - [232] = "sys_listxattr", - [233] = "sys_llistxattr", - [234] = "sys_flistxattr", - [235] = "sys_removexattr", - [236] = "sys_lremovexattr", - [237] = "sys_fremovexattr", - [238] = "sys_tkill", - [239] = "sys_sendfile64", - [240] = "sys_futex_time32", - [241] = "sys_sched_setaffinity", - [242] = "sys_sched_getaffinity", - [243] = "sys_io_setup", - [244] = "sys_io_destroy", - [245] = "sys_io_getevents_time32", - [246] = "sys_io_submit", - [247] = "sys_io_cancel", - [248] = "sys_exit_group", - [250] = "sys_epoll_create", - [251] = "sys_epoll_ctl", - [252] = "sys_epoll_wait", - [253] = "sys_remap_file_pages", - [256] = "sys_set_tid_address", - [257] = "sys_timer_create", - [258] = "sys_timer_settime32", - [259] = "sys_timer_gettime32", - [260] = "sys_timer_getoverrun", - [261] = "sys_timer_delete", - [262] = "sys_clock_settime32", - [263] = "sys_clock_gettime32", - [264] = "sys_clock_getres_time32", - [265] = "sys_clock_nanosleep_time32", - [266] = "sys_aarch32_statfs64", - [267] = "sys_aarch32_fstatfs64", - [268] = "sys_tgkill", - [269] = "sys_utimes_time32", - [270] = "sys_aarch32_fadvise64_64", - [272] = "sys_pciconfig_read", - [273] = "sys_pciconfig_write", - [274] = "sys_mq_open", - [275] = "sys_mq_unlink", - [276] = "sys_mq_timedsend_time32", - [277] = "sys_mq_timedreceive_time32", - [278] = "sys_mq_notify", - [279] = "sys_mq_getsetattr", - [280] = "sys_waitid", - [281] = "sys_socket", - [282] = "sys_bind", - [283] = "sys_connect", - [284] = "sys_listen", - [285] = "sys_accept", - [286] = "sys_getsockname", - [287] = "sys_getpeername", - [288] = "sys_socketpair", - [289] = "sys_send", - [290] = "sys_sendto", - [291] = "sys_recv", - [292] = "sys_recvfrom", - [293] = "sys_shutdown", - [294] = "sys_setsockopt", - [295] = "sys_getsockopt", - [296] = "sys_sendmsg", - [297] = "sys_recvmsg", - [298] = "sys_semop", - [299] = "sys_semget", - [300] = "sys_old_semctl", - [301] = "sys_msgsnd", - [302] = "sys_msgrcv", - [303] = "sys_msgget", - [304] = "sys_old_msgctl", - [305] = "sys_shmat", - [306] = "sys_shmdt", - [307] = "sys_shmget", - [308] = "sys_old_shmctl", - [309] = "sys_add_key", - [310] = "sys_request_key", - [311] = "sys_keyctl", - [312] = "sys_semtimedop_time32", - [314] = "sys_ioprio_set", - [315] = "sys_ioprio_get", - [316] = "sys_inotify_init", - [317] = "sys_inotify_add_watch", - [318] = "sys_inotify_rm_watch", - [319] = "sys_mbind", - [320] = "sys_get_mempolicy", - [321] = "sys_set_mempolicy", - [322] = "sys_openat", - [323] = "sys_mkdirat", - [324] = "sys_mknodat", - [325] = "sys_fchownat", - [326] = "sys_futimesat_time32", - [327] = "sys_fstatat64", - [328] = "sys_unlinkat", - [329] = "sys_renameat", - [330] = "sys_linkat", - [331] = "sys_symlinkat", - [332] = "sys_readlinkat", - [333] = "sys_fchmodat", - [334] = "sys_faccessat", - [335] = "sys_pselect6_time32", - [336] = "sys_ppoll_time32", - [337] = "sys_unshare", - [338] = "sys_set_robust_list", - [339] = "sys_get_robust_list", - [340] = "sys_splice", - [341] = "sys_aarch32_sync_file_range2", - [342] = "sys_tee", - [343] = "sys_vmsplice", - [344] = "sys_move_pages", - [345] = "sys_getcpu", - [346] = "sys_epoll_pwait", - [347] = "sys_kexec_load", - [348] = "sys_utimensat_time32", - [349] = "sys_signalfd", - [350] = "sys_timerfd_create", - [351] = "sys_eventfd", - [352] = "sys_aarch32_fallocate", - [353] = "sys_timerfd_settime32", - [354] = "sys_timerfd_gettime32", - [355] = "sys_signalfd4", - [356] = "sys_eventfd2", - [357] = "sys_epoll_create1", - [358] = "sys_dup3", - [359] = "sys_pipe2", - [360] = "sys_inotify_init1", - [361] = "sys_preadv", - [362] = "sys_pwritev", - [363] = "sys_rt_tgsigqueueinfo", - [364] = "sys_perf_event_open", - [365] = "sys_recvmmsg_time32", - [366] = "sys_accept4", - [367] = "sys_fanotify_init", - [368] = "sys_fanotify_mark", - [369] = "sys_prlimit64", - [370] = "sys_name_to_handle_at", - [371] = "sys_open_by_handle_at", - [372] = "sys_clock_adjtime32", - [373] = "sys_syncfs", - [374] = "sys_sendmmsg", - [375] = "sys_setns", - [376] = "sys_process_vm_readv", - [377] = "sys_process_vm_writev", - [378] = "sys_kcmp", - [379] = "sys_finit_module", - [380] = "sys_sched_setattr", - [381] = "sys_sched_getattr", - [382] = "sys_renameat2", - [383] = "sys_seccomp", - [384] = "sys_getrandom", - [385] = "sys_memfd_create", - [386] = "sys_bpf", - [387] = "sys_execveat", - [388] = "sys_userfaultfd", - [389] = "sys_membarrier", - [390] = "sys_mlock2", - [391] = "sys_copy_file_range", - [392] = "sys_preadv2", - [393] = "sys_pwritev2", - [394] = "sys_pkey_mprotect", - [395] = "sys_pkey_alloc", - [396] = "sys_pkey_free", - [397] = "sys_statx", - [398] = "sys_rseq", - [399] = "sys_io_pgetevents", - [400] = "sys_migrate_pages", - [401] = "sys_kexec_file_load", - [403] = "sys_clock_gettime", - [404] = "sys_clock_settime", - [405] = "sys_clock_adjtime", - [406] = "sys_clock_getres", - [407] = "sys_clock_nanosleep", - [408] = "sys_timer_gettime", - [409] = "sys_timer_settime", - [410] = "sys_timerfd_gettime", - [411] = "sys_timerfd_settime", - [412] = "sys_utimensat", - [413] = "sys_pselect6_time64", - [414] = "sys_ppoll_time64", - [416] = "sys_io_pgetevents", - [417] = "sys_recvmmsg_time64", - [418] = "sys_mq_timedsend", - [419] = "sys_mq_timedreceive", - [420] = "sys_semtimedop", - [421] = "sys_rt_sigtimedwait_time64", - [422] = "sys_futex", - [423] = "sys_sched_rr_get_interval", - [424] = "sys_pidfd_send_signal", - [425] = "sys_io_uring_setup", - [426] = "sys_io_uring_enter", - [427] = "sys_io_uring_register", - [428] = "sys_open_tree", - [429] = "sys_move_mount", - [430] = "sys_fsopen", - [431] = "sys_fsconfig", - [432] = "sys_fsmount", - [433] = "sys_fspick", - [434] = "sys_pidfd_open", - [435] = "sys_clone3", - [436] = "sys_close_range", - [437] = "sys_openat2", - [438] = "sys_pidfd_getfd", - [439] = "sys_faccessat2", - [440] = "sys_process_madvise", - [441] = "sys_epoll_pwait2", - [442] = "sys_mount_setattr", - [443] = "sys_quotactl_fd", - [444] = "sys_landlock_create_ruleset", - [445] = "sys_landlock_add_rule", - [446] = "sys_landlock_restrict_self", - [448] = "sys_process_mrelease", - [449] = "sys_futex_waitv", - [450] = "sys_set_mempolicy_home_node", - [451] = "sys_cachestat", +struct +{ + const char *name; + uintptr_t addr; +} compat_syscall_name_table[460] = { + [0] = { "sys_restart_syscall", 0 }, + [1] = { "sys_exit", 0 }, + [2] = { "sys_fork", 0 }, + [3] = { "sys_read", 0 }, + [4] = { "sys_write", 0 }, + [5] = { "sys_open", 0 }, + [6] = { "sys_close", 0 }, + [8] = { "sys_creat", 0 }, + [9] = { "sys_link", 0 }, + [10] = { "sys_unlink", 0 }, + [11] = { "sys_execve", 0 }, + [12] = { "sys_chdir", 0 }, + [14] = { "sys_mknod", 0 }, + [15] = { "sys_chmod", 0 }, + [16] = { "sys_lchown16", 0 }, + [19] = { "sys_lseek", 0 }, + [20] = { "sys_getpid", 0 }, + [21] = { "sys_mount", 0 }, + [23] = { "sys_setuid16", 0 }, + [24] = { "sys_getuid16", 0 }, + [26] = { "sys_ptrace", 0 }, + [29] = { "sys_pause", 0 }, + [33] = { "sys_access", 0 }, + [34] = { "sys_nice", 0 }, + [36] = { "sys_sync", 0 }, + [37] = { "sys_kill", 0 }, + [38] = { "sys_rename", 0 }, + [39] = { "sys_mkdir", 0 }, + [40] = { "sys_rmdir", 0 }, + [41] = { "sys_dup", 0 }, + [42] = { "sys_pipe", 0 }, + [43] = { "sys_times", 0 }, + [45] = { "sys_brk", 0 }, + [46] = { "sys_setgid16", 0 }, + [47] = { "sys_getgid16", 0 }, + [49] = { "sys_geteuid16", 0 }, + [50] = { "sys_getegid16", 0 }, + [51] = { "sys_acct", 0 }, + [52] = { "sys_umount", 0 }, + [54] = { "sys_ioctl", 0 }, + [55] = { "sys_fcntl", 0 }, + [57] = { "sys_setpgid", 0 }, + [60] = { "sys_umask", 0 }, + [61] = { "sys_chroot", 0 }, + [62] = { "sys_ustat", 0 }, + [63] = { "sys_dup2", 0 }, + [64] = { "sys_getppid", 0 }, + [65] = { "sys_getpgrp", 0 }, + [66] = { "sys_setsid", 0 }, + [67] = { "sys_sigaction", 0 }, + [70] = { "sys_setreuid16", 0 }, + [71] = { "sys_setregid16", 0 }, + [72] = { "sys_sigsuspend", 0 }, + [73] = { "sys_sigpending", 0 }, + [74] = { "sys_sethostname", 0 }, + [75] = { "sys_setrlimit", 0 }, + [77] = { "sys_getrusage", 0 }, + [78] = { "sys_gettimeofday", 0 }, + [79] = { "sys_settimeofday", 0 }, + [80] = { "sys_getgroups16", 0 }, + [81] = { "sys_setgroups16", 0 }, + [83] = { "sys_symlink", 0 }, + [85] = { "sys_readlink", 0 }, + [86] = { "sys_uselib", 0 }, + [87] = { "sys_swapon", 0 }, + [88] = { "sys_reboot", 0 }, + [91] = { "sys_munmap", 0 }, + [92] = { "sys_truncate", 0 }, + [93] = { "sys_ftruncate", 0 }, + [94] = { "sys_fchmod", 0 }, + [95] = { "sys_fchown16", 0 }, + [96] = { "sys_getpriority", 0 }, + [97] = { "sys_setpriority", 0 }, + [99] = { "sys_statfs", 0 }, + [100] = { "sys_fstatfs", 0 }, + [103] = { "sys_syslog", 0 }, + [104] = { "sys_setitimer", 0 }, + [105] = { "sys_getitimer", 0 }, + [106] = { "sys_newstat", 0 }, + [107] = { "sys_newlstat", 0 }, + [108] = { "sys_newfstat", 0 }, + [111] = { "sys_vhangup", 0 }, + [114] = { "sys_wait4", 0 }, + [115] = { "sys_swapoff", 0 }, + [116] = { "sys_sysinfo", 0 }, + [118] = { "sys_fsync", 0 }, + [119] = { "sys_sigreturn", 0 }, + [120] = { "sys_clone", 0 }, + [121] = { "sys_setdomainname", 0 }, + [122] = { "sys_newuname", 0 }, + [124] = { "sys_adjtimex_time32", 0 }, + [125] = { "sys_mprotect", 0 }, + [126] = { "sys_sigprocmask", 0 }, + [128] = { "sys_init_module", 0 }, + [129] = { "sys_delete_module", 0 }, + [131] = { "sys_quotactl", 0 }, + [132] = { "sys_getpgid", 0 }, + [133] = { "sys_fchdir", 0 }, + [135] = { "sys_sysfs", 0 }, + [136] = { "sys_personality", 0 }, + [138] = { "sys_setfsuid16", 0 }, + [139] = { "sys_setfsgid16", 0 }, + [140] = { "sys_llseek", 0 }, + [141] = { "sys_getdents", 0 }, + [142] = { "sys_select", 0 }, + [143] = { "sys_flock", 0 }, + [144] = { "sys_msync", 0 }, + [145] = { "sys_readv", 0 }, + [146] = { "sys_writev", 0 }, + [147] = { "sys_getsid", 0 }, + [148] = { "sys_fdatasync", 0 }, + [150] = { "sys_mlock", 0 }, + [151] = { "sys_munlock", 0 }, + [152] = { "sys_mlockall", 0 }, + [153] = { "sys_munlockall", 0 }, + [154] = { "sys_sched_setparam", 0 }, + [155] = { "sys_sched_getparam", 0 }, + [156] = { "sys_sched_setscheduler", 0 }, + [157] = { "sys_sched_getscheduler", 0 }, + [158] = { "sys_sched_yield", 0 }, + [159] = { "sys_sched_get_priority_max", 0 }, + [160] = { "sys_sched_get_priority_min", 0 }, + [161] = { "sys_sched_rr_get_interval_time32", 0 }, + [162] = { "sys_nanosleep_time32", 0 }, + [163] = { "sys_mremap", 0 }, + [164] = { "sys_setresuid16", 0 }, + [165] = { "sys_getresuid16", 0 }, + [168] = { "sys_poll", 0 }, + [170] = { "sys_setresgid16", 0 }, + [171] = { "sys_getresgid16", 0 }, + [172] = { "sys_prctl", 0 }, + [173] = { "sys_rt_sigreturn", 0 }, + [174] = { "sys_rt_sigaction", 0 }, + [175] = { "sys_rt_sigprocmask", 0 }, + [176] = { "sys_rt_sigpending", 0 }, + [177] = { "sys_rt_sigtimedwait_time32", 0 }, + [178] = { "sys_rt_sigqueueinfo", 0 }, + [179] = { "sys_rt_sigsuspend", 0 }, + [180] = { "sys_aarch32_pread64", 0 }, + [181] = { "sys_aarch32_pwrite64", 0 }, + [182] = { "sys_chown16", 0 }, + [183] = { "sys_getcwd", 0 }, + [184] = { "sys_capget", 0 }, + [185] = { "sys_capset", 0 }, + [186] = { "sys_sigaltstack", 0 }, + [187] = { "sys_sendfile", 0 }, + [190] = { "sys_vfork", 0 }, + [191] = { "sys_getrlimit", 0 }, + [192] = { "sys_aarch32_mmap2", 0 }, + [193] = { "sys_aarch32_truncate64", 0 }, + [194] = { "sys_aarch32_ftruncate64", 0 }, + [195] = { "sys_stat64", 0 }, + [196] = { "sys_lstat64", 0 }, + [197] = { "sys_fstat64", 0 }, + [198] = { "sys_lchown", 0 }, + [199] = { "sys_getuid", 0 }, + [200] = { "sys_getgid", 0 }, + [201] = { "sys_geteuid", 0 }, + [202] = { "sys_getegid", 0 }, + [203] = { "sys_setreuid", 0 }, + [204] = { "sys_setregid", 0 }, + [205] = { "sys_getgroups", 0 }, + [206] = { "sys_setgroups", 0 }, + [207] = { "sys_fchown", 0 }, + [208] = { "sys_setresuid", 0 }, + [209] = { "sys_getresuid", 0 }, + [210] = { "sys_setresgid", 0 }, + [211] = { "sys_getresgid", 0 }, + [212] = { "sys_chown", 0 }, + [213] = { "sys_setuid", 0 }, + [214] = { "sys_setgid", 0 }, + [215] = { "sys_setfsuid", 0 }, + [216] = { "sys_setfsgid", 0 }, + [217] = { "sys_getdents64", 0 }, + [218] = { "sys_pivot_root", 0 }, + [219] = { "sys_mincore", 0 }, + [220] = { "sys_madvise", 0 }, + [221] = { "sys_fcntl64", 0 }, + [224] = { "sys_gettid", 0 }, + [225] = { "sys_aarch32_readahead", 0 }, + [226] = { "sys_setxattr", 0 }, + [227] = { "sys_lsetxattr", 0 }, + [228] = { "sys_fsetxattr", 0 }, + [229] = { "sys_getxattr", 0 }, + [230] = { "sys_lgetxattr", 0 }, + [231] = { "sys_fgetxattr", 0 }, + [232] = { "sys_listxattr", 0 }, + [233] = { "sys_llistxattr", 0 }, + [234] = { "sys_flistxattr", 0 }, + [235] = { "sys_removexattr", 0 }, + [236] = { "sys_lremovexattr", 0 }, + [237] = { "sys_fremovexattr", 0 }, + [238] = { "sys_tkill", 0 }, + [239] = { "sys_sendfile64", 0 }, + [240] = { "sys_futex_time32", 0 }, + [241] = { "sys_sched_setaffinity", 0 }, + [242] = { "sys_sched_getaffinity", 0 }, + [243] = { "sys_io_setup", 0 }, + [244] = { "sys_io_destroy", 0 }, + [245] = { "sys_io_getevents_time32", 0 }, + [246] = { "sys_io_submit", 0 }, + [247] = { "sys_io_cancel", 0 }, + [248] = { "sys_exit_group", 0 }, + [250] = { "sys_epoll_create", 0 }, + [251] = { "sys_epoll_ctl", 0 }, + [252] = { "sys_epoll_wait", 0 }, + [253] = { "sys_remap_file_pages", 0 }, + [256] = { "sys_set_tid_address", 0 }, + [257] = { "sys_timer_create", 0 }, + [258] = { "sys_timer_settime32", 0 }, + [259] = { "sys_timer_gettime32", 0 }, + [260] = { "sys_timer_getoverrun", 0 }, + [261] = { "sys_timer_delete", 0 }, + [262] = { "sys_clock_settime32", 0 }, + [263] = { "sys_clock_gettime32", 0 }, + [264] = { "sys_clock_getres_time32", 0 }, + [265] = { "sys_clock_nanosleep_time32", 0 }, + [266] = { "sys_aarch32_statfs64", 0 }, + [267] = { "sys_aarch32_fstatfs64", 0 }, + [268] = { "sys_tgkill", 0 }, + [269] = { "sys_utimes_time32", 0 }, + [270] = { "sys_aarch32_fadvise64_64", 0 }, + [272] = { "sys_pciconfig_read", 0 }, + [273] = { "sys_pciconfig_write", 0 }, + [274] = { "sys_mq_open", 0 }, + [275] = { "sys_mq_unlink", 0 }, + [276] = { "sys_mq_timedsend_time32", 0 }, + [277] = { "sys_mq_timedreceive_time32", 0 }, + [278] = { "sys_mq_notify", 0 }, + [279] = { "sys_mq_getsetattr", 0 }, + [280] = { "sys_waitid", 0 }, + [281] = { "sys_socket", 0 }, + [282] = { "sys_bind", 0 }, + [283] = { "sys_connect", 0 }, + [284] = { "sys_listen", 0 }, + [285] = { "sys_accept", 0 }, + [286] = { "sys_getsockname", 0 }, + [287] = { "sys_getpeername", 0 }, + [288] = { "sys_socketpair", 0 }, + [289] = { "sys_send", 0 }, + [290] = { "sys_sendto", 0 }, + [291] = { "sys_recv", 0 }, + [292] = { "sys_recvfrom", 0 }, + [293] = { "sys_shutdown", 0 }, + [294] = { "sys_setsockopt", 0 }, + [295] = { "sys_getsockopt", 0 }, + [296] = { "sys_sendmsg", 0 }, + [297] = { "sys_recvmsg", 0 }, + [298] = { "sys_semop", 0 }, + [299] = { "sys_semget", 0 }, + [300] = { "sys_old_semctl", 0 }, + [301] = { "sys_msgsnd", 0 }, + [302] = { "sys_msgrcv", 0 }, + [303] = { "sys_msgget", 0 }, + [304] = { "sys_old_msgctl", 0 }, + [305] = { "sys_shmat", 0 }, + [306] = { "sys_shmdt", 0 }, + [307] = { "sys_shmget", 0 }, + [308] = { "sys_old_shmctl", 0 }, + [309] = { "sys_add_key", 0 }, + [310] = { "sys_request_key", 0 }, + [311] = { "sys_keyctl", 0 }, + [312] = { "sys_semtimedop_time32", 0 }, + [314] = { "sys_ioprio_set", 0 }, + [315] = { "sys_ioprio_get", 0 }, + [316] = { "sys_inotify_init", 0 }, + [317] = { "sys_inotify_add_watch", 0 }, + [318] = { "sys_inotify_rm_watch", 0 }, + [319] = { "sys_mbind", 0 }, + [320] = { "sys_get_mempolicy", 0 }, + [321] = { "sys_set_mempolicy", 0 }, + [322] = { "sys_openat", 0 }, + [323] = { "sys_mkdirat", 0 }, + [324] = { "sys_mknodat", 0 }, + [325] = { "sys_fchownat", 0 }, + [326] = { "sys_futimesat_time32", 0 }, + [327] = { "sys_fstatat64", 0 }, + [328] = { "sys_unlinkat", 0 }, + [329] = { "sys_renameat", 0 }, + [330] = { "sys_linkat", 0 }, + [331] = { "sys_symlinkat", 0 }, + [332] = { "sys_readlinkat", 0 }, + [333] = { "sys_fchmodat", 0 }, + [334] = { "sys_faccessat", 0 }, + [335] = { "sys_pselect6_time32", 0 }, + [336] = { "sys_ppoll_time32", 0 }, + [337] = { "sys_unshare", 0 }, + [338] = { "sys_set_robust_list", 0 }, + [339] = { "sys_get_robust_list", 0 }, + [340] = { "sys_splice", 0 }, + [341] = { "sys_aarch32_sync_file_range2", 0 }, + [342] = { "sys_tee", 0 }, + [343] = { "sys_vmsplice", 0 }, + [344] = { "sys_move_pages", 0 }, + [345] = { "sys_getcpu", 0 }, + [346] = { "sys_epoll_pwait", 0 }, + [347] = { "sys_kexec_load", 0 }, + [348] = { "sys_utimensat_time32", 0 }, + [349] = { "sys_signalfd", 0 }, + [350] = { "sys_timerfd_create", 0 }, + [351] = { "sys_eventfd", 0 }, + [352] = { "sys_aarch32_fallocate", 0 }, + [353] = { "sys_timerfd_settime32", 0 }, + [354] = { "sys_timerfd_gettime32", 0 }, + [355] = { "sys_signalfd4", 0 }, + [356] = { "sys_eventfd2", 0 }, + [357] = { "sys_epoll_create1", 0 }, + [358] = { "sys_dup3", 0 }, + [359] = { "sys_pipe2", 0 }, + [360] = { "sys_inotify_init1", 0 }, + [361] = { "sys_preadv", 0 }, + [362] = { "sys_pwritev", 0 }, + [363] = { "sys_rt_tgsigqueueinfo", 0 }, + [364] = { "sys_perf_event_open", 0 }, + [365] = { "sys_recvmmsg_time32", 0 }, + [366] = { "sys_accept4", 0 }, + [367] = { "sys_fanotify_init", 0 }, + [368] = { "sys_fanotify_mark", 0 }, + [369] = { "sys_prlimit64", 0 }, + [370] = { "sys_name_to_handle_at", 0 }, + [371] = { "sys_open_by_handle_at", 0 }, + [372] = { "sys_clock_adjtime32", 0 }, + [373] = { "sys_syncfs", 0 }, + [374] = { "sys_sendmmsg", 0 }, + [375] = { "sys_setns", 0 }, + [376] = { "sys_process_vm_readv", 0 }, + [377] = { "sys_process_vm_writev", 0 }, + [378] = { "sys_kcmp", 0 }, + [379] = { "sys_finit_module", 0 }, + [380] = { "sys_sched_setattr", 0 }, + [381] = { "sys_sched_getattr", 0 }, + [382] = { "sys_renameat2", 0 }, + [383] = { "sys_seccomp", 0 }, + [384] = { "sys_getrandom", 0 }, + [385] = { "sys_memfd_create", 0 }, + [386] = { "sys_bpf", 0 }, + [387] = { "sys_execveat", 0 }, + [388] = { "sys_userfaultfd", 0 }, + [389] = { "sys_membarrier", 0 }, + [390] = { "sys_mlock2", 0 }, + [391] = { "sys_copy_file_range", 0 }, + [392] = { "sys_preadv2", 0 }, + [393] = { "sys_pwritev2", 0 }, + [394] = { "sys_pkey_mprotect", 0 }, + [395] = { "sys_pkey_alloc", 0 }, + [396] = { "sys_pkey_free", 0 }, + [397] = { "sys_statx", 0 }, + [398] = { "sys_rseq", 0 }, + [399] = { "sys_io_pgetevents", 0 }, + [400] = { "sys_migrate_pages", 0 }, + [401] = { "sys_kexec_file_load", 0 }, + [403] = { "sys_clock_gettime", 0 }, + [404] = { "sys_clock_settime", 0 }, + [405] = { "sys_clock_adjtime", 0 }, + [406] = { "sys_clock_getres", 0 }, + [407] = { "sys_clock_nanosleep", 0 }, + [408] = { "sys_timer_gettime", 0 }, + [409] = { "sys_timer_settime", 0 }, + [410] = { "sys_timerfd_gettime", 0 }, + [411] = { "sys_timerfd_settime", 0 }, + [412] = { "sys_utimensat", 0 }, + [413] = { "sys_pselect6_time64", 0 }, + [414] = { "sys_ppoll_time64", 0 }, + [416] = { "sys_io_pgetevents", 0 }, + [417] = { "sys_recvmmsg_time64", 0 }, + [418] = { "sys_mq_timedsend", 0 }, + [419] = { "sys_mq_timedreceive", 0 }, + [420] = { "sys_semtimedop", 0 }, + [421] = { "sys_rt_sigtimedwait_time64", 0 }, + [422] = { "sys_futex", 0 }, + [423] = { "sys_sched_rr_get_interval", 0 }, + [424] = { "sys_pidfd_send_signal", 0 }, + [425] = { "sys_io_uring_setup", 0 }, + [426] = { "sys_io_uring_enter", 0 }, + [427] = { "sys_io_uring_register", 0 }, + [428] = { "sys_open_tree", 0 }, + [429] = { "sys_move_mount", 0 }, + [430] = { "sys_fsopen", 0 }, + [431] = { "sys_fsconfig", 0 }, + [432] = { "sys_fsmount", 0 }, + [433] = { "sys_fspick", 0 }, + [434] = { "sys_pidfd_open", 0 }, + [435] = { "sys_clone3", 0 }, + [436] = { "sys_close_range", 0 }, + [437] = { "sys_openat2", 0 }, + [438] = { "sys_pidfd_getfd", 0 }, + [439] = { "sys_faccessat2", 0 }, + [440] = { "sys_process_madvise", 0 }, + [441] = { "sys_epoll_pwait2", 0 }, + [442] = { "sys_mount_setattr", 0 }, + [443] = { "sys_quotactl_fd", 0 }, + [444] = { "sys_landlock_create_ruleset", 0 }, + [445] = { "sys_landlock_add_rule", 0 }, + [446] = { "sys_landlock_restrict_self", 0 }, + [448] = { "sys_process_mrelease", 0 }, + [449] = { "sys_futex_waitv", 0 }, + [450] = { "sys_set_mempolicy_home_node", 0 }, + [451] = { "sys_cachestat", 0 }, }; KP_EXPORT_SYMBOL(compat_syscall_name_table); diff --git a/kernel/patch/include/syscall.h b/kernel/patch/include/syscall.h index efa733c3..857474f5 100644 --- a/kernel/patch/include/syscall.h +++ b/kernel/patch/include/syscall.h @@ -15,8 +15,17 @@ extern uintptr_t *sys_call_table; extern uintptr_t *compat_sys_call_table; extern int has_syscall_wrapper; -extern const char *syscall_name_table[460]; -extern const char *compat_syscall_name_table[460]; +extern struct +{ + const char *name; + uintptr_t addr; +} syscall_name_table[460]; + +extern struct +{ + const char *name; + uintptr_t addr; +} compat_syscall_name_table[460]; const char __user *get_user_arg_ptr(void *a0, void *a1, int nr); int set_user_arg_ptr(void *a0, void *a1, int nr, uintptr_t val); diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 34330486..3dc625ae 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -46,6 +46,11 @@ int resolve_pt_regs(); int supercall_install(); int su_compat_init(); +void linux_misc_symbol_init(); +void linux_libs_symbol_init(); +void module_init(); +void syscall_init(); + #ifdef ANDROID int android_user_init(); int android_sepolicy_flags_init(); @@ -56,15 +61,9 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) int rc = 0; log_boot("entering init ...\n"); - if ((rc = bypass_kcfi())) goto out; - log_boot("bypass_kcfi done: %d\n", rc); - if ((rc = resolve_struct())) goto out; log_boot("resolve_struct done: %d\n", rc); - if ((rc = bypass_selinux())) goto out; - log_boot("bypass_selinux done: %d\n", rc); - #ifdef ANDROID rc = android_sepolicy_flags_init(); log_boot("android_sepolicy_flags_init done: %d\n", rc); @@ -73,12 +72,6 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) if ((rc = task_observer())) goto out; log_boot("task_observer done: %d\n", rc); - rc = supercall_install(); - log_boot("supercall_install done: %d\n", rc); - - rc = su_compat_init(); - log_boot("su_compat_init done: %d\n", rc); - rc = resolve_pt_regs(); log_boot("resolve_pt_regs done: %d\n", rc); @@ -113,21 +106,24 @@ static void after_kernel_init(hook_fargs4_t *args, void *udata) log_boot("event: %s\n", EXTRA_EVENT_POST_KERNEL_INIT); } -// internal header -void linux_misc_symbol_init(); -void linux_libs_symbol_init(); -void module_init(); -void syscall_init(); - int patch() { linux_libs_symbol_init(); linux_misc_symbol_init(); + module_init(); + syscall_init(); hook_err_t rc = 0; + if ((rc = bypass_kcfi())) goto out; + log_boot("bypass_kcfi done: %d\n", rc); + + if ((rc = bypass_selinux())) goto out; + log_boot("bypass_selinux done: %d\n", rc); + + // panic unsigned long panic_addr = get_preset_patch_sym()->panic; logkd("panic addr: %llx\n", panic_addr); if (panic_addr) { @@ -145,6 +141,12 @@ int patch() } if (rc) return rc; + rc = supercall_install(); + log_boot("supercall_install done: %d\n", rc); + + rc = su_compat_init(); + log_boot("su_compat_init done: %d\n", rc); + // kernel_init unsigned long kernel_init_addr = get_preset_patch_sym()->kernel_init; if (kernel_init_addr) { @@ -152,5 +154,6 @@ int patch() log_boot("hook kernel_init rc: %d\n", rc); } +out: return rc; } diff --git a/tools/kallsym.c b/tools/kallsym.c index 907414ef..63e076d3 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -622,7 +622,7 @@ static int find_names(kallsym_t *info, char *img, int32_t imglen) return 0; } -int arm64_verify_pid_vnr(kallsym_t *info, char *img, int32_t offset) +static int arm64_verify_pid_vnr(kallsym_t *info, char *img, int32_t offset) { for (int i = 0; i < 6; i++) { int32_t insn_offset = offset + i * 4; @@ -631,12 +631,14 @@ int arm64_verify_pid_vnr(kallsym_t *info, char *img, int32_t offset) if (enc == AARCH64_INSN_CLS_BR_SYS) { if (aarch64_insn_extract_system_reg(insn) == AARCH64_INSN_SPCLREG_SP_EL0) { tools_logi("pid_vnr verfied sp_el0, insn: 0x%x\n", insn); + info->current_type = SP_EL0; return 0; } } else if (enc == AARCH64_INSN_CLS_DP_IMM) { u32 rn = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RN, insn); if (rn == AARCH64_INSN_REG_SP) { tools_logi("pid_vnr verfied sp, insn: 0x%x\n", insn); + info->current_type = SP; return 0; } } @@ -738,8 +740,7 @@ static int correct_addresses_or_offsets_by_banner(kallsym_t *info, char *img, in int32_t pos = info->kallsyms_names_offset; int32_t index = 0; char symbol[KSYM_SYMBOL_LEN] = { '\0' }; - // Pick a symbol (linux_banner) whose offset we know, use its index to fix the - // beginning of the addresses or offsets table + while (pos < info->kallsyms_markers_offset) { memset(symbol, 0, sizeof(symbol)); int32_t ret = decompress_symbol_name(info, img, &pos, NULL, symbol); @@ -749,6 +750,8 @@ static int correct_addresses_or_offsets_by_banner(kallsym_t *info, char *img, in tools_logi("names table linux_banner index: 0x%08x\n", index); break; } + if (!strcmp(symbol, "pid_vnr")) { + } index++; } @@ -793,6 +796,12 @@ static int correct_addresses_or_offsets_by_banner(kallsym_t *info, char *img, in info->kernel_base = uint_unpack(img + info->kallsyms_addresses_offset, elem_size, info->is_be); tools_logi("kernel base address: 0x%llx\n", info->kernel_base); } + + int32_t pid_vnr_offset = get_symbol_offset(info, img, "pid_vnr"); + if (arm64_verify_pid_vnr(info, img, pid_vnr_offset)) { + tools_logw("pid_vnr verification failed\n"); + } + return 0; } @@ -801,8 +810,10 @@ static int correct_addresses_or_offsets(kallsym_t *info, char *img, int32_t imgl int rc = 0; #if 1 rc = correct_addresses_or_offsets_by_banner(info, img, imglen); + info->is_kallsysms_all_yes = 1; #endif if (rc) { + info->is_kallsysms_all_yes = 0; tools_logw("no linux_banner? maybe CONFIG_KALLSYMS_ALL=n?\n"); } if (rc) rc = correct_addresses_or_offsets_by_vectors(info, img, imglen); diff --git a/tools/kallsym.h b/tools/kallsym.h index da9d494a..22d0e05c 100644 --- a/tools/kallsym.h +++ b/tools/kallsym.h @@ -54,6 +54,12 @@ enum arch_type X86 }; +enum current_type +{ + SP_EL0, + SP +}; + #define ELF64_KERNEL_MIN_VA 0xffffff8008080000 #define ELF64_KERNEL_MAX_VA 0xffffffffffffffff @@ -103,6 +109,9 @@ typedef struct int32_t elf64_rela_num; int32_t elf64_rela_offset; + int32_t is_kallsysms_all_yes; + enum current_type current_type; + } kallsym_t; int analyze_kallsym_info(kallsym_t *info, char *img, int32_t imglen, enum arch_type arch, int32_t is_64); From b1e367884d40ae86b8ba357e4e35a4b741213403 Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 21 Aug 2024 22:37:50 +0800 Subject: [PATCH 31/71] fix kallsyms_all=n --- kernel/patch/android/userd.c | 6 +- kernel/patch/common/syscall.c | 103 +++++++++++++++++++++++++++------ kernel/patch/include/syscall.h | 77 ++++++++++++------------ kernel/patch/ksyms/task_cred.c | 16 ++++- kernel/patch/patch.c | 34 +++++------ tools/kallsym.c | 2 +- 6 files changed, 158 insertions(+), 80 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index e03b8586..e120767d 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -359,15 +359,15 @@ int android_user_init() hook_err_t ret = 0; hook_err_t rc = HOOK_NO_ERR; - rc = fp_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)__NR_execve); + rc = hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)__NR_execve); log_boot("hook __NR_execve rc: %d\n", rc); ret |= rc; - rc = fp_hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)__NR_execveat); + rc = hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)__NR_execveat); log_boot("hook __NR_execveat rc: %d\n", rc); ret |= rc; - rc = fp_hook_syscalln(__NR_openat, 4, before_openat, after_openat, 0); + rc = hook_syscalln(__NR_openat, 4, before_openat, after_openat, 0); log_boot("hook __NR_openat rc: %d\n", rc); ret |= rc; diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index a0217baa..07014d51 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -114,10 +114,16 @@ uintptr_t syscalln_name_addr(int nr, int is_compat) } name = compat_syscall_name_table[nr].name; } + if (!name) return 0; - static const char *prefix[2] = { "__arm64_", "" }; - static const char *suffix[3] = { ".cfi_jt", ".cfi", "" }; + const char *prefix[2]; + prefix[0] = "__arm64_"; + prefix[1] = ""; + const char *suffix[3]; + suffix[0] = ".cfi_jt"; + suffix[1] = ".cfi"; + suffix[2] = ""; uintptr_t addr = 0; @@ -128,6 +134,7 @@ uintptr_t syscalln_name_addr(int nr, int is_compat) addr = kallsyms_lookup_name(buffer); if (addr) break; } + if (addr) break; } if (!is_compat) { syscall_name_table[nr].addr = addr; @@ -136,16 +143,19 @@ uintptr_t syscalln_name_addr(int nr, int is_compat) } return addr; } +KP_EXPORT_SYMBOL(syscalln_name_addr); uintptr_t syscalln_addr(int nr, int is_compat) { - if (sys_call_table) return sys_call_table[nr]; - return syscalln_name_addr(nr, ); + if (!is_compat && sys_call_table) return sys_call_table[nr]; + if (is_compat && compat_sys_call_table) return compat_sys_call_table[nr]; + return syscalln_name_addr(nr, is_compat); } +KP_EXPORT_SYMBOL(syscalln_addr); long raw_syscall0(long nr) { - uintptr_t addr = sys_call_table[nr]; + uintptr_t addr = syscalln_addr(nr, 0); if (has_syscall_wrapper) { struct pt_regs regs; regs.syscallno = nr; @@ -153,12 +163,11 @@ long raw_syscall0(long nr) return ((warp_raw_syscall_f)addr)(®s); } return ((raw_syscall0_f)addr)(); - return 0; } long raw_syscall1(long nr, long arg0) { - uintptr_t addr = sys_call_table[nr]; + uintptr_t addr = syscalln_addr(nr, 0); if (has_syscall_wrapper) { struct pt_regs regs; regs.syscallno = nr; @@ -171,7 +180,7 @@ long raw_syscall1(long nr, long arg0) long raw_syscall2(long nr, long arg0, long arg1) { - uintptr_t addr = sys_call_table[nr]; + uintptr_t addr = syscalln_addr(nr, 0); if (has_syscall_wrapper) { struct pt_regs regs; regs.syscallno = nr; @@ -185,7 +194,7 @@ long raw_syscall2(long nr, long arg0, long arg1) long raw_syscall3(long nr, long arg0, long arg1, long arg2) { - uintptr_t addr = sys_call_table[nr]; + uintptr_t addr = syscalln_addr(nr, 0); if (has_syscall_wrapper) { struct pt_regs regs; regs.syscallno = nr; @@ -200,7 +209,7 @@ long raw_syscall3(long nr, long arg0, long arg1, long arg2) long raw_syscall4(long nr, long arg0, long arg1, long arg2, long arg3) { - uintptr_t addr = sys_call_table[nr]; + uintptr_t addr = syscalln_addr(nr, 0); if (has_syscall_wrapper) { struct pt_regs regs; regs.syscallno = nr; @@ -216,7 +225,7 @@ long raw_syscall4(long nr, long arg0, long arg1, long arg2, long arg3) long raw_syscall5(long nr, long arg0, long arg1, long arg2, long arg3, long arg4) { - uintptr_t addr = sys_call_table[nr]; + uintptr_t addr = syscalln_addr(nr, 0); if (has_syscall_wrapper) { struct pt_regs regs; regs.syscallno = nr; @@ -233,7 +242,7 @@ long raw_syscall5(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) { - uintptr_t addr = sys_call_table[nr]; + uintptr_t addr = syscalln_addr(nr, 0); if (has_syscall_wrapper) { struct pt_regs regs; regs.syscallno = nr; @@ -249,6 +258,40 @@ long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 return ((raw_syscall6_f)addr)(arg0, arg1, arg2, arg3, arg4, arg5); } +hook_err_t __fp_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) +{ + if (!is_compat) { + if (!sys_call_table) return HOOK_BAD_ADDRESS; + uintptr_t fp_addr = (uintptr_t)(sys_call_table + nr); + if (has_syscall_wrapper) narg = 1; + return fp_hook_wrap(fp_addr, narg, before, after, udata); + } else { + if (!compat_sys_call_table) return HOOK_BAD_ADDRESS; + uintptr_t fp_addr = (uintptr_t)(compat_sys_call_table + nr); + if (has_syscall_wrapper) narg = 1; + return fp_hook_wrap(fp_addr, narg, before, after, udata); + } +} + +void __fp_unhook_syscalln(int nr, int is_compat, void *before, void *after) +{ + if (!is_compat) { + if (!sys_call_table) return; + uintptr_t fp_addr = (uintptr_t)(sys_call_table + nr); + fp_hook_unwrap(fp_addr, before, after); + } else { + if (!compat_sys_call_table) return; + uintptr_t fp_addr = (uintptr_t)(compat_sys_call_table + nr); + fp_hook_unwrap(fp_addr, before, after); + } +} + +/* +sys_xxx.cfi_jt + +hint #0x22 # bti c +b #0xfffffffffeb452f4 +*/ hook_err_t __inline_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) { uintptr_t addr = syscalln_name_addr(nr, is_compat); @@ -263,23 +306,47 @@ void __inline_unhook_syscalln(int nr, int is_compat, void *before, void *after) hook_unwrap((void *)addr, before, after); } +hook_err_t hook_syscalln(int nr, int narg, void *before, void *after, void *udata) +{ + if (sys_call_table) return __fp_hook_syscalln(nr, narg, 0, before, after, udata); + return __inline_hook_syscalln(nr, narg, 0, before, after, udata); +} + +void unhook_syscalln(int nr, void *before, void *after) +{ + if (sys_call_table) return __fp_unhook_syscalln(nr, 0, before, after); + return __inline_unhook_syscalln(nr, 0, before, after); +} + +hook_err_t hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) +{ + if (compat_sys_call_table) return __fp_hook_syscalln(nr, narg, 1, before, after, udata); + return __inline_hook_syscalln(nr, narg, 1, before, after, udata); +} + +void unhook_compat_syscalln(int nr, void *before, void *after) +{ + if (compat_sys_call_table) return __fp_unhook_syscalln(nr, 1, before, after); + return __inline_unhook_syscalln(nr, 1, before, after); +} + void syscall_init() { for (int i = 0; i < sizeof(syscall_name_table) / sizeof(syscall_name_table[0]); i++) { - uintptr_t *addr = syscall_name_table[i].name; + uintptr_t *addr = (uintptr_t *)&syscall_name_table[i].name; *addr = link2runtime(*addr); } for (int i = 0; i < sizeof(compat_syscall_name_table) / sizeof(compat_syscall_name_table[0]); i++) { - uintptr_t *addr = (uintptr_t *)compat_syscall_name_table + i; + uintptr_t *addr = (uintptr_t *)&compat_syscall_name_table[i].name; *addr = link2runtime(*addr); } - sys_call_table = (typeof(sys_call_table))kallsyms_lookup_name("sys_call_table"); - log_boot("sys_call_table addr: %llx\n", sys_call_table); + // sys_call_table = (typeof(sys_call_table))kallsyms_lookup_name("sys_call_table"); + // log_boot("sys_call_table addr: %llx\n", sys_call_table); - compat_sys_call_table = (typeof(compat_sys_call_table))kallsyms_lookup_name("compat_sys_call_table"); - log_boot("compat_sys_call_table addr: %llx\n", compat_sys_call_table); + // compat_sys_call_table = (typeof(compat_sys_call_table))kallsyms_lookup_name("compat_sys_call_table"); + // log_boot("compat_sys_call_table addr: %llx\n", compat_sys_call_table); has_config_compat = 0; has_syscall_wrapper = 0; diff --git a/kernel/patch/include/syscall.h b/kernel/patch/include/syscall.h index 857474f5..d1d1d02d 100644 --- a/kernel/patch/include/syscall.h +++ b/kernel/patch/include/syscall.h @@ -12,8 +12,6 @@ #include #include -extern uintptr_t *sys_call_table; -extern uintptr_t *compat_sys_call_table; extern int has_syscall_wrapper; extern struct { @@ -28,6 +26,7 @@ extern struct } compat_syscall_name_table[460]; const char __user *get_user_arg_ptr(void *a0, void *a1, int nr); + int set_user_arg_ptr(void *a0, void *a1, int nr, uintptr_t val); long raw_syscall0(long nr); @@ -40,6 +39,10 @@ long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 #define raw_syscall(f) raw_syscall##f +uintptr_t syscalln_name_addr(int nr, int is_compat); + +uintptr_t syscalln_addr(int nr, int is_compat); + static inline uint64_t *syscall_args(void *hook_fargs) { uint64_t *args; @@ -67,43 +70,49 @@ static inline void *syscall_argn_p(void *fdata_args, int n) return syscall_args(fdata_args) + n; } +/** + * @brief + * + * @param nr + * @param narg + * @param is_compat + * @param before + * @param after + * @param udata + * @return hook_err_t + */ +hook_err_t __fp_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata); + +/** + * @brief + * + * @param nr + * @param is_compat + * @param before + * @param after + */ +void __fp_unhook_syscalln(int nr, int is_compat, void *before, void *after); + static inline hook_err_t fp_hook_syscalln(int nr, int narg, void *before, void *after, void *udata) { - if (!sys_call_table) return HOOK_BAD_ADDRESS; - uintptr_t fp_addr = (uintptr_t)(sys_call_table + nr); - if (has_syscall_wrapper) narg = 1; - return fp_hook_wrap(fp_addr, narg, before, after, udata); + return __fp_hook_syscalln(nr, narg, 0, before, after, udata); } static inline void fp_unhook_syscalln(int nr, void *before, void *after) { - if (!sys_call_table) return; - uintptr_t fp_addr = (uintptr_t)(sys_call_table + nr); - fp_hook_unwrap(fp_addr, before, after); + return __fp_unhook_syscalln(nr, 0, before, after); } static inline hook_err_t fp_hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) { - if (!compat_sys_call_table) return HOOK_BAD_ADDRESS; - uintptr_t fp_addr = (uintptr_t)(compat_sys_call_table + nr); - if (has_syscall_wrapper) narg = 1; - return fp_hook_wrap(fp_addr, narg, before, after, udata); + return __fp_hook_syscalln(nr, narg, 1, before, after, udata); } static inline void fp_unhook_compat_syscalln(int nr, void *before, void *after) { - if (!compat_sys_call_table) return; - uintptr_t fp_addr = (uintptr_t)(compat_sys_call_table + nr); - fp_hook_unwrap(fp_addr, before, after); + return __fp_unhook_syscalln(nr, 1, before, after); } -/* -syscall table element: -sys_xxx.cfi_jt -hint #0x22 # bti c -b #0xfffffffffeb452f4 -*/ - /** * @brief * @@ -147,18 +156,14 @@ static inline void inline_unhook_compat_syscalln(int nr, void *before, void *aft __inline_unhook_syscalln(nr, 0, before, after); } -// #define DEFAULT_INLINE_HOOK_SYSCALL - -#ifdef DEFAULT_INLINE_HOOK_SYSCALL -#define hook_syscalln inline_hook_syscalln -#define unhook_syscalln inline_unhook_syscalln -#define hook_compat_syscalln inline_hook_compat_syscalln -#define unhook_compat_syscalln inline_unhook_compat_syscalln -#else -#define hook_syscalln fp_hook_syscalln -#define unhook_syscalln fp_unhook_syscalln -#define hook_compat_syscalln fp_hook_compat_syscalln -#define unhook_compat_syscalln fp_unhook_compat_syscalln -#endif +// + +hook_err_t hook_syscalln(int nr, int narg, void *before, void *after, void *udata); + +void unhook_syscalln(int nr, void *before, void *after); + +hook_err_t hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata); + +void unhook_compat_syscalln(int nr, void *before, void *after); #endif \ No newline at end of file diff --git a/kernel/patch/ksyms/task_cred.c b/kernel/patch/ksyms/task_cred.c index 216ec48c..6d4036b3 100644 --- a/kernel/patch/ksyms/task_cred.c +++ b/kernel/patch/ksyms/task_cred.c @@ -476,13 +476,14 @@ int resolve_current() init_task = (struct task_struct *)kallsyms_lookup_name("init_task"); uint64_t init_thread_union_addr = kallsyms_lookup_name("init_thread_union"); + #if 0 init_task = 0; init_thread_union_addr = 0; #endif - log_boot(" init_task lookup: %llx\n", init_task); - log_boot(" init_thread_union lookup: %llx\n", init_thread_union_addr); + log_boot(" init_task addr lookup: %llx\n", init_task); + log_boot(" init_thread_union addr lookup: %llx\n", init_thread_union_addr); if (is_kimg_range(sp_el0)) { if (sp_el0 == init_thread_union_addr) { @@ -585,11 +586,19 @@ int resolve_current() return 0; } +// todo int resolve_mm_struct_offset() { + if (!init_mm) return 0; + log_boot("struct mm_struct: \n"); + // struct mm_struct *mm = get_task_mm(init_task); + // uintptr_t init_mm_addr = (uintptr_t)mm; + uintptr_t init_mm_addr = (uintptr_t)init_mm; + if (!init_mm_addr) return 0; + for (uintptr_t i = init_mm_addr; i < init_mm_addr + MM_STRUCT_MAX_SIZE; i += sizeof(uintptr_t)) { uint64_t pgd = *(uintptr_t *)i; if (pgd == phys_to_kimg(pgd_pa)) { @@ -605,8 +614,11 @@ int resolve_struct() full_cap = CAP_FULL_SET; int err = 0; + if ((err = resolve_current())) goto out; + if ((err = resolve_task_offset())) goto out; + if ((err = resolve_cred_offset())) goto out; resolve_mm_struct_offset(); diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 3dc625ae..50f259fb 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -61,21 +61,31 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) int rc = 0; log_boot("entering init ...\n"); + if ((rc = bypass_kcfi())) goto out; + log_boot("bypass_kcfi done: %d\n", rc); + if ((rc = resolve_struct())) goto out; log_boot("resolve_struct done: %d\n", rc); -#ifdef ANDROID - rc = android_sepolicy_flags_init(); - log_boot("android_sepolicy_flags_init done: %d\n", rc); -#endif + if ((rc = bypass_selinux())) goto out; + log_boot("bypass_selinux done: %d\n", rc); if ((rc = task_observer())) goto out; log_boot("task_observer done: %d\n", rc); + rc = supercall_install(); + log_boot("supercall_install done: %d\n", rc); + + rc = su_compat_init(); + log_boot("su_compat_init done: %d\n", rc); + rc = resolve_pt_regs(); log_boot("resolve_pt_regs done: %d\n", rc); #ifdef ANDROID + rc = android_sepolicy_flags_init(); + log_boot("android_sepolicy_flags_init done: %d\n", rc); + rc = android_user_init(); log_boot("android_user_init done: %d\n", rc); #endif @@ -110,20 +120,11 @@ int patch() { linux_libs_symbol_init(); linux_misc_symbol_init(); - module_init(); - syscall_init(); hook_err_t rc = 0; - if ((rc = bypass_kcfi())) goto out; - log_boot("bypass_kcfi done: %d\n", rc); - - if ((rc = bypass_selinux())) goto out; - log_boot("bypass_selinux done: %d\n", rc); - - // panic unsigned long panic_addr = get_preset_patch_sym()->panic; logkd("panic addr: %llx\n", panic_addr); if (panic_addr) { @@ -141,12 +142,6 @@ int patch() } if (rc) return rc; - rc = supercall_install(); - log_boot("supercall_install done: %d\n", rc); - - rc = su_compat_init(); - log_boot("su_compat_init done: %d\n", rc); - // kernel_init unsigned long kernel_init_addr = get_preset_patch_sym()->kernel_init; if (kernel_init_addr) { @@ -154,6 +149,5 @@ int patch() log_boot("hook kernel_init rc: %d\n", rc); } -out: return rc; } diff --git a/tools/kallsym.c b/tools/kallsym.c index 63e076d3..099827b5 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -814,7 +814,7 @@ static int correct_addresses_or_offsets(kallsym_t *info, char *img, int32_t imgl #endif if (rc) { info->is_kallsysms_all_yes = 0; - tools_logw("no linux_banner? maybe CONFIG_KALLSYMS_ALL=n?\n"); + tools_logw("no linux_banner, CONFIG_KALLSYMS_ALL=n\n"); } if (rc) rc = correct_addresses_or_offsets_by_vectors(info, img, imglen); return rc; From 27ce684fa78386c342576b71cd4bb50cbffc9e7f Mon Sep 17 00:00:00 2001 From: XIN <61306840+NepXIN@users.noreply.github.com> Date: Mon, 26 Aug 2024 09:45:17 +0800 Subject: [PATCH 32/71] kpm: Fix alignment issue in `module` (#118) --- kernel/patch/module/module.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/kernel/patch/module/module.c b/kernel/patch/module/module.c index 2c09fd2a..087cd4bf 100644 --- a/kernel/patch/module/module.c +++ b/kernel/patch/module/module.c @@ -58,12 +58,7 @@ static char *next_string(char *string, unsigned long *secsize) /* Update size with this section: return offset. */ static long get_offset(struct module *mod, unsigned int *size, Elf_Shdr *sechdr, unsigned int section) { - long ret; - /* Additional bytes needed by arch in front of individual sections */ - int arm64_mod_section_prepend = 0; - *size += arm64_mod_section_prepend; - ret = ALIGN(*size, sechdr->sh_addralign ?: 1); - ret = *size; + long ret = ALIGN(*size, sechdr->sh_addralign ?: 1); *size = ret + sechdr->sh_size; return ret; } From 9841e4655ccd8576fb9f9463465d7bf4ec60ecdf Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 1 Sep 2024 21:48:13 +0800 Subject: [PATCH 33/71] a --- kernel/include/preset.h | 1 - kernel/patch/android/sepolicy_flags.c | 22 +-- kernel/patch/common/pmem.c | 174 +++++++++---------- kernel/patch/common/supercall.c | 6 - kernel/patch/common/supercmd.c | 233 ++++++++++++++------------ kernel/patch/include/pidmem.h | 2 +- kernel/patch/patch.c | 4 +- user/supercall.h | 7 - user_deprecated/kpatch.c | 2 +- user_deprecated/supercall.h | 8 - user_deprecated/supercall_ge0a04.h | 7 - 11 files changed, 227 insertions(+), 239 deletions(-) diff --git a/kernel/include/preset.h b/kernel/include/preset.h index be6232f8..b63772de 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -118,7 +118,6 @@ struct patch_symbol uint64_t cgroup_post_fork; uint64_t avc_denied; uint64_t slow_avc_audit; - uint64_t policydb_write; uint64_t input_handle_event; }; char _cap[PATCH_SYMBOL_LEN]; diff --git a/kernel/patch/android/sepolicy_flags.c b/kernel/patch/android/sepolicy_flags.c index 5548c730..2875c89e 100644 --- a/kernel/patch/android/sepolicy_flags.c +++ b/kernel/patch/android/sepolicy_flags.c @@ -19,16 +19,15 @@ #include /* - * see: https://android-review.googlesource.com/c/kernel/common/+/3009995 - * + * @see: https://android-review.googlesource.com/c/kernel/common/+/3009995 */ - -static int (*policydb_write_backup)(struct _policydb *p, struct _policy_file *fp) = 0; -static int policydb_write_replace(struct _policydb *p, struct _policy_file *fp) +static void after_policydb_write(hook_fargs2_t *args, void *udata) { + struct _policydb *p = (struct _policydb *)args->arg0; + struct _policy_file *fp = (struct _policy_file *)args->arg1; char *data = fp->data; - int ret = policydb_write_backup(p, fp); - if (!ret) { + + if (!args->ret) { __le32 *config = (__le32 *)(data + POLICYDB_CONFIG_OFFSET); __le32 before_config = *config; bool android_netlink_route_exists = before_config & POLICYDB_CONFIG_ANDROID_NETLINK_ROUTE; @@ -40,14 +39,15 @@ static int policydb_write_replace(struct _policydb *p, struct _policy_file *fp) *config |= POLICYDB_CONFIG_ANDROID_NETLINK_GETNEIGH; } } - return ret; } -int android_sepolicy_flags_init() +int android_sepolicy_flags_fix() { - unsigned long policydb_write_addr = get_preset_patch_sym()->policydb_write; + unsigned long policydb_write_addr = kallsyms_lookup_name("policydb_write"); + if (likely(policydb_write_addr)) { - hook_err_t err = hook((void *)policydb_write_addr, (void *)policydb_write_replace, (void **)&policydb_write_backup); + hook_err_t err = hook_wrap2((void *)policydb_write_addr, 0, after_policydb_write, 0); + if (unlikely(err != HOOK_NO_ERR)) { log_boot("hook policydb_write_addr: %llx, error: %d\n", policydb_write_addr, err); return -1; diff --git a/kernel/patch/common/pmem.c b/kernel/patch/common/pmem.c index 6b0fe703..7db89512 100644 --- a/kernel/patch/common/pmem.c +++ b/kernel/patch/common/pmem.c @@ -13,90 +13,90 @@ // void __put_task_struct(struct task_struct *tsk) //EXPORT_SYMBOL_GPL(__put_task_struct); -uint64_t *local_pgtable_entry(uint64_t pgd, uint64_t va) -{ - uint64_t pxd_bits = page_shift - 3; - uint64_t pxd_ptrs = 1u << pxd_bits; - uint64_t pxd_va = pgd; - uint64_t pxd_pa = virt_to_phys(pxd_va); - uint64_t pxd_entry_va = 0; - uint64_t block_lv = 0; - - for (int64_t lv = 4 - page_level; lv < 4; lv++) { - uint64_t pxd_shift = (page_shift - 3) * (4 - lv) + 3; - uint64_t pxd_index = (va >> pxd_shift) & (pxd_ptrs - 1); - pxd_entry_va = pxd_va + pxd_index * 8; - if (!pxd_entry_va) return 0; - uint64_t pxd_desc = *((uint64_t *)pxd_entry_va); - if ((pxd_desc & 0b11) == 0b11) { // table - pxd_pa = pxd_desc & (((1ul << (48 - page_shift)) - 1) << page_shift); - } else if ((pxd_desc & 0b11) == 0b01) { // block - // 4k page: lv1, lv2. 16k and 64k page: only lv2. - uint64_t block_bits = (3 - lv) * pxd_bits + page_shift; - pxd_pa = pxd_desc & (((1ul << (48 - block_bits)) - 1) << block_bits); - block_lv = lv; - } else { // invalid - return 0; - } - // - pxd_va = phys_to_virt(pxd_pa); - if (block_lv) { - break; - } - } -#if 1 - uint64_t left_bit = page_shift + (block_lv ? (3 - block_lv) * pxd_bits : 0); - uint64_t tpa = pxd_pa + (va & ((1u << left_bit) - 1)); - uint64_t tlva = phys_to_virt(tpa); - uint64_t tkimg = phys_to_kimg(tpa); - // if (tlva != va && tkimg != va) { - // return 0; - // } - logkd("tpa: %llx, tlva: %llx, tkimg: %llx\n", tpa, tlva, tkimg); -#endif - return (uint64_t *)pxd_entry_va; -} - -phys_addr_t pid_virt_to_phys(pid_t pid, uintptr_t vaddr) -{ - if (mm_struct_offset.pgd_offset < 0) { - return -EFAULT; - } - - int rc = 0; - - logkd("pid: %llx, vaddr: %llx\n", pid, vaddr); - logkd("aaaa %llx\n", kfunc(find_get_task_by_vpid)); - - // struct task_struct *task = find_get_task_by_vpid(pid); - struct task_struct *task = find_task_by_vpid(pid); - if (!task) { - logkfe("no such pid: %d\n", pid); - return -ESRCH; - } - - logkd("task: %llx\n", task); - - struct mm_struct *mm = get_task_mm(task); - if (!mm || IS_ERR(mm)) { - // todo - } - - logkd("mm: %llx\n", mm); - - uintptr_t pgd = *(uintptr_t *)((uintptr_t)mm + mm_struct_offset.pgd_offset); - logkd("pgd: %llx\n", pgd); - - for (uintptr_t i = pgd; i < pgd + 512 * 8; i += 8) { - logkd("pgd i: %llx, val: %llx\n", i, *(uintptr_t *)i); - } - - uintptr_t *entry = local_pgtable_entry(pgd, vaddr); - logkd("entry: %llx\n", entry); - logkd("entry value: %llx\n", *(uintptr_t *)entry); - - // remap_pfn_range or direct modify pgtable - - mmput(mm); - return rc; -} \ No newline at end of file +// uint64_t *local_pgtable_entry(uint64_t pgd, uint64_t va) +// { +// uint64_t pxd_bits = page_shift - 3; +// uint64_t pxd_ptrs = 1u << pxd_bits; +// uint64_t pxd_va = pgd; +// uint64_t pxd_pa = virt_to_phys(pxd_va); +// uint64_t pxd_entry_va = 0; +// uint64_t block_lv = 0; + +// for (int64_t lv = 4 - page_level; lv < 4; lv++) { +// uint64_t pxd_shift = (page_shift - 3) * (4 - lv) + 3; +// uint64_t pxd_index = (va >> pxd_shift) & (pxd_ptrs - 1); +// pxd_entry_va = pxd_va + pxd_index * 8; +// if (!pxd_entry_va) return 0; +// uint64_t pxd_desc = *((uint64_t *)pxd_entry_va); +// if ((pxd_desc & 0b11) == 0b11) { // table +// pxd_pa = pxd_desc & (((1ul << (48 - page_shift)) - 1) << page_shift); +// } else if ((pxd_desc & 0b11) == 0b01) { // block +// // 4k page: lv1, lv2. 16k and 64k page: only lv2. +// uint64_t block_bits = (3 - lv) * pxd_bits + page_shift; +// pxd_pa = pxd_desc & (((1ul << (48 - block_bits)) - 1) << block_bits); +// block_lv = lv; +// } else { // invalid +// return 0; +// } +// // +// pxd_va = phys_to_virt(pxd_pa); +// if (block_lv) { +// break; +// } +// } +// #if 1 +// uint64_t left_bit = page_shift + (block_lv ? (3 - block_lv) * pxd_bits : 0); +// uint64_t tpa = pxd_pa + (va & ((1u << left_bit) - 1)); +// uint64_t tlva = phys_to_virt(tpa); +// uint64_t tkimg = phys_to_kimg(tpa); +// // if (tlva != va && tkimg != va) { +// // return 0; +// // } +// logkd("tpa: %llx, tlva: %llx, tkimg: %llx\n", tpa, tlva, tkimg); +// #endif +// return (uint64_t *)pxd_entry_va; +// } + +// phys_addr_t pid_virt_to_phys(pid_t pid, uintptr_t vaddr) +// { +// if (mm_struct_offset.pgd_offset < 0) { +// return -EFAULT; +// } + +// int rc = 0; + +// logkd("pid: %llx, vaddr: %llx\n", pid, vaddr); +// logkd("aaaa %llx\n", kfunc(find_get_task_by_vpid)); + +// // struct task_struct *task = find_get_task_by_vpid(pid); +// struct task_struct *task = find_task_by_vpid(pid); +// if (!task) { +// logkfe("no such pid: %d\n", pid); +// return -ESRCH; +// } + +// logkd("task: %llx\n", task); + +// struct mm_struct *mm = get_task_mm(task); +// if (!mm || IS_ERR(mm)) { +// // todo +// } + +// logkd("mm: %llx\n", mm); + +// uintptr_t pgd = *(uintptr_t *)((uintptr_t)mm + mm_struct_offset.pgd_offset); +// logkd("pgd: %llx\n", pgd); + +// for (uintptr_t i = pgd; i < pgd + 512 * 8; i += 8) { +// logkd("pgd i: %llx, val: %llx\n", i, *(uintptr_t *)i); +// } + +// uintptr_t *entry = local_pgtable_entry(pgd, vaddr); +// logkd("entry: %llx\n", entry); +// logkd("entry value: %llx\n", *(uintptr_t *)entry); + +// // remap_pfn_range or direct modify pgtable + +// mmput(mm); +// return rc; +// } \ No newline at end of file diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 53a64a7e..72c1516d 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -175,11 +175,6 @@ static long call_skey_root_enable(int enable) return 0; } -static unsigned long call_pid_virt_to_phys(pid_t pid, uintptr_t vaddr) -{ - return pid_virt_to_phys(pid, vaddr); -} - static long call_grant_uid(struct su_profile *__user uprofile) { struct su_profile *profile = memdup_user(uprofile, sizeof(struct su_profile)); @@ -334,7 +329,6 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3 switch (cmd) { case SUPERCALL_MEM_PHYS: - return call_pid_virt_to_phys((pid_t)arg1, (uintptr_t)arg2); default: break; } diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 6254cf6d..34cd592f 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -99,6 +99,91 @@ static const char supercmd_help[] = " hash : Whether to use hash to verify the root superkey.\n" ""; +struct cmd_res +{ + const char *msg; + const char *err_msg; + int rc; +}; + +static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char *buffer, struct cmd_res *cmd_res) +{ + const char *sub_cmd = carr[1]; + if (!sub_cmd) sub_cmd = ""; + + if (!strcmp(sub_cmd, "grant")) { + unsigned long long uid = 0, to_uid = 0; + const char *scontext = ""; + if (!carr[2] || kstrtoull(carr[2], 10, &uid)) { + sprintf(buffer, "illegal uid: %s", carr[2]); + cmd_res->err_msg = buffer; + return; + } + if (carr[3]) kstrtoull(carr[3], 10, &to_uid); + if (carr[4]) scontext = carr[4]; + su_add_allow_uid(uid, to_uid, scontext, 1); + sprintf(buffer, "grant %d, %d, %s", uid, to_uid, scontext); + cmd_res->msg = buffer; + } else if (!strcmp(sub_cmd, "revoke")) { + const char *suid = carr[2]; + unsigned long long uid; + if (!suid || kstrtoull(suid, 10, &uid)) { + sprintf(buffer, "illegal uid: %s\n", suid); + cmd_res->err_msg = buffer; + return; + } + su_remove_allow_uid(uid, 1); + cmd_res->msg = suid; + } else if (!strcmp(sub_cmd, "num")) { + int num = su_allow_uid_nums(); + sprintf(buffer, "%d", num); + cmd_res->msg = buffer; + } else if (!strcmp(sub_cmd, "list")) { + int num = su_allow_uid_nums(); + uid_t uids[num]; // stack overflow + int offset = 0; + su_allow_uids(0, uids, num); + + for (int i = 0; i < num; i++) { + offset += sprintf(buffer + offset, "%d\n", uids[i]); + }; + if (offset > 0) buffer[offset - 1] = '\0'; + cmd_res->msg = buffer; + + } else if (!strcmp(sub_cmd, "profile")) { + unsigned long long uid; + if (!carr[2] || kstrtoull(carr[2], 10, &uid)) { + cmd_res->err_msg = "invalid uid"; + return; + } + struct su_profile profile; + cmd_res->rc = su_allow_uid_profile(0, uid, &profile); + if (cmd_res->rc) return; + + sprintf(buffer, "uid: %d, to_uid: %d, scontext: %s", profile.uid, profile.to_uid, profile.scontext); + cmd_res->msg = buffer; + + } else if (!strcmp(sub_cmd, "path")) { + if (carr[2]) { + cmd_res->rc = su_reset_path(carr[2]); + if (cmd_res->rc) return; + cmd_res->msg = carr[2]; + carr[2] = 0; // no free + } else { + cmd_res->msg = su_get_path(); + } + } else if (!strcmp(sub_cmd, "sctx")) { + if (carr[2]) { + cmd_res->rc = set_all_allow_sctx(carr[2]); + if (!cmd_res->rc) cmd_res->msg = carr[2]; + } else { + cmd_res->msg = all_allow_sctx; + } + } else { + cmd_res->err_msg = "invalid subcommand"; + } +} + void handle_supercmd(char **__user u_filename_p, char **__user uargv) { int is_key_auth = 0; @@ -187,10 +272,10 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) commit_su(profile.to_uid, profile.scontext); - int rc = 0; - const char *msg = 0; - const char *err_msg = 0; + struct cmd_res cmd_res = { 0 }; + char buffer[4096]; + buffer[0] = '\0'; // command const char **carr = parr + pi; @@ -199,7 +284,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) if (pi < SUPERCMD_ARGS_NO - 1) { cmd = carr[0]; } else { - err_msg = "too many args\n"; + cmd_res.err_msg = "too many args\n"; goto echo; } @@ -210,14 +295,14 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } if (!strcmp("help", cmd)) { - msg = supercmd_help; + cmd_res.msg = supercmd_help; } else if (!strcmp("-c", cmd)) { supercmd_exec(u_filename_p, sh_path, &sp); *uargv += (carr - parr - 1) * 8; goto free; } else if (!strcmp("exec", cmd)) { if (!carr[1]) { - err_msg = "invalid commmand path"; + cmd_res.err_msg = "invalid commmand path"; goto echo; } supercmd_exec(u_filename_p, carr[1], &sp); @@ -227,126 +312,58 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) supercmd_echo(u_filename_p, uargv, &sp, "%x,%x", kver, kpver); goto free; } else if (!strcmp("sumgr", cmd)) { - const char *sub_cmd = carr[1]; - if (!sub_cmd) sub_cmd = ""; - if (!strcmp(sub_cmd, "grant")) { - unsigned long long uid = 0, to_uid = 0; - const char *scontext = ""; - if (!carr[2] || kstrtoull(carr[2], 10, &uid)) { - supercmd_echo(u_filename_p, uargv, &sp, "supercmd error: illegal uid"); - goto free; - } - if (carr[3]) kstrtoull(carr[3], 10, &to_uid); - if (carr[4]) scontext = carr[4]; - su_add_allow_uid(uid, to_uid, scontext, 1); - supercmd_echo(u_filename_p, uargv, &sp, "supercmd: grant %d, %d, %s", uid, to_uid, scontext); - goto free; - } else if (!strcmp(sub_cmd, "revoke")) { - const char *suid = carr[2]; - unsigned long long uid; - if (!suid || kstrtoull(suid, 10, &uid)) { - supercmd_echo(u_filename_p, uargv, &sp, "supercmd error: illegal uid"); - goto free; - } - su_remove_allow_uid(uid, 1); - msg = suid; - } else if (!strcmp(sub_cmd, "num")) { - int num = su_allow_uid_nums(); - supercmd_echo(u_filename_p, uargv, &sp, "%d", num); - } else if (!strcmp(sub_cmd, "list")) { - int num = su_allow_uid_nums(); - uid_t *uids = (uid_t *)buffer; - int offset = 0; - su_allow_uids(0, uids, num); - - char *msg_buf = buffer + num * sizeof(uid_t); - msg_buf[0] = '\0'; - for (int i = 0; i < num; i++) { - offset += sprintf(msg_buf + offset, "%d\n", uids[i]); - }; - if (offset > 0) msg_buf[offset - 1] = '\0'; - msg = msg_buf; - } else if (!strcmp(sub_cmd, "profile")) { - unsigned long long uid; - if (!carr[2] || kstrtoull(carr[2], 10, &uid)) { - err_msg = "invalid uid"; - goto echo; - } - struct su_profile *profile = (struct su_profile *)buffer; - rc = su_allow_uid_profile(0, uid, profile); - char *msg = buffer + sizeof(struct su_profile); - msg[0] = '\0'; - if (!rc) - sprintf(msg, "uid: %d, to_uid: %d, scontext: %s", profile->uid, profile->to_uid, profile->scontext); - } else if (!strcmp(sub_cmd, "path")) { - if (carr[2]) { - rc = su_reset_path(carr[2]); - msg = carr[2]; - carr[2] = 0; // no free - } else { - msg = su_get_path(); - } - } else if (!strcmp(sub_cmd, "sctx")) { - if (carr[2]) { - rc = set_all_allow_sctx(carr[2]); - if (!rc) msg = carr[2]; - } else { - msg = all_allow_sctx; - } - } else { - err_msg = "invalid subcommand"; - } + handle_cmd_sumgr(u_filename_p, carr, buffer, &cmd_res); } else if (!strcmp("event", cmd)) { if (carr[1]) { - rc = report_user_event(carr[1], carr[2]); + cmd_res.rc = report_user_event(carr[1], carr[2]); } else { - err_msg = "empty event"; + cmd_res.err_msg = "empty event"; } } else if (!strcmp("bootlog", cmd)) { - msg = get_boot_log(); + cmd_res.msg = get_boot_log(); } else if (!strcmp("test", cmd)) { void test(); test(); - msg = "test done..."; + cmd_res.msg = "test done..."; } else { // superkey authrication command const char *not_key_auth_err_msg = "superkey(not su) is required"; if (!strcmp("key", cmd)) { if (!is_key_auth) { - err_msg = not_key_auth_err_msg; + cmd_res.err_msg = not_key_auth_err_msg; goto echo; } const char *sub_cmd = carr[1]; if (!sub_cmd) sub_cmd = ""; if (!strcmp("get", sub_cmd)) { - msg = get_superkey(); + cmd_res.msg = get_superkey(); } else if (!strcmp("set", sub_cmd)) { const char *key = carr[2]; if (!key) { - err_msg = "invalid new key"; + cmd_res.err_msg = "invalid new key"; goto echo; } - msg = key; + cmd_res.msg = key; reset_superkey(key); } else if (!strcmp("hash", sub_cmd)) { const char *able = carr[2]; if (able && !strcmp("enable", able)) { - msg = able; + cmd_res.msg = able; enable_auth_root_key(true); } else if (able && !strcmp("disable", able)) { - msg = able; + cmd_res.msg = able; enable_auth_root_key(false); } else { - err_msg = "invalid enable or disable"; + cmd_res.err_msg = "invalid enable or disable"; goto echo; } } else { - err_msg = "invalid subcommand"; + cmd_res.err_msg = "invalid subcommand"; goto echo; } } else if (!strcmp("module", cmd)) { if (!is_key_auth) { - err_msg = not_key_auth_err_msg; + cmd_res.err_msg = not_key_auth_err_msg; goto echo; } const char *sub_cmd = carr[1]; @@ -357,63 +374,63 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } else if (!strcmp("list", sub_cmd)) { buffer[0] = '\0'; list_modules(buffer, sizeof(buffer)); - msg = buffer; + cmd_res.msg = buffer; } else if (!strcmp("load", sub_cmd)) { const char *path = carr[2]; if (!path) { - err_msg = "invalid module path"; + cmd_res.err_msg = "invalid module path"; goto echo; } - rc = load_module_path(path, carr[3], 0); - if (!rc) msg = path; + cmd_res.rc = load_module_path(path, carr[3], 0); + if (!cmd_res.rc) cmd_res.msg = path; } else if (!strcmp("ctl0", sub_cmd)) { const char *name = carr[2]; if (!name) { - err_msg = "invalid module name"; + cmd_res.err_msg = "invalid module name"; goto echo; } const char *mod_args = carr[3]; if (!mod_args) { - err_msg = "invalid control arguments"; + cmd_res.err_msg = "invalid control arguments"; goto echo; } buffer[0] = '\0'; - rc = module_control0(name, mod_args, buffer, sizeof(buffer)); - msg = buffer; + cmd_res.rc = module_control0(name, mod_args, buffer, sizeof(buffer)); + cmd_res.msg = buffer; } else if (!strcmp("ctl1", sub_cmd)) { - err_msg = "not implement"; + cmd_res.err_msg = "not implement"; } else if (!strcmp("unload", sub_cmd)) { const char *name = carr[2]; if (!name) { - err_msg = "invalid module name"; + cmd_res.err_msg = "invalid module name"; goto echo; } - rc = unload_module(name, 0); - if (!rc) msg = name; + cmd_res.rc = unload_module(name, 0); + if (!cmd_res.rc) cmd_res.msg = name; } else if (!strcmp("info", sub_cmd)) { const char *name = carr[2]; if (!name) { - err_msg = "invalid module name"; + cmd_res.err_msg = "invalid module name"; goto echo; } buffer[0] = '\0'; int sz = get_module_info(name, buffer, sizeof(buffer)); - if (sz <= 0) rc = sz; - msg = buffer; + if (sz <= 0) cmd_res.rc = sz; + cmd_res.msg = buffer; } else { - err_msg = "invalid subcommand"; + cmd_res.err_msg = "invalid subcommand"; goto echo; } } else { - err_msg = "invalid command"; + cmd_res.err_msg = "invalid command"; goto echo; } } echo: - if (msg) supercmd_echo(u_filename_p, uargv, &sp, msg); - if (rc) supercmd_echo(u_filename_p, uargv, &sp, "supercmd error code: %d", rc); - if (err_msg) supercmd_echo(u_filename_p, uargv, &sp, "supercmd error message: %s", err_msg); + if (cmd_res.msg) supercmd_echo(u_filename_p, uargv, &sp, cmd_res.msg); + if (cmd_res.rc) supercmd_echo(u_filename_p, uargv, &sp, "supercmd error code: %d", cmd_res.rc); + if (cmd_res.err_msg) supercmd_echo(u_filename_p, uargv, &sp, "supercmd error message: %s", cmd_res.err_msg); free: // free args diff --git a/kernel/patch/include/pidmem.h b/kernel/patch/include/pidmem.h index 5cb10c2e..e9761f16 100644 --- a/kernel/patch/include/pidmem.h +++ b/kernel/patch/include/pidmem.h @@ -8,7 +8,7 @@ #include -phys_addr_t pid_virt_to_phys(pid_t pid, uintptr_t vaddr); +// phys_addr_t pid_virt_to_phys(pid_t pid, uintptr_t vaddr); // void *pid_map_mem(pid_t pid, void *mem, size_t size, ) diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 50f259fb..4fd0eafa 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -83,8 +83,8 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) log_boot("resolve_pt_regs done: %d\n", rc); #ifdef ANDROID - rc = android_sepolicy_flags_init(); - log_boot("android_sepolicy_flags_init done: %d\n", rc); + // rc = android_sepolicy_flags_init(); + // log_boot("android_sepolicy_flags_init done: %d\n", rc); rc = android_user_init(); log_boot("android_user_init done: %d\n", rc); diff --git a/user/supercall.h b/user/supercall.h index 769d3a1d..1e0ab50d 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -428,13 +428,6 @@ static inline long sc_su_get_safemode(const char *key) return syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_SAFEMODE)); } -// todo -static inline long sc_pid_virt_to_phys(const char *key, pid_t pid, unsigned long vaddr) -{ - if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_MEM_PHYS), pid, vaddr); - return ret; -} static inline long sc_bootlog(const char *key) { diff --git a/user_deprecated/kpatch.c b/user_deprecated/kpatch.c index 63cec4c0..93090c70 100644 --- a/user_deprecated/kpatch.c +++ b/user_deprecated/kpatch.c @@ -58,7 +58,7 @@ void panic(const char *key) int __test(const char *key) { // return __sc_test(key, 0, 0, 0); - return sc_pid_virt_to_phys(key, getpid(), (unsigned long)__test); + return 0; } extern const char program_name[]; diff --git a/user_deprecated/supercall.h b/user_deprecated/supercall.h index 4f594900..f921de3a 100644 --- a/user_deprecated/supercall.h +++ b/user_deprecated/supercall.h @@ -382,14 +382,6 @@ static inline long sc_skey_root_enable(const char *key, bool enable) return ret; } -// todo -static inline long sc_pid_virt_to_phys(const char *key, pid_t pid, unsigned long vaddr) -{ - if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_MEM_PHYS), pid, vaddr); - return ret; -} - static inline long sc_bootlog(const char *key) { long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_BOOTLOG)); diff --git a/user_deprecated/supercall_ge0a04.h b/user_deprecated/supercall_ge0a04.h index bf272394..beecbf03 100644 --- a/user_deprecated/supercall_ge0a04.h +++ b/user_deprecated/supercall_ge0a04.h @@ -142,13 +142,6 @@ static inline long sc_kpm_info(const char *key, const char *name, char *buf, int return ret; } -static inline long sc_pid_virt_to_phys(const char *key, pid_t pid, unsigned long vaddr) -{ - if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_MEM_PHYS), pid, vaddr); - return ret; -} - static inline long sc_bootlog(const char *key) { long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_BOOTLOG)); From b237b6d10820bb247a9eddd4aaac8afd4368dd80 Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 1 Sep 2024 22:13:42 +0800 Subject: [PATCH 34/71] a --- kernel/patch/common/supercmd.c | 194 ++++++++++++++++----------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 34cd592f..7f259233 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -184,6 +184,100 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } } +// superkey commands +static void handle_cmd_key_auth(char **__user u_filename_p, const char *cmd, const char **carr, char *buffer, + struct cmd_res *cmd_res) +{ + if (!strcmp("key", cmd)) { + const char *sub_cmd = carr[1]; + if (!sub_cmd) sub_cmd = ""; + if (!strcmp("get", sub_cmd)) { + cmd_res->msg = get_superkey(); + } else if (!strcmp("set", sub_cmd)) { + const char *key = carr[2]; + if (!key) { + cmd_res->err_msg = "invalid new key"; + return; + } + cmd_res->msg = key; + reset_superkey(key); + } else if (!strcmp("hash", sub_cmd)) { + const char *able = carr[2]; + if (able && !strcmp("enable", able)) { + cmd_res->msg = able; + enable_auth_root_key(true); + } else if (able && !strcmp("disable", able)) { + cmd_res->msg = able; + enable_auth_root_key(false); + } else { + cmd_res->err_msg = "invalid enable or disable"; + return; + } + } else { + cmd_res->err_msg = "invalid subcommand"; + return; + } + } else if (!strcmp("module", cmd)) { + const char *sub_cmd = carr[1]; + if (!sub_cmd) sub_cmd = ""; + if (!strcmp("num", sub_cmd)) { + int num = get_module_nums(); + sprintf(buffer, "%d\n", num); + cmd_res->msg = buffer; + } else if (!strcmp("list", sub_cmd)) { + list_modules(buffer, sizeof(buffer)); + cmd_res->msg = buffer; + } else if (!strcmp("load", sub_cmd)) { + const char *path = carr[2]; + if (!path) { + cmd_res->err_msg = "invalid module path"; + return; + } + cmd_res->rc = load_module_path(path, carr[3], 0); + if (!cmd_res->rc) cmd_res->msg = path; + } else if (!strcmp("ctl0", sub_cmd)) { + const char *name = carr[2]; + if (!name) { + cmd_res->err_msg = "invalid module name"; + return; + } + const char *mod_args = carr[3]; + if (!mod_args) { + cmd_res->err_msg = "invalid control arguments"; + return; + } + buffer[0] = '\0'; + cmd_res->rc = module_control0(name, mod_args, buffer, sizeof(buffer)); + cmd_res->msg = buffer; + } else if (!strcmp("ctl1", sub_cmd)) { + cmd_res->err_msg = "not implement"; + } else if (!strcmp("unload", sub_cmd)) { + const char *name = carr[2]; + if (!name) { + cmd_res->err_msg = "invalid module name"; + return; + } + cmd_res->rc = unload_module(name, 0); + if (!cmd_res->rc) cmd_res->msg = name; + } else if (!strcmp("info", sub_cmd)) { + const char *name = carr[2]; + if (!name) { + cmd_res->err_msg = "invalid module name"; + return; + } + int sz = get_module_info(name, buffer, sizeof(buffer)); + if (sz <= 0) cmd_res->rc = sz; + cmd_res->msg = buffer; + } else { + cmd_res->err_msg = "invalid subcommand"; + return; + } + } else { + cmd_res->err_msg = "invalid command"; + return; + } +} + void handle_supercmd(char **__user u_filename_p, char **__user uargv) { int is_key_auth = 0; @@ -326,104 +420,10 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) test(); cmd_res.msg = "test done..."; } else { - // superkey authrication command - const char *not_key_auth_err_msg = "superkey(not su) is required"; - if (!strcmp("key", cmd)) { - if (!is_key_auth) { - cmd_res.err_msg = not_key_auth_err_msg; - goto echo; - } - const char *sub_cmd = carr[1]; - if (!sub_cmd) sub_cmd = ""; - if (!strcmp("get", sub_cmd)) { - cmd_res.msg = get_superkey(); - } else if (!strcmp("set", sub_cmd)) { - const char *key = carr[2]; - if (!key) { - cmd_res.err_msg = "invalid new key"; - goto echo; - } - cmd_res.msg = key; - reset_superkey(key); - } else if (!strcmp("hash", sub_cmd)) { - const char *able = carr[2]; - if (able && !strcmp("enable", able)) { - cmd_res.msg = able; - enable_auth_root_key(true); - } else if (able && !strcmp("disable", able)) { - cmd_res.msg = able; - enable_auth_root_key(false); - } else { - cmd_res.err_msg = "invalid enable or disable"; - goto echo; - } - } else { - cmd_res.err_msg = "invalid subcommand"; - goto echo; - } - } else if (!strcmp("module", cmd)) { - if (!is_key_auth) { - cmd_res.err_msg = not_key_auth_err_msg; - goto echo; - } - const char *sub_cmd = carr[1]; - if (!sub_cmd) sub_cmd = ""; - if (!strcmp("num", sub_cmd)) { - int num = get_module_nums(); - supercmd_echo(u_filename_p, uargv, &sp, "%d", num); - } else if (!strcmp("list", sub_cmd)) { - buffer[0] = '\0'; - list_modules(buffer, sizeof(buffer)); - cmd_res.msg = buffer; - } else if (!strcmp("load", sub_cmd)) { - const char *path = carr[2]; - if (!path) { - cmd_res.err_msg = "invalid module path"; - goto echo; - } - cmd_res.rc = load_module_path(path, carr[3], 0); - if (!cmd_res.rc) cmd_res.msg = path; - } else if (!strcmp("ctl0", sub_cmd)) { - const char *name = carr[2]; - if (!name) { - cmd_res.err_msg = "invalid module name"; - goto echo; - } - const char *mod_args = carr[3]; - if (!mod_args) { - cmd_res.err_msg = "invalid control arguments"; - goto echo; - } - buffer[0] = '\0'; - cmd_res.rc = module_control0(name, mod_args, buffer, sizeof(buffer)); - cmd_res.msg = buffer; - } else if (!strcmp("ctl1", sub_cmd)) { - cmd_res.err_msg = "not implement"; - } else if (!strcmp("unload", sub_cmd)) { - const char *name = carr[2]; - if (!name) { - cmd_res.err_msg = "invalid module name"; - goto echo; - } - cmd_res.rc = unload_module(name, 0); - if (!cmd_res.rc) cmd_res.msg = name; - } else if (!strcmp("info", sub_cmd)) { - const char *name = carr[2]; - if (!name) { - cmd_res.err_msg = "invalid module name"; - goto echo; - } - buffer[0] = '\0'; - int sz = get_module_info(name, buffer, sizeof(buffer)); - if (sz <= 0) cmd_res.rc = sz; - cmd_res.msg = buffer; - } else { - cmd_res.err_msg = "invalid subcommand"; - goto echo; - } + if (is_key_auth) { + handle_cmd_key_auth(u_filename_p, cmd, carr, buffer, &cmd_res); } else { - cmd_res.err_msg = "invalid command"; - goto echo; + cmd_res.err_msg = "invalid command or a superkey is required"; } } From 33b7e085bb80327ba43be50f1ef2cb9211d8dbb3 Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 5 Sep 2024 22:07:49 +0800 Subject: [PATCH 35/71] fix supercmd report --- kernel/patch/common/supercmd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 7f259233..4ed5fc55 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -410,6 +410,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } else if (!strcmp("event", cmd)) { if (carr[1]) { cmd_res.rc = report_user_event(carr[1], carr[2]); + if (!cmd_res.rc) cmd_res.msg = "report success"; } else { cmd_res.err_msg = "empty event"; } @@ -436,7 +437,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) // free args for (int i = 2; i < sizeof(parr) / sizeof(parr[0]); i++) { const char *a = parr[i]; - if (!a) break; + if (!a) continue; kfree(a); } } From 6511dab839f3fa0695f8626f9cb010dfc32ac332 Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 5 Sep 2024 22:08:18 +0800 Subject: [PATCH 36/71] feat: try support 6.6 --- README.md | 3 +-- tools/kallsym.c | 35 +++++++++++++++++++---------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index a2f54da3..95c1211a 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,7 @@ CONFIG_KALLSYMS=y Currently only supports arm64 architecture. -Linux 3.18 - 6.2 (theoretically) -Linux 6.3+ (not yet adapted) +Linux 3.18 - 6.6 (theoretically) ## Get Involved diff --git a/tools/kallsym.c b/tools/kallsym.c index 099827b5..8717bb27 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -440,29 +440,31 @@ static int32_t find_approx_addresses_or_offset(kallsym_t *info, char *img, int32 static int find_num_syms(kallsym_t *info, char *img, int32_t imglen) { - int32_t approx_end = info->_approx_addresses_or_offsets_end; +#define NSYMS_MAX_GAP 10 + + int32_t approx_end = info->kallsyms_names_offset; // int32_t num_syms_elem_size = get_num_syms_elem_size(info); int32_t num_syms_elem_size = 4; int32_t approx_num_syms = info->_approx_addresses_or_offsets_num; - int32_t nsyms = 0; - int32_t nsyms_max_offset = approx_end + 4096; - int32_t NSYMS_MAX_GAP = 20; - int32_t LAST_SYM_EQUAL_NUM = 10; - int32_t cand = approx_end / num_syms_elem_size * num_syms_elem_size - LAST_SYM_EQUAL_NUM * num_syms_elem_size; - for (; cand < nsyms_max_offset; cand += num_syms_elem_size) { - nsyms = (int)int_unpack(img + cand, num_syms_elem_size, info->is_be); - if (approx_num_syms >= nsyms && approx_num_syms - nsyms < NSYMS_MAX_GAP) break; + for (int32_t cand = approx_end; cand > approx_end - 4096; cand -= num_syms_elem_size) { + int nsyms = (int)int_unpack(img + cand, num_syms_elem_size, info->is_be); + if (!nsyms) continue; + if (approx_num_syms > nsyms && approx_num_syms - nsyms > NSYMS_MAX_GAP) continue; + if (nsyms > approx_num_syms && nsyms - approx_num_syms > NSYMS_MAX_GAP) continue; + // find + info->kallsyms_num_syms = nsyms; + info->kallsyms_num_syms_offset = cand; + break; } - if (cand >= nsyms_max_offset) { - tools_loge("kallsyms_num_syms error\n"); - return -1; + if (info->kallsyms_num_syms_offset) { + info->kallsyms_num_syms = approx_num_syms - NSYMS_MAX_GAP; + tools_logw("can't find kallsyms_num_syms, try: 0x%08x\n", info->kallsyms_num_syms); } else { - info->kallsyms_num_syms = nsyms; - info->kallsyms_num_syms_offset = cand; - tools_logi("kallsyms_num_syms offset: 0x%08x, value: 0x%08x\n", cand, nsyms); + tools_logi("kallsyms_num_syms offset: 0x%08x, value: 0x%08x\n", info->kallsyms_num_syms_offset, + info->kallsyms_num_syms); } return 0; } @@ -576,7 +578,8 @@ static int is_symbol_name_pos(kallsym_t *info, char *img, int32_t pos, char *sym static int find_names(kallsym_t *info, char *img, int32_t imglen) { int32_t marker_elem_size = get_markers_elem_size(info); - int32_t cand = info->_approx_addresses_or_offsets_offset; + // int32_t cand = info->_approx_addresses_or_offsets_offset; + int32_t cand = 0x4000; int32_t test_marker_num = -1; for (; cand < info->kallsyms_markers_offset; cand++) { int32_t pos = cand; From c09886198d92eb4575ca624080ef69a273055b64 Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 5 Sep 2024 22:10:28 +0800 Subject: [PATCH 37/71] fix: preset symbol --- tools/symbol.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/symbol.c b/tools/symbol.c index 9c5c275a..d3787b90 100644 --- a/tools/symbol.c +++ b/tools/symbol.c @@ -126,7 +126,6 @@ int fillin_patch_symbol(kallsym_t *kallsym, char *img_buf, int imglen, patch_sym symbol->slow_avc_audit = try_get_symbol_offset_zero(kallsym, img_buf, "slow_avc_audit"); - symbol->policydb_write = try_get_symbol_offset_zero(kallsym, img_buf, "policydb_write"); symbol->input_handle_event = get_symbol_offset_zero(kallsym, img_buf, "input_handle_event"); if ((is_be() ^ target_is_be)) { From 34ae841412ae85fa0790fe11d8566ad4cdab8b82 Mon Sep 17 00:00:00 2001 From: bmax Date: Fri, 13 Sep 2024 22:44:54 +0800 Subject: [PATCH 38/71] export syscall hook function --- kernel/patch/common/syscall.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index 07014d51..4bb9b0c0 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -164,6 +164,7 @@ long raw_syscall0(long nr) } return ((raw_syscall0_f)addr)(); } +KP_EXPORT_SYMBOL(raw_syscall0); long raw_syscall1(long nr, long arg0) { @@ -177,6 +178,7 @@ long raw_syscall1(long nr, long arg0) } return ((raw_syscall1_f)addr)(arg0); } +KP_EXPORT_SYMBOL(raw_syscall1); long raw_syscall2(long nr, long arg0, long arg1) { @@ -191,6 +193,7 @@ long raw_syscall2(long nr, long arg0, long arg1) } return ((raw_syscall2_f)addr)(arg0, arg1); } +KP_EXPORT_SYMBOL(raw_syscall2); long raw_syscall3(long nr, long arg0, long arg1, long arg2) { @@ -206,6 +209,7 @@ long raw_syscall3(long nr, long arg0, long arg1, long arg2) } return ((raw_syscall3_f)addr)(arg0, arg1, arg2); } +KP_EXPORT_SYMBOL(raw_syscall3); long raw_syscall4(long nr, long arg0, long arg1, long arg2, long arg3) { @@ -222,6 +226,7 @@ long raw_syscall4(long nr, long arg0, long arg1, long arg2, long arg3) } return ((raw_syscall4_f)addr)(arg0, arg1, arg2, arg3); } +KP_EXPORT_SYMBOL(raw_syscall4); long raw_syscall5(long nr, long arg0, long arg1, long arg2, long arg3, long arg4) { @@ -239,6 +244,7 @@ long raw_syscall5(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 } return ((raw_syscall5_f)addr)(arg0, arg1, arg2, arg3, arg4); } +KP_EXPORT_SYMBOL(raw_syscall5); long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4, long arg5) { @@ -257,6 +263,7 @@ long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 } return ((raw_syscall6_f)addr)(arg0, arg1, arg2, arg3, arg4, arg5); } +KP_EXPORT_SYMBOL(raw_syscall6); hook_err_t __fp_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) { @@ -272,6 +279,7 @@ hook_err_t __fp_hook_syscalln(int nr, int narg, int is_compat, void *before, voi return fp_hook_wrap(fp_addr, narg, before, after, udata); } } +KP_EXPORT_SYMBOL(__fp_hook_syscalln); void __fp_unhook_syscalln(int nr, int is_compat, void *before, void *after) { @@ -285,6 +293,7 @@ void __fp_unhook_syscalln(int nr, int is_compat, void *before, void *after) fp_hook_unwrap(fp_addr, before, after); } } +KP_EXPORT_SYMBOL(__fp_unhook_syscalln); /* sys_xxx.cfi_jt @@ -299,36 +308,42 @@ hook_err_t __inline_hook_syscalln(int nr, int narg, int is_compat, void *before, if (has_syscall_wrapper) narg = 1; return hook_wrap((void *)addr, narg, before, after, udata); } +KP_EXPORT_SYMBOL(__inline_hook_syscalln); void __inline_unhook_syscalln(int nr, int is_compat, void *before, void *after) { uintptr_t addr = syscalln_name_addr(nr, is_compat); hook_unwrap((void *)addr, before, after); } +KP_EXPORT_SYMBOL(__inline_unhook_syscalln); hook_err_t hook_syscalln(int nr, int narg, void *before, void *after, void *udata) { if (sys_call_table) return __fp_hook_syscalln(nr, narg, 0, before, after, udata); return __inline_hook_syscalln(nr, narg, 0, before, after, udata); } +KP_EXPORT_SYMBOL(hook_syscalln); void unhook_syscalln(int nr, void *before, void *after) { if (sys_call_table) return __fp_unhook_syscalln(nr, 0, before, after); return __inline_unhook_syscalln(nr, 0, before, after); } +KP_EXPORT_SYMBOL(unhook_syscalln); hook_err_t hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) { if (compat_sys_call_table) return __fp_hook_syscalln(nr, narg, 1, before, after, udata); return __inline_hook_syscalln(nr, narg, 1, before, after, udata); } +KP_EXPORT_SYMBOL(hook_compat_syscalln); void unhook_compat_syscalln(int nr, void *before, void *after) { if (compat_sys_call_table) return __fp_unhook_syscalln(nr, 1, before, after); return __inline_unhook_syscalln(nr, 1, before, after); } +KP_EXPORT_SYMBOL(unhook_compat_syscalln); void syscall_init() { From 3fc74c26ba503b79dd604a575da12d72e2ba7c21 Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 18 Sep 2024 22:09:37 +0800 Subject: [PATCH 39/71] add exclude, change shell default su scontext --- kernel/linux/include/linux/string.h | 4 ++-- kernel/patch/common/sucompat.c | 11 ++++++++--- kernel/patch/common/supercall.c | 2 +- kernel/patch/common/supercmd.c | 25 ++++++++++++++----------- kernel/patch/common/syscall.c | 8 ++++---- kernel/patch/include/accctl.h | 2 +- kernel/patch/include/uapi/scdefs.h | 10 ++++++++++ 7 files changed, 40 insertions(+), 22 deletions(-) diff --git a/kernel/linux/include/linux/string.h b/kernel/linux/include/linux/string.h index bec5fcd2..1404d35f 100644 --- a/kernel/linux/include/linux/string.h +++ b/kernel/linux/include/linux/string.h @@ -66,8 +66,8 @@ extern void *kfunc_def(memchr_inv)(const void *start, int c, size_t bytes); extern char *kfunc_def(strreplace)(char *s, char old, char new); extern void kfunc_def(fortify_panic)(const char *name); -extern int __must_check kfunc_def(kstrtoull)(const char *s, unsigned int base, unsigned long long *res); -extern int __must_check kfunc_def(kstrtoll)(const char *s, unsigned int base, long long *res); +extern int kfunc_def(kstrtoull)(const char *s, unsigned int base, unsigned long long *res); +extern int kfunc_def(kstrtoll)(const char *s, unsigned int base, long long *res); static inline void kfree_const(const void *x) { diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 06161c23..1e31b60d 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -93,7 +93,7 @@ int is_su_allow_uid(uid_t uid) } KP_EXPORT_SYMBOL(is_su_allow_uid); -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, int async) +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, struct su_profile_ext *ext, int async) { if (!scontext) scontext = ""; @@ -113,6 +113,7 @@ int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, int async) new->profile.to_uid = to_uid; strncpy(new->profile.scontext, scontext, sizeof(new->profile.scontext)); new->profile.scontext[sizeof(new->profile.scontext) - 1] = '\0'; + new->profile.ext = *ext; spin_lock(&list_lock); if (old) { // update @@ -485,9 +486,13 @@ int su_compat_init() INIT_LIST_HEAD(&allow_uid_list); spin_lock_init(&list_lock); +#ifdef ANDROID // default shell - su_add_allow_uid(2000, 0, all_allow_sctx, 1); - su_add_allow_uid(0, 0, all_allow_sctx, 1); + if (!all_allow_sctx[0]) strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK); + struct su_profile_ext ext = { .exclude = 0 }; + su_add_allow_uid(2000, 0, all_allow_sctx, &ext, 1); + su_add_allow_uid(0, 0, all_allow_sctx, &ext, 1); +#endif hook_err_t rc = HOOK_NO_ERR; diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 72c1516d..05311e8f 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -179,7 +179,7 @@ static long call_grant_uid(struct su_profile *__user uprofile) { struct su_profile *profile = memdup_user(uprofile, sizeof(struct su_profile)); if (!profile || IS_ERR(profile)) return PTR_ERR(profile); - int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext, 1); + int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext, &profile->ext, 1); kvfree(profile); return rc; } diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 4ed5fc55..7a2aea1b 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -58,7 +58,7 @@ static const char supercmd_help[] = "" "KernelPatch supercmd:\n" "Usage: truncate [-uZc] [Command [[SubCommand]...]]\n" - "superkey|su: Authentication. For certain commands, if the current uid is allowed to use su,\n" + "superkey|su: Authentication for certain commands, if the current uid is allowed to use su,\n" " the 'su' string can be used for authentication.\n" "Options:\n" " -u Change user id to UID.\n" @@ -75,14 +75,14 @@ static const char supercmd_help[] = " whose full PATH is '/system/bin/kp'. This can avoid conflicts with the existing 'su' command.\n" " If you wish to modify this PATH, you can use the 'reset' command.\n" " SubCommand:\n" - " grant [TO_UID] [SCONTEXT] Grant su permission to UID.\n" - " revoke Revoke su permission to UID.\n" - " num Get the number of uids with the aforementioned permissions.\n" - " list List all su allowed uids.\n" - " profile Get the profile of the uid configuration.\n" - " path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n" - " sctx [SCONTEXT] Get or Reset current all allowed security context, \n" - " event Report EVENT.\n" + " grant [TO_UID [SCONTEXT [EXCLUDE]]] Grant su permission to UID. EXCLUDE is 'true' or 'false'.\n" + " revoke Revoke su permission to UID.\n" + " num Get the number of uids with the aforementioned permissions.\n" + " list List all su allowed uids.\n" + " profile Get the profile of the uid configuration.\n" + " path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n" + " sctx [SCONTEXT] Get or Reset current all allowed security context, \n" + " event Report EVENT.\n" "\n" "The command below requires superkey authentication.\n" " module [...]: KernelPatch Module manager\n" @@ -121,7 +121,9 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } if (carr[3]) kstrtoull(carr[3], 10, &to_uid); if (carr[4]) scontext = carr[4]; - su_add_allow_uid(uid, to_uid, scontext, 1); + struct su_profile_ext ext = { .exclude = false }; + if (carr[5] && !strcmp(carr[5], "true")) ext.exclude = true; + su_add_allow_uid(uid, to_uid, scontext, &ext, 1); sprintf(buffer, "grant %d, %d, %s", uid, to_uid, scontext); cmd_res->msg = buffer; } else if (!strcmp(sub_cmd, "revoke")) { @@ -160,7 +162,8 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char cmd_res->rc = su_allow_uid_profile(0, uid, &profile); if (cmd_res->rc) return; - sprintf(buffer, "uid: %d, to_uid: %d, scontext: %s", profile.uid, profile.to_uid, profile.scontext); + sprintf(buffer, "uid: %d, to_uid: %d, scontext: %s, exclude: %d", profile.uid, profile.to_uid, profile.scontext, + profile.ext.exclude); cmd_res->msg = buffer; } else if (!strcmp(sub_cmd, "path")) { diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index 4bb9b0c0..17c64d6e 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -357,11 +357,11 @@ void syscall_init() *addr = link2runtime(*addr); } - // sys_call_table = (typeof(sys_call_table))kallsyms_lookup_name("sys_call_table"); - // log_boot("sys_call_table addr: %llx\n", sys_call_table); + sys_call_table = (typeof(sys_call_table))kallsyms_lookup_name("sys_call_table"); + log_boot("sys_call_table addr: %llx\n", sys_call_table); - // compat_sys_call_table = (typeof(compat_sys_call_table))kallsyms_lookup_name("compat_sys_call_table"); - // log_boot("compat_sys_call_table addr: %llx\n", compat_sys_call_table); + compat_sys_call_table = (typeof(compat_sys_call_table))kallsyms_lookup_name("compat_sys_call_table"); + log_boot("compat_sys_call_table addr: %llx\n", compat_sys_call_table); has_config_compat = 0; has_syscall_wrapper = 0; diff --git a/kernel/patch/include/accctl.h b/kernel/patch/include/accctl.h index 771a133b..ebc87b57 100644 --- a/kernel/patch/include/accctl.h +++ b/kernel/patch/include/accctl.h @@ -24,7 +24,7 @@ int commit_common_su(uid_t to_uid, const char *sctx); int commit_su(uid_t uid, const char *sctx); int task_su(pid_t pid, uid_t to_uid, const char *sctx); -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, int async); +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, struct su_profile_ext *ext, int async); int su_remove_allow_uid(uid_t uid, int async); int su_allow_uid_nums(); int su_allow_uids(int is_user, uid_t *out_uids, int out_num); diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index b1392ad4..42234bb8 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -55,11 +55,21 @@ static inline long hash_key(const char *key) #define SUPERCALL_KEY_MAX_LEN 0x40 #define SUPERCALL_SCONTEXT_LEN 0x60 +struct su_profile_ext +{ + union + { + bool exclude; + }; + char _[32]; +}; + struct su_profile { uid_t uid; uid_t to_uid; char scontext[SUPERCALL_SCONTEXT_LEN]; + struct su_profile_ext ext; }; #ifdef ANDROID From bb3a8286a16dad46b133c10f1082409c69998167 Mon Sep 17 00:00:00 2001 From: bmax Date: Sat, 21 Sep 2024 10:26:54 +0800 Subject: [PATCH 40/71] 1. enable sepolicy flag fix, 2. fix some supercmd, 3. module code size 2M->4M --- kernel/include/preset.h | 2 +- kernel/patch/common/supercmd.c | 17 +++++++++-------- kernel/patch/patch.c | 6 +++--- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/kernel/include/preset.h b/kernel/include/preset.h index b63772de..b1a3edc2 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -20,7 +20,7 @@ #define COMPILE_TIME_LEN 0x18 #define MAP_MAX_SIZE 0xa00 #define HOOK_ALLOC_SIZE (1 << 20) -#define MEMORY_ROX_SIZE (2 << 20) +#define MEMORY_ROX_SIZE (4 << 20) #define MEMORY_RW_SIZE (2 << 20) #define MAP_ALIGN 0x10 diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 7a2aea1b..d63f92dd 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -58,7 +58,7 @@ static const char supercmd_help[] = "" "KernelPatch supercmd:\n" "Usage: truncate [-uZc] [Command [[SubCommand]...]]\n" - "superkey|su: Authentication for certain commands, if the current uid is allowed to use su,\n" + "superkey|su: Authentication. For certain commands, if the current uid is allowed to use su,\n" " the 'su' string can be used for authentication.\n" "Options:\n" " -u Change user id to UID.\n" @@ -106,7 +106,8 @@ struct cmd_res int rc; }; -static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char *buffer, struct cmd_res *cmd_res) +static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char *buffer, int buflen, + struct cmd_res *cmd_res) { const char *sub_cmd = carr[1]; if (!sub_cmd) sub_cmd = ""; @@ -189,7 +190,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char // superkey commands static void handle_cmd_key_auth(char **__user u_filename_p, const char *cmd, const char **carr, char *buffer, - struct cmd_res *cmd_res) + int buflen, struct cmd_res *cmd_res) { if (!strcmp("key", cmd)) { const char *sub_cmd = carr[1]; @@ -228,7 +229,7 @@ static void handle_cmd_key_auth(char **__user u_filename_p, const char *cmd, con sprintf(buffer, "%d\n", num); cmd_res->msg = buffer; } else if (!strcmp("list", sub_cmd)) { - list_modules(buffer, sizeof(buffer)); + list_modules(buffer, buflen); cmd_res->msg = buffer; } else if (!strcmp("load", sub_cmd)) { const char *path = carr[2]; @@ -250,7 +251,7 @@ static void handle_cmd_key_auth(char **__user u_filename_p, const char *cmd, con return; } buffer[0] = '\0'; - cmd_res->rc = module_control0(name, mod_args, buffer, sizeof(buffer)); + cmd_res->rc = module_control0(name, mod_args, buffer, buflen); cmd_res->msg = buffer; } else if (!strcmp("ctl1", sub_cmd)) { cmd_res->err_msg = "not implement"; @@ -268,7 +269,7 @@ static void handle_cmd_key_auth(char **__user u_filename_p, const char *cmd, con cmd_res->err_msg = "invalid module name"; return; } - int sz = get_module_info(name, buffer, sizeof(buffer)); + int sz = get_module_info(name, buffer, buflen); if (sz <= 0) cmd_res->rc = sz; cmd_res->msg = buffer; } else { @@ -409,7 +410,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) supercmd_echo(u_filename_p, uargv, &sp, "%x,%x", kver, kpver); goto free; } else if (!strcmp("sumgr", cmd)) { - handle_cmd_sumgr(u_filename_p, carr, buffer, &cmd_res); + handle_cmd_sumgr(u_filename_p, carr, buffer, sizeof(buffer), &cmd_res); } else if (!strcmp("event", cmd)) { if (carr[1]) { cmd_res.rc = report_user_event(carr[1], carr[2]); @@ -425,7 +426,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) cmd_res.msg = "test done..."; } else { if (is_key_auth) { - handle_cmd_key_auth(u_filename_p, cmd, carr, buffer, &cmd_res); + handle_cmd_key_auth(u_filename_p, cmd, carr, buffer, sizeof(buffer), &cmd_res); } else { cmd_res.err_msg = "invalid command or a superkey is required"; } diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 4fd0eafa..4b322010 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -53,7 +53,7 @@ void syscall_init(); #ifdef ANDROID int android_user_init(); -int android_sepolicy_flags_init(); +int android_sepolicy_flags_fix(); #endif static void before_rest_init(hook_fargs4_t *args, void *udata) @@ -83,8 +83,8 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) log_boot("resolve_pt_regs done: %d\n", rc); #ifdef ANDROID - // rc = android_sepolicy_flags_init(); - // log_boot("android_sepolicy_flags_init done: %d\n", rc); + rc = android_sepolicy_flags_fix(); + log_boot("android_sepolicy_flags_fix done: %d\n", rc); rc = android_user_init(); log_boot("android_user_init done: %d\n", rc); From deed2d19464499541bc33fc29dabd039f284f909 Mon Sep 17 00:00:00 2001 From: bmax Date: Sat, 21 Sep 2024 19:58:22 +0800 Subject: [PATCH 41/71] test fix bti --- kernel/base/hook.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/base/hook.c b/kernel/base/hook.c index 3bf0cab4..00e89319 100644 --- a/kernel/base/hook.c +++ b/kernel/base/hook.c @@ -15,7 +15,7 @@ #define bit(n, st) (((n) >> (st)) & 1) #define sign64_extend(n, len) \ (((uint64_t)((n) << (63u - (len - 1))) >> 63u) ? ((n) | (0xFFFFFFFFFFFFFFFF << (len))) : n) -#define align_ceil(x, align) (((u64)(x) + (u64)(align)-1) & ~((u64)(align)-1)) +#define align_ceil(x, align) (((u64)(x) + (u64)(align) - 1) & ~((u64)(align) - 1)) typedef uint32_t inst_type_t; typedef uint32_t inst_mask_t; @@ -164,7 +164,7 @@ static __noinline hook_err_t relo_b(hook_t *hook, uint64_t inst_addr, uint32_t i if (type == INST_BL) { buf[idx++] = 0xD63F0220; // BLR X17 } else { - buf[idx++] = 0xD61F0220; // BR X17 + buf[idx++] = 0xd65f0220; // BR X17 -> RET X17 } buf[idx++] = ARM64_NOP; return HOOK_NO_ERR; From dabe16f0d910b3ebf41cfc76e934a89cd0538eef Mon Sep 17 00:00:00 2001 From: bmax Date: Sat, 21 Sep 2024 22:01:07 +0800 Subject: [PATCH 42/71] fix: bti caused boot-stock or hook-crash --- kernel/base/hook.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/base/hook.c b/kernel/base/hook.c index 00e89319..58979574 100644 --- a/kernel/base/hook.c +++ b/kernel/base/hook.c @@ -69,7 +69,7 @@ static inst_type_t types[] = { INST_CBZ, INST_CBNZ, INST_TBZ, INST_TBNZ, INST_IGNORE, }; -static int32_t relo_len[] = { 6, 8, 6, 4, 4, 6, 6, 6, 8, 8, 8, 8, 6, 6, 6, 6, 2 }; +static int32_t relo_len[] = { 6, 8, 8, 4, 4, 6, 6, 6, 8, 8, 8, 8, 6, 6, 6, 6, 2 }; // static uint64_t sign_extend(uint64_t x, uint32_t len) // { @@ -162,9 +162,11 @@ static __noinline hook_err_t relo_b(hook_t *hook, uint64_t inst_addr, uint32_t i buf[idx++] = addr & 0xFFFFFFFF; buf[idx++] = addr >> 32u; if (type == INST_BL) { - buf[idx++] = 0xD63F0220; // BLR X17 + buf[idx++] = 0x1000001E; // ARD X30, . + buf[idx++] = 0x910033DE; // ADD X30, X30, #12 + buf[idx++] = 0xD65F0220; // RET X17 } else { - buf[idx++] = 0xd65f0220; // BR X17 -> RET X17 + buf[idx++] = 0xD65F0220; // RET X17 } buf[idx++] = ARM64_NOP; return HOOK_NO_ERR; @@ -253,7 +255,7 @@ static __noinline hook_err_t relo_cb(hook_t *hook, uint64_t inst_addr, uint32_t buf[0] = (inst & 0xFF00001F) | 0x40u; // CB(N)Z Rt, #8 buf[1] = 0x14000005; // B #20 buf[2] = 0x58000051; // LDR X17, #8 - buf[3] = 0xd61f0220; // BR X17 + buf[3] = 0xD65F0220; // RET X17 buf[4] = addr & 0xFFFFFFFF; buf[5] = addr >> 32u; return HOOK_NO_ERR; @@ -271,7 +273,7 @@ static __noinline hook_err_t relo_tb(hook_t *hook, uint64_t inst_addr, uint32_t buf[0] = (inst & 0xFFF8001F) | 0x40u; // TB(N)Z Rt, #, #8 buf[1] = 0x14000005; // B #20 buf[2] = 0x58000051; // LDR X17, #8 - buf[3] = 0xd61f0220; // BR X17 + buf[3] = 0xd61f0220; // RET X17 buf[4] = addr & 0xFFFFFFFF; buf[5] = addr >> 32u; return HOOK_NO_ERR; @@ -316,7 +318,7 @@ KP_EXPORT_SYMBOL(branch_absolute); int32_t ret_absolute(uint32_t *buf, uint64_t addr) { buf[0] = 0x58000051; // LDR X17, #8 - buf[1] = 0xd65f0220; // RET X17 + buf[1] = 0xD65F0220; // RET X17 buf[2] = addr & 0xFFFFFFFF; buf[3] = addr >> 32u; return 4; From b6c45aed14db5e51d5fc5bc627cf377ba887e4a4 Mon Sep 17 00:00:00 2001 From: bmax Date: Sat, 21 Sep 2024 22:09:36 +0800 Subject: [PATCH 43/71] fix typo --- kernel/base/hook.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/base/hook.c b/kernel/base/hook.c index 58979574..c568ed29 100644 --- a/kernel/base/hook.c +++ b/kernel/base/hook.c @@ -162,7 +162,7 @@ static __noinline hook_err_t relo_b(hook_t *hook, uint64_t inst_addr, uint32_t i buf[idx++] = addr & 0xFFFFFFFF; buf[idx++] = addr >> 32u; if (type == INST_BL) { - buf[idx++] = 0x1000001E; // ARD X30, . + buf[idx++] = 0x1000001E; // ADR X30, . buf[idx++] = 0x910033DE; // ADD X30, X30, #12 buf[idx++] = 0xD65F0220; // RET X17 } else { From 925f287f2aa7e4f2796b6d423af054eb1338131b Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 22 Sep 2024 20:58:35 +0800 Subject: [PATCH 44/71] rename patch_symbol to patch_config --- kernel/base/predata.c | 14 ++++++-------- kernel/base/setup1.S | 8 ++++---- kernel/base/start.h | 6 +++--- kernel/include/predata.h | 5 ++--- kernel/include/preset.h | 18 +++++++++--------- kernel/patch/android/userd.c | 2 +- kernel/patch/common/accctl.c | 4 ++-- kernel/patch/common/secpass.c | 6 +++--- kernel/patch/common/selinuxhook.c.bak | 4 ++-- kernel/patch/common/taskob.c | 4 ++-- kernel/patch/patch.c | 8 ++++---- tools/patch.c | 2 +- tools/symbol.c | 2 +- tools/symbol.h | 2 +- 14 files changed, 41 insertions(+), 44 deletions(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 71878bbb..1809a41b 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "start.h" #include "pgtable.h" @@ -16,7 +17,9 @@ extern start_preset_t start_preset; static char *superkey = 0; static char *root_superkey = 0; -static struct patch_symbol *patch_symbol = 0; + +struct patch_config *patch_config = 0; +KP_EXPORT_SYMBOL(patch_config); static const char bstr[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; @@ -71,11 +74,6 @@ const char *get_superkey() return superkey; } -struct patch_symbol *get_preset_patch_sym() -{ - return patch_symbol; -} - int on_each_extra_item(int (*callback)(const patch_extra_item_t *extra, const char *arg, const void *con, void *udata), void *udata) { @@ -128,9 +126,9 @@ void predata_init() } log_boot("gen rand key: %s\n", superkey); - patch_symbol = &start_preset.patch_symbol; + patch_config = &start_preset.patch_config; - for (uintptr_t addr = (uint64_t)patch_symbol; addr < (uintptr_t)patch_symbol + PATCH_SYMBOL_LEN; + for (uintptr_t addr = (uint64_t)patch_config; addr < (uintptr_t)patch_config + PATCH_CONFIG_LEN; addr += sizeof(uintptr_t)) { uintptr_t *p = (uintptr_t *)addr; if (*p) *p += kernel_va; diff --git a/kernel/base/setup1.S b/kernel/base/setup1.S index 10c05e26..9cb6f978 100644 --- a/kernel/base/setup1.S +++ b/kernel/base/setup1.S @@ -109,10 +109,10 @@ start_prepare: mov x2, #ROOT_SUPER_KEY_HASH_LEN bl memcpy8 - // memcpy(&start_preset.patch_symbol, &setup_preset.patch_symbol, sizeof(header.patch_symbol)); - add x0, x11, #start_patch_symbol_offset; - add x1, x10, #setup_patch_symbol_offset - mov x2, #PATCH_SYMBOL_LEN + // memcpy(&start_preset.patch_config, &setup_preset.patch_config, sizeof(header.patch_config)); + add x0, x11, #start_patch_config_offset; + add x1, x10, #setup_patch_config_offset + mov x2, #PATCH_CONFIG_LEN bl memcpy8 // backup map area diff --git a/kernel/base/start.h b/kernel/base/start.h index 5766bfbc..3cc3b665 100644 --- a/kernel/base/start.h +++ b/kernel/base/start.h @@ -24,7 +24,7 @@ typedef struct uint8_t map_backup[MAP_MAX_SIZE]; uint8_t superkey[SUPER_KEY_LEN]; uint8_t root_superkey[ROOT_SUPER_KEY_HASH_LEN]; - patch_symbol_t patch_symbol; + patch_config_t patch_config; } start_preset_t; #else #define start_header_offset 0 @@ -39,8 +39,8 @@ typedef struct #define start_map_backup_offset (start_map_backup_len_offset + 8) #define start_superkey_offset (start_map_backup_offset + MAP_MAX_SIZE) #define start_root_superkey_offset (start_superkey_offset + SUPER_KEY_LEN) -#define start_patch_symbol_offset (start_root_superkey_offset + ROOT_SUPER_KEY_HASH_LEN) -#define start_patch_extra_offset_offset (start_patch_symbol_offset + PATCH_SYMBOL_LEN) +#define start_patch_config_offset (start_root_superkey_offset + ROOT_SUPER_KEY_HASH_LEN) +#define start_patch_extra_offset_offset (start_patch_config_offset + PATCH_CONFIG_LEN) #define start_patch_extra_size_offset (start_patch_extra_offset_offset + 8) #define start_end (start_patch_extra_size_offset + 8) #endif diff --git a/kernel/include/predata.h b/kernel/include/predata.h index 5d02451c..136b77eb 100644 --- a/kernel/include/predata.h +++ b/kernel/include/predata.h @@ -9,14 +9,13 @@ #include #include +extern struct patch_config *patch_config; + int auth_superkey(const char *key); void reset_superkey(const char *key); void enable_auth_root_key(bool enable); const char *get_superkey(); - uint64_t rand_next(); -uint64_t get_build_config(); -struct patch_symbol *get_preset_patch_sym(); int on_each_extra_item(int (*callback)(const patch_extra_item_t *extra, const char *arg, const void *data, void *udata), void *udata); diff --git a/kernel/include/preset.h b/kernel/include/preset.h index b1a3edc2..ba7471f6 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -30,7 +30,7 @@ #define MAP_SYMBOL_NUM (5) #define MAP_SYMBOL_SIZE (MAP_SYMBOL_NUM * 8) -#define PATCH_SYMBOL_LEN (512) +#define PATCH_CONFIG_LEN (512) #define ADDITIONAL_LEN (512) @@ -98,7 +98,7 @@ _Static_assert(sizeof(map_symbol_t) == MAP_SYMBOL_SIZE, "sizeof map_symbol_t mis #endif #ifndef __ASSEMBLY__ -struct patch_symbol +struct patch_config { union { @@ -120,11 +120,11 @@ struct patch_symbol uint64_t slow_avc_audit; uint64_t input_handle_event; }; - char _cap[PATCH_SYMBOL_LEN]; + char _cap[PATCH_CONFIG_LEN]; }; }; -typedef struct patch_symbol patch_symbol_t; -_Static_assert(sizeof(patch_symbol_t) == PATCH_SYMBOL_LEN, "sizeof patch_symbol_t mismatch"); +typedef struct patch_config patch_config_t; +_Static_assert(sizeof(patch_config_t) == PATCH_CONFIG_LEN, "sizeof patch_config_t mismatch"); #endif #ifndef __ASSEMBLY__ @@ -210,7 +210,7 @@ typedef struct map_symbol_t map_symbol; uint8_t header_backup[HDR_BACKUP_SIZE]; uint8_t superkey[SUPER_KEY_LEN]; - patch_symbol_t patch_symbol; + patch_config_t patch_config; char additional[ADDITIONAL_LEN]; } setup_preset_be_000a04_t; @@ -235,7 +235,7 @@ typedef struct _setup_preset_t uint8_t superkey[SUPER_KEY_LEN]; uint8_t root_superkey[ROOT_SUPER_KEY_HASH_LEN]; uint8_t __[SETUP_PRESERVE_LEN]; - patch_symbol_t patch_symbol; + patch_config_t patch_config; char additional[ADDITIONAL_LEN]; } setup_preset_t; #else @@ -256,8 +256,8 @@ typedef struct _setup_preset_t #define setup_header_backup_offset (setup_map_symbol_offset + MAP_SYMBOL_SIZE) #define setup_superkey_offset (setup_header_backup_offset + HDR_BACKUP_SIZE) #define setup_root_superkey_offset (setup_superkey_offset + SUPER_KEY_LEN) -#define setup_patch_symbol_offset (setup_root_superkey_offset + ROOT_SUPER_KEY_HASH_LEN + SETUP_PRESERVE_LEN) -#define setup_end (setup_patch_symbol_offset + PATCH_SYMBOL_LEN) +#define setup_patch_config_offset (setup_root_superkey_offset + ROOT_SUPER_KEY_HASH_LEN + SETUP_PRESERVE_LEN) +#define setup_end (setup_patch_config_offset + PATCH_CONFIG_LEN) #endif #ifndef __ASSEMBLY__ diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index e120767d..2c20299c 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -371,7 +371,7 @@ int android_user_init() log_boot("hook __NR_openat rc: %d\n", rc); ret |= rc; - unsigned long input_handle_event_addr = get_preset_patch_sym()->input_handle_event; + unsigned long input_handle_event_addr = patch_config->input_handle_event; if (input_handle_event_addr) { rc = hook_wrap4((void *)input_handle_event_addr, before_input_handle_event, 0, 0); ret |= rc; diff --git a/kernel/patch/common/accctl.c b/kernel/patch/common/accctl.c index 73d39958..6d09f1bf 100644 --- a/kernel/patch/common/accctl.c +++ b/kernel/patch/common/accctl.c @@ -234,7 +234,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi int bypass_selinux() { - unsigned long avc_denied_addr = get_preset_patch_sym()->avc_denied; + unsigned long avc_denied_addr = patch_config->avc_denied; if (avc_denied_addr) { hook_err_t err = hook((void *)avc_denied_addr, (void *)avc_denied_replace, (void **)&avc_denied_backup); if (err != HOOK_NO_ERR) { @@ -242,7 +242,7 @@ int bypass_selinux() } } - unsigned long slow_avc_audit_addr = get_preset_patch_sym()->slow_avc_audit; + unsigned long slow_avc_audit_addr = patch_config->slow_avc_audit; if (slow_avc_audit_addr) { hook_err_t err = hook((void *)slow_avc_audit_addr, (void *)slow_avc_audit_replace, (void **)&slow_avc_audit_backup); diff --git a/kernel/patch/common/secpass.c b/kernel/patch/common/secpass.c index d1d4a394..2b6bce90 100644 --- a/kernel/patch/common/secpass.c +++ b/kernel/patch/common/secpass.c @@ -52,7 +52,7 @@ int bypass_kcfi() // 6.1.0 // todo: Is there more elegant way? - unsigned long report_cfi_failure_addr = get_preset_patch_sym()->report_cfi_failure; + unsigned long report_cfi_failure_addr = patch_config->report_cfi_failure; if (report_cfi_failure_addr) { hook_err_t err = hook((void *)report_cfi_failure_addr, (void *)replace_report_cfi_failure, (void **)&backup_report_cfi_failure); @@ -64,9 +64,9 @@ int bypass_kcfi() } // todo: direct modify cfi_shadow, __cfi_check? - unsigned long __cfi_slowpath_addr = get_preset_patch_sym()->__cfi_slowpath_diag; + unsigned long __cfi_slowpath_addr = patch_config->__cfi_slowpath_diag; if (!__cfi_slowpath_addr) { - __cfi_slowpath_addr = get_preset_patch_sym()->__cfi_slowpath; + __cfi_slowpath_addr = patch_config->__cfi_slowpath; } if (__cfi_slowpath_addr) { hook_err_t err = diff --git a/kernel/patch/common/selinuxhook.c.bak b/kernel/patch/common/selinuxhook.c.bak index 2e2329c8..20be0f2d 100644 --- a/kernel/patch/common/selinuxhook.c.bak +++ b/kernel/patch/common/selinuxhook.c.bak @@ -299,7 +299,7 @@ static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, voi int selinux_hook_install() { - unsigned long avc_denied_addr = get_preset_patch_sym()->avc_denied; + unsigned long avc_denied_addr = patch_config->avc_denied; if (avc_denied_addr) { hook_err_t err = hook((void *)avc_denied_addr, (void *)avc_denied_replace, (void **)&avc_denied_backup); if (err != HOOK_NO_ERR) { @@ -307,7 +307,7 @@ int selinux_hook_install() } } - unsigned long slow_avc_audit_addr = get_preset_patch_sym()->slow_avc_audit; + unsigned long slow_avc_audit_addr = patch_config->slow_avc_audit; if (slow_avc_audit_addr) { hook_err_t err = hook((void *)slow_avc_audit_addr, (void *)slow_avc_audit_replace, (void **)&slow_avc_audit_backup); diff --git a/kernel/patch/common/taskob.c b/kernel/patch/common/taskob.c index d8fe863a..5b10b9be 100644 --- a/kernel/patch/common/taskob.c +++ b/kernel/patch/common/taskob.c @@ -75,12 +75,12 @@ int task_observer() prepare_init_ext(init_task); - unsigned long copy_process_addr = get_preset_patch_sym()->copy_process; + unsigned long copy_process_addr = patch_config->copy_process; if (copy_process_addr) { rc |= hook_wrap8((void *)copy_process_addr, 0, after_copy_process, 0); log_boot("hook copy_process: %llx, rc: %d\n", copy_process_addr, rc); } else { - unsigned long cgroup_post_fork_addr = get_preset_patch_sym()->cgroup_post_fork; + unsigned long cgroup_post_fork_addr = patch_config->cgroup_post_fork; if (cgroup_post_fork_addr) { rc |= hook_wrap4((void *)cgroup_post_fork_addr, 0, after_cgroup_post_fork, 0); log_boot("hook cgroup_post_fork: %llx, rc: %d\n", cgroup_post_fork_addr, rc); diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 4b322010..9f30d866 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -125,7 +125,7 @@ int patch() hook_err_t rc = 0; - unsigned long panic_addr = get_preset_patch_sym()->panic; + unsigned long panic_addr = patch_config->panic; logkd("panic addr: %llx\n", panic_addr); if (panic_addr) { rc = hook_wrap12((void *)panic_addr, before_panic, 0, 0); @@ -134,8 +134,8 @@ int patch() if (rc) return rc; // rest_init or cgroup_init - unsigned long init_addr = get_preset_patch_sym()->rest_init; - if (!init_addr) init_addr = get_preset_patch_sym()->cgroup_init; + unsigned long init_addr = patch_config->rest_init; + if (!init_addr) init_addr = patch_config->cgroup_init; if (init_addr) { rc = hook_wrap4((void *)init_addr, before_rest_init, 0, (void *)init_addr); log_boot("hook rest_init rc: %d\n", rc); @@ -143,7 +143,7 @@ int patch() if (rc) return rc; // kernel_init - unsigned long kernel_init_addr = get_preset_patch_sym()->kernel_init; + unsigned long kernel_init_addr = patch_config->kernel_init; if (kernel_init_addr) { rc = hook_wrap4((void *)kernel_init_addr, before_kernel_init, after_kernel_init, 0); log_boot("hook kernel_init rc: %d\n", rc); diff --git a/tools/patch.c b/tools/patch.c index bc981db6..cb2d0d21 100644 --- a/tools/patch.c +++ b/tools/patch.c @@ -531,7 +531,7 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * memcpy(setup->header_backup, kallsym_kimg, sizeof(setup->header_backup)); // start symbol - fillin_patch_symbol(&kallsym, kallsym_kimg, ori_kimg_len, &setup->patch_symbol, kinfo->is_be, 0); + fillin_patch_config(&kallsym, kallsym_kimg, ori_kimg_len, &setup->patch_config, kinfo->is_be, 0); // superkey if (!root_key) { diff --git a/tools/symbol.c b/tools/symbol.c index d3787b90..e8d3c405 100644 --- a/tools/symbol.c +++ b/tools/symbol.c @@ -101,7 +101,7 @@ static int get_cand_arr_symbol_offset_zero(kallsym_t *kallsym, char *img_buf, ch return offset; } -int fillin_patch_symbol(kallsym_t *kallsym, char *img_buf, int imglen, patch_symbol_t *symbol, int32_t target_is_be, +int fillin_patch_config(kallsym_t *kallsym, char *img_buf, int imglen, patch_config_t *symbol, int32_t target_is_be, bool is_android) { symbol->panic = get_symbol_offset_zero(kallsym, img_buf, "panic"); diff --git a/tools/symbol.h b/tools/symbol.h index 03a00a9a..86f22bc3 100644 --- a/tools/symbol.h +++ b/tools/symbol.h @@ -19,7 +19,7 @@ int32_t get_symbol_offset_exit(kallsym_t *info, char *img, char *symbol); int32_t find_suffixed_symbol(kallsym_t *kallsym, char *img_buf, const char *symbol); void select_map_area(kallsym_t *kallsym, char *image_buf, int32_t *map_start, int32_t *max_size); int fillin_map_symbol(kallsym_t *kallsym, char *img_buf, map_symbol_t *symbol, int32_t target_is_be); -int fillin_patch_symbol(kallsym_t *kallsym, char *img_buf, int imglen, patch_symbol_t *symbol, int32_t target_is_be, +int fillin_patch_config(kallsym_t *kallsym, char *img_buf, int imglen, patch_config_t *symbol, int32_t target_is_be, bool is_android); #endif \ No newline at end of file From 3eafd3aba4db203861be375644f844c571e30441 Mon Sep 17 00:00:00 2001 From: bmax Date: Tue, 24 Sep 2024 09:59:30 +0800 Subject: [PATCH 45/71] fix sepolicy --- kernel/include/preset.h | 6 ++++++ kernel/patch/android/sepolicy_flags.c | 12 +++++++++--- kernel/patch/common/sucompat.c | 10 +++++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/kernel/include/preset.h b/kernel/include/preset.h index ba7471f6..81658194 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -98,6 +98,10 @@ _Static_assert(sizeof(map_symbol_t) == MAP_SYMBOL_SIZE, "sizeof map_symbol_t mis #endif #ifndef __ASSEMBLY__ + +#define PATCH_CONFIG_SU_ENABLE 0x1 +#define PATCH_CONFIG_SU_HOOK_NO_WRAP 0x2 + struct patch_config { union @@ -119,6 +123,8 @@ struct patch_config uint64_t avc_denied; uint64_t slow_avc_audit; uint64_t input_handle_event; + + uint8_t patch_su_config; }; char _cap[PATCH_CONFIG_LEN]; }; diff --git a/kernel/patch/android/sepolicy_flags.c b/kernel/patch/android/sepolicy_flags.c index 2875c89e..fa17b08b 100644 --- a/kernel/patch/android/sepolicy_flags.c +++ b/kernel/patch/android/sepolicy_flags.c @@ -21,11 +21,17 @@ /* * @see: https://android-review.googlesource.com/c/kernel/common/+/3009995 */ + +static void before_policydb_write(hook_fargs2_t *args, void *udata) +{ + struct _policy_file *fp = (struct _policy_file *)args->arg1; + args->local.data0 = (uint64_t)fp->data; +} + static void after_policydb_write(hook_fargs2_t *args, void *udata) { struct _policydb *p = (struct _policydb *)args->arg0; - struct _policy_file *fp = (struct _policy_file *)args->arg1; - char *data = fp->data; + char *data = (char *)args->local.data0; if (!args->ret) { __le32 *config = (__le32 *)(data + POLICYDB_CONFIG_OFFSET); @@ -46,7 +52,7 @@ int android_sepolicy_flags_fix() unsigned long policydb_write_addr = kallsyms_lookup_name("policydb_write"); if (likely(policydb_write_addr)) { - hook_err_t err = hook_wrap2((void *)policydb_write_addr, 0, after_policydb_write, 0); + hook_err_t err = hook_wrap2((void *)policydb_write_addr, before_policydb_write, after_policydb_write, 0); if (unlikely(err != HOOK_NO_ERR)) { log_boot("hook policydb_write_addr: %llx, error: %d\n", policydb_write_addr, err); diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 1e31b60d..0911bd8d 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -39,6 +39,7 @@ #include #include #include +#include const char sh_path[] = SH_PATH; const char default_su_path[] = SU_PATH; @@ -451,19 +452,21 @@ static void su_handler_arg1_ufilename_before(hook_fargs6_t *args, void *udata) int cplen = 0; #ifdef TRY_DIRECT_MODIFY_USER cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); -#endif if (cplen > 0) { args->local.data0 = cplen; args->local.data1 = (uint64_t)*u_filename_p; logkfi("su uid: %d, cp: %d\n", uid, cplen); } else { +#endif void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); if (uptr && !IS_ERR(uptr)) { *u_filename_p = uptr; } else { logkfi("su uid: %d, cp stack error: %d\n", uid, uptr); } +#ifdef TRY_DIRECT_MODIFY_USER } +#endif } } @@ -496,6 +499,11 @@ int su_compat_init() hook_err_t rc = HOOK_NO_ERR; + uint8_t su_config = patch_config->patch_su_config; + bool enable = su_config & PATCH_CONFIG_SU_ENABLE; + bool wrap = su_config & PATCH_CONFIG_SU_HOOK_NO_WRAP; + log_boot("su config, enable: %d, wrap: %d\n"); + rc = hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)0); log_boot("hook __NR_execve rc: %d\n", rc); From 325faac507873c8d27fbb6c731da5f49dd1b1a14 Mon Sep 17 00:00:00 2001 From: bmax Date: Sat, 28 Sep 2024 16:42:51 +0800 Subject: [PATCH 46/71] tmp save --- kernel/include/preset.h | 1 + kernel/include/stdbool.h | 7 +- kernel/patch/common/kstorage.c | 224 ++++++++++++ kernel/patch/common/sucompat.c | 356 ++++-------------- kernel/patch/common/sucompat.c.bak | 554 +++++++++++++++++++++++++++++ kernel/patch/common/supercall.c | 16 +- kernel/patch/common/supercmd.c | 23 +- kernel/patch/common/syscall.c | 32 +- kernel/patch/include/accctl.h | 4 +- kernel/patch/include/kstorage.h | 42 +++ kernel/patch/include/syscall.h | 24 +- kernel/patch/include/uapi/scdefs.h | 39 +- kernel/patch/patch.c | 4 + 13 files changed, 963 insertions(+), 363 deletions(-) create mode 100644 kernel/patch/common/kstorage.c create mode 100644 kernel/patch/common/sucompat.c.bak create mode 100644 kernel/patch/include/kstorage.h diff --git a/kernel/include/preset.h b/kernel/include/preset.h index 81658194..6f9b601b 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -101,6 +101,7 @@ _Static_assert(sizeof(map_symbol_t) == MAP_SYMBOL_SIZE, "sizeof map_symbol_t mis #define PATCH_CONFIG_SU_ENABLE 0x1 #define PATCH_CONFIG_SU_HOOK_NO_WRAP 0x2 +#define PATCH_CONFIG_SU_ENABLE32 0x2 struct patch_config { diff --git a/kernel/include/stdbool.h b/kernel/include/stdbool.h index b40bcdfa..f66cbbb9 100644 --- a/kernel/include/stdbool.h +++ b/kernel/include/stdbool.h @@ -1,9 +1,12 @@ #ifndef _KP_STDBOOL_H_ #define _KP_STDBOOL_H_ +#ifndef __bool_true_false_are_defined + #define bool _Bool +#define true 1 +#define false 0 -#define true ((bool)1) -#define false ((bool)0) +#endif #endif \ No newline at end of file diff --git a/kernel/patch/common/kstorage.c b/kernel/patch/common/kstorage.c new file mode 100644 index 00000000..6fe80107 --- /dev/null +++ b/kernel/patch/common/kstorage.c @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KSTRORAGE_MAX_GROUP_NUM 4 + +// static atomic64_t used_max_group = ATOMIC_INIT(0); +static int used_max_group = 0; +static struct list_head kstorage_groups[KSTRORAGE_MAX_GROUP_NUM]; +static spinlock_t kstorage_glocks[KSTRORAGE_MAX_GROUP_NUM]; +static int group_sizes[KSTRORAGE_MAX_GROUP_NUM] = { 0 }; +static spinlock_t used_max_group_lock; + +// static void reclaim_callback(struct rcu_head *rcu) +// { +// struct kstorage *ks = container_of(rcu, struct kstorage, rcu); +// kvfree(ks); +// } + +int try_alloc_kstroage_group() +{ + spin_lock(&used_max_group_lock); + used_max_group++; + if (used_max_group >= KSTRORAGE_MAX_GROUP_NUM) return -1; + spin_unlock(&used_max_group_lock); + return used_max_group; +} + +int kstorage_group_size(int gid) +{ + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return -ENOENT; + return group_sizes[gid]; +} + +int write_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user) +{ + int rc = -ENOENT; + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return rc; + + struct list_head *head = &kstorage_groups[gid]; + spinlock_t *lock = &kstorage_glocks[gid]; + struct kstorage *pos = 0, *old = 0; + + rcu_read_lock(); + + list_for_each_entry(pos, head, list) + { + if (pos->did == did) { + old = pos; + break; + } + } + + struct kstorage *new = (struct kstorage *)vmalloc(sizeof(struct kstorage) + len); + new->gid = gid; + new->did = did; + new->dlen = 0; + if (data_is_user) { + void *drc = memdup_user(data + offset, len); + if (IS_ERR(drc)) { + rcu_read_unlock(); + return PTR_ERR(drc); + } + memcpy(new->data, drc, len); + kvfree(drc); + } else { + memcpy(new->data, data + offset, len); + } + new->dlen = len; + + spin_lock(lock); + if (old) { // update + list_replace_rcu(&old->list, &new->list); + logkfi("update %d %d\n", gid, did); + } else { // add new one + list_add_rcu(&new->list, head); + group_sizes[gid]++; + logkfi("new %d %d\n", gid, did); + } + spin_unlock(lock); + + rcu_read_unlock(); + + if (old) { + // if (async) { + // call_rcu(&old->rcu, reclaim_callback); + // } else { + synchronize_rcu(); + kvfree(old); + // } + } + return 0; +} +KP_EXPORT_SYMBOL(write_kstorage); + +const struct kstorage *get_kstorage(int gid, long did) +{ + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return ERR_PTR(-ENOENT); + + struct list_head *head = &kstorage_groups[gid]; + struct kstorage *pos = 0; + + list_for_each_entry(pos, head, list) + { + if (pos->did == did) { + return pos; + } + } + + return ERR_PTR(-ENOENT); +} +KP_EXPORT_SYMBOL(get_kstorage); + +int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata) +{ + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return; + + int rc = 0; + + struct list_head *head = &kstorage_groups[gid]; + struct kstorage *pos = 0; + + rcu_read_lock(); + + list_for_each_entry(pos, head, list) + { + int rc = cb(pos, udata); + if (rc) break; + } + + rcu_read_unlock(); + + return rc; +} +KP_EXPORT_SYMBOL(on_each_kstorage_elem); + +int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user) +{ + int rc = 0; + rcu_read_lock(); + + struct kstorage *pos = get_kstorage(gid, did); + if (IS_ERR(pos)) return PTR_ERR(pos); + + int min_len = pos->dlen - offset > len ? len : pos->dlen - offset; + + if (data_is_user) { + int cplen = compat_copy_to_user(data, pos->data + offset, min_len); + logkfd("%d %ld %d\n", gid, did, pos->dlen); + + if (cplen <= 0) { + logkfd("compat_copy_to_user error: %d", cplen); + rc = cplen; + } + } else { + memcpy(data, pos->data + offset, min_len); + } + + rcu_read_unlock(); + return rc; +} +KP_EXPORT_SYMBOL(read_kstorage); + +int remove_kstorage(int gid, long did) +{ + int rc = -ENOENT; + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return rc; + + struct list_head *head = &kstorage_groups[gid]; + spinlock_t *lock = &kstorage_glocks[gid]; + struct kstorage *pos = 0; + + spin_lock(&kstorage_glocks[gid]); + + list_for_each_entry(pos, head, list) + { + if (pos->did == did) { + list_del_rcu(&pos->list); + spin_unlock(lock); + + group_sizes[did]--; + + logkfi("%d %ld\n", gid, did); + + // if (async) { + // call_rcu(&pos->rcu, reclaim_callback); + // } else { + synchronize_rcu(); + kvfree(pos); + // } + return 0; + } + } + + spin_unlock(lock); + + return 0; +} +KP_EXPORT_SYMBOL(remove_kstorage); + +int kstorage_init() +{ + for (int i = 0; i < KSTRORAGE_MAX_GROUP_NUM; i++) { + INIT_LIST_HEAD(&kstorage_groups[i]); + spin_lock_init(&kstorage_glocks[i]); + } + spin_lock_init(&used_max_group_lock); + + return 0; +} \ No newline at end of file diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 0911bd8d..54e27de1 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -19,20 +19,17 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include #include #include #include -#include #include #include #include @@ -40,6 +37,7 @@ #include #include #include +#include const char sh_path[] = SH_PATH; const char default_su_path[] = SU_PATH; @@ -51,161 +49,82 @@ const char apd_path[] = APD_PATH; static const char *current_su_path = 0; -static struct list_head allow_uid_list; -static spinlock_t list_lock; - -static void allow_reclaim_callback(struct rcu_head *rcu) +struct su_profile { - struct allow_uid *allow = container_of(rcu, struct allow_uid, rcu); - kvfree(allow); -} - -struct su_profile profile_su_allow_uid(uid_t uid) -{ - rcu_read_lock(); - struct allow_uid *pos; - struct su_profile profile = { 0 }; - list_for_each_entry_rcu(pos, &allow_uid_list, list) - { - if (pos->uid == uid) { - memcpy(&profile, &pos->profile, sizeof(struct su_profile)); - rcu_read_unlock(); - return profile; - } - } - rcu_read_unlock(); - return profile; -} -KP_EXPORT_SYMBOL(profile_su_allow_uid); + uid_t uid; + uid_t to_uid; + char scontext[SUPERCALL_SCONTEXT_LEN]; +}; int is_su_allow_uid(uid_t uid) { rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry_rcu(pos, &allow_uid_list, list) - { - if (pos->uid == uid) { - rcu_read_unlock(); - return 1; - } - } + const struct kstorage *ks = get_kstorage(KSTORAGE_SU_LIST_GROUP, uid); + struct su_profile *profile = (struct su_profile *)ks->data; + int rc = profile != 0; rcu_read_unlock(); - return 0; + return rc; } KP_EXPORT_SYMBOL(is_su_allow_uid); -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, struct su_profile_ext *ext, int async) +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext) { if (!scontext) scontext = ""; - - rcu_read_lock(); - struct allow_uid *pos, *old = 0; - list_for_each_entry(pos, &allow_uid_list, list) - { - if (pos->uid == uid) { - old = pos; - break; - } - } - // todo: vmalloc -> kmalloc, gfp - struct allow_uid *new = (struct allow_uid *)vmalloc(sizeof(struct allow_uid)); - new->uid = uid; - new->profile.uid = uid; - new->profile.to_uid = to_uid; - strncpy(new->profile.scontext, scontext, sizeof(new->profile.scontext)); - new->profile.scontext[sizeof(new->profile.scontext) - 1] = '\0'; - new->profile.ext = *ext; - - spin_lock(&list_lock); - if (old) { // update - list_replace_rcu(&old->list, &new->list); - logkfi("update uid: %d, to_uid: %d, sctx: %s\n", uid, new->profile.to_uid, new->profile.scontext); - } else { // add new one - list_add_rcu(&new->list, &allow_uid_list); - logkfi("new uid: %d, to_uid: %d, sctx: %s\n", uid, new->profile.to_uid, new->profile.scontext); - } - spin_unlock(&list_lock); - - rcu_read_unlock(); - if (old) { - if (async) { - call_rcu(&old->rcu, allow_reclaim_callback); - } else { - synchronize_rcu(); - kvfree(old); - } - } - return 0; + struct su_profile profile = { uid, to_uid, scontext }; + int rc = write_kstorage(KSTORAGE_SU_LIST_GROUP, uid, &profile, 0, sizeof(struct su_profile), false); + logkfd("uid: %d, to_uid: %d, sctx: %s, rc: %d\n", uid, to_uid, scontext, rc); + return rc; } KP_EXPORT_SYMBOL(su_add_allow_uid); -int su_remove_allow_uid(uid_t uid, int async) +int su_remove_allow_uid(uid_t uid) { - struct allow_uid *pos; - spin_lock(&list_lock); - list_for_each_entry(pos, &allow_uid_list, list) - { - if (pos->uid == uid) { - list_del_rcu(&pos->list); - spin_unlock(&list_lock); - logkfi("uid: %d, to_uid: %d, sctx: %s\n", pos->uid, pos->profile.to_uid, pos->profile.scontext); - if (async) { - call_rcu(&pos->rcu, allow_reclaim_callback); - } else { - synchronize_rcu(); - kvfree(pos); - } - return 0; - } - } - spin_unlock(&list_lock); - return 0; + return remove_kstorage(KSTORAGE_SU_LIST_GROUP, uid); } KP_EXPORT_SYMBOL(su_remove_allow_uid); int su_allow_uid_nums() { - int num = 0; - rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry(pos, &allow_uid_list, list) + return kstorage_group_size(KSTORAGE_SU_LIST_GROUP); +} +KP_EXPORT_SYMBOL(su_allow_uid_nums); + +static int allow_uids_cb(struct kstorage *kstorage, void *udata) +{ + struct { - num++; + int is_user; + uid_t *out_uids; + int out_num; + } *up = (typeof(up))udata; + + if (up->is_user) { + int cplen = compat_copy_to_user(up->out_uids + num, &uid, sizeof(uid)); + logkfd("uid: %d\n", uid); + if (cplen <= 0) { + logkfd("compat_copy_to_user error: %d", cplen); + rc = cplen; + goto out; + } + } else { + out_uids[num] = uid; } - rcu_read_unlock(); - logkfd("%d\n", num); - return num; + + num++; + + return 0; } -KP_EXPORT_SYMBOL(su_allow_uid_nums); int su_allow_uids(int is_user, uid_t *out_uids, int out_num) { int rc = 0; - int num = 0; - rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry(pos, &allow_uid_list, list) + struct { - if (num >= out_num) goto out; - - uid_t uid = pos->profile.uid; - if (is_user) { - int cplen = compat_copy_to_user(out_uids + num, &uid, sizeof(uid)); - logkfd("uid: %d\n", uid); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; - } - } else { - out_uids[num] = uid; - } - - num++; - } - rc = num; -out: - rcu_read_unlock(); + int iu; + uid_t *up; + int un; + } udata = { is_user, out_uids, out_num }; + on_each_kstorage_elem(KSTORAGE_SU_LIST_GROUP, allow_uids_cb, &udata); return rc; } KP_EXPORT_SYMBOL(su_allow_uids); @@ -257,17 +176,8 @@ const char *su_get_path() } KP_EXPORT_SYMBOL(su_get_path); -// #define TRY_DIRECT_MODIFY_USER - -#define INLINE_HOOK_SYSCALL - -static void handle_before_execve(hook_local_t *hook_local, char **__user u_filename_p, char **__user uargv, void *udata) +static void handle_before_execve(char **__user u_filename_p, char **__user uargv, void *udata) { -#ifdef TRY_DIRECT_MODIFY_USER - // copy to user len - hook_local->data0 = 0; -#endif - char __user *ufilename = *u_filename_p; char filename[SU_PATH_MAX_LEN]; int flen = compat_strncpy_from_user(filename, ufilename, sizeof(filename)); @@ -286,54 +196,28 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen struct file *filp = filp_open(apd_path, O_RDONLY, 0); if (!filp || IS_ERR(filp)) { #endif - int cplen = 0; -#ifdef TRY_DIRECT_MODIFY_USER - cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); - if (cplen > 0) { - hook_local->data0 = cplen; - hook_local->data1 = (uint64_t)u_filename_p; - logkfi("call su uid: %d, to_uid: %d, sctx: %s, cplen: %d\n", uid, to_uid, sctx, cplen); - } -#endif - if (cplen <= 0) { - void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); - if (uptr && !IS_ERR(uptr)) { - *u_filename_p = (char *__user)uptr; - } - logkfi("call su uid: %d, to_uid: %d, sctx: %s, uptr: %llx\n", uid, to_uid, sctx, uptr); + void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); + if (uptr && !IS_ERR(uptr)) { + *u_filename_p = (char *__user)uptr; } - + logkfi("call su uid: %d, to_uid: %d, sctx: %s, uptr: %llx\n", uid, to_uid, sctx, uptr); #ifdef ANDROID } else { filp_close(filp, 0); // command - int cplen = 0; -#ifdef TRY_DIRECT_MODIFY_USER - cplen = compat_copy_to_user(*u_filename_p, apd_path, sizeof(apd_path)); - if (cplen > 0) { - hook_local->data0 = cplen; - hook_local->data1 = (uint64_t)u_filename_p; - } -#endif uint64_t sp = 0; - if (cplen <= 0) { - sp = current_user_stack_pointer(); - sp -= sizeof(apd_path); - sp &= 0xFFFFFFFFFFFFFFF8; - cplen = compat_copy_to_user((void *)sp, apd_path, sizeof(apd_path)); - if (cplen > 0) { - *u_filename_p = (char *)sp; - } + sp = current_user_stack_pointer(); + sp -= sizeof(apd_path); + sp &= 0xFFFFFFFFFFFFFFF8; + int cplen = compat_copy_to_user((void *)sp, apd_path, sizeof(apd_path)); + if (cplen > 0) { + *u_filename_p = (char *)sp; } // argv int argv_cplen = 0; if (strcmp(legacy_su_path, filename)) { -#ifdef TRY_DIRECT_MODIFY_USER - const char __user *p1 = get_user_arg_ptr(0, *uargv, 0); - argv_cplen = compat_copy_to_user((void *__user)p1, legacy_su_path, sizeof(legacy_su_path)); -#endif if (argv_cplen <= 0) { sp = sp ?: current_user_stack_pointer(); sp -= sizeof(legacy_su_path); @@ -357,17 +241,6 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen } } -#ifdef TRY_DIRECT_MODIFY_USER -static void handle_after_execve(hook_local_t *hook_local) -{ - int cplen = hook_local->data0; - char **__user u_filename_p = (char **__user)hook_local->data1; - if (cplen > 0) { - compat_copy_to_user((void *)*u_filename_p, current_su_path, cplen); - } -} -#endif - // https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2107 // COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename, // const compat_uptr_t __user *, argv, @@ -381,17 +254,8 @@ static void before_execve(hook_fargs3_t *args, void *udata) { void *arg0p = syscall_argn_p(args, 0); void *arg1p = syscall_argn_p(args, 1); - handle_before_execve(&args->local, (char **)arg0p, (char **)arg1p, udata); -} - -#ifdef TRY_DIRECT_MODIFY_USER -static void after_execve(hook_fargs3_t *args, void *udata) -{ - handle_after_execve(&args->local); + handle_before_execve((char **)arg0p, (char **)arg1p, udata); } -#else -#define after_execve 0 -#endif // https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2114 // COMPAT_SYSCALL_DEFINE5(execveat, int, fd, @@ -407,18 +271,9 @@ __maybe_unused static void before_execveat(hook_fargs5_t *args, void *udata) { void *arg1p = syscall_argn_p(args, 1); void *arg2p = syscall_argn_p(args, 2); - handle_before_execve(&args->local, (char **)arg1p, (char **)arg2p, udata); + handle_before_execve((char **)arg1p, (char **)arg2p, udata); } -#ifdef TRY_DIRECT_MODIFY_USER -static void after_execveat(hook_fargs5_t *args, void *udata) -{ - handle_after_execve(&args->local); -} -#else -#define after_execveat 0 -#endif - // https://elixir.bootlin.com/linux/v6.1/source/fs/stat.c#L431 // SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename, // struct stat __user *, statbuf, int, flag) @@ -436,9 +291,6 @@ static void after_execveat(hook_fargs5_t *args, void *udata) // struct statx __user *, buffer) static void su_handler_arg1_ufilename_before(hook_fargs6_t *args, void *udata) { - // copy to user len - args->local.data0 = 0; - uid_t uid = current_uid(); if (!is_su_allow_uid(uid)) return; @@ -449,52 +301,24 @@ static void su_handler_arg1_ufilename_before(hook_fargs6_t *args, void *udata) if (flen <= 0) return; if (!strcmp(current_su_path, filename)) { - int cplen = 0; -#ifdef TRY_DIRECT_MODIFY_USER - cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); - if (cplen > 0) { - args->local.data0 = cplen; - args->local.data1 = (uint64_t)*u_filename_p; - logkfi("su uid: %d, cp: %d\n", uid, cplen); + void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); + if (uptr && !IS_ERR(uptr)) { + *u_filename_p = uptr; } else { -#endif - void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); - if (uptr && !IS_ERR(uptr)) { - *u_filename_p = uptr; - } else { - logkfi("su uid: %d, cp stack error: %d\n", uid, uptr); - } -#ifdef TRY_DIRECT_MODIFY_USER + logkfi("su uid: %d, cp stack error: %d\n", uid, uptr); } -#endif } } -#ifdef TRY_DIRECT_MODIFY_USER -static void su_handler_arg1_ufilename_after(hook_fargs6_t *args, void *udata) -{ - int cplen = args->local.data0; - if (cplen > 0) { - compat_copy_to_user((void *)args->local.data1, current_su_path, cplen); - } -} -#else -#define su_handler_arg1_ufilename_after 0 -#endif - int su_compat_init() { current_su_path = default_su_path; - INIT_LIST_HEAD(&allow_uid_list); - spin_lock_init(&list_lock); - #ifdef ANDROID // default shell if (!all_allow_sctx[0]) strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK); - struct su_profile_ext ext = { .exclude = 0 }; - su_add_allow_uid(2000, 0, all_allow_sctx, &ext, 1); - su_add_allow_uid(0, 0, all_allow_sctx, &ext, 1); + su_add_allow_uid(2000, 0, all_allow_sctx, 1); + su_add_allow_uid(0, 0, all_allow_sctx, 1); #endif hook_err_t rc = HOOK_NO_ERR; @@ -504,56 +328,28 @@ int su_compat_init() bool wrap = su_config & PATCH_CONFIG_SU_HOOK_NO_WRAP; log_boot("su config, enable: %d, wrap: %d\n"); - rc = hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)0); - log_boot("hook __NR_execve rc: %d\n", rc); + if (!enable) return; - // rc = hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)0); - // log_boot("hook __NR_execveat rc: %d\n", rc); + rc = hook_syscalln(__NR_execve, 3, before_execve, 0, (void *)0); + log_boot("hook __NR_execve rc: %d\n", rc); - rc = hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)0); + rc = hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, 0, (void *)0); log_boot("hook __NR3264_fstatat rc: %d\n", rc); - // rc = hook_syscalln(__NR_statx, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - // log_boot("hook __NR_statx rc: %d\n", rc); - - rc = hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + rc = hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, 0, (void *)0); log_boot("hook __NR_faccessat rc: %d\n", rc); - // rc = - // hook_syscalln(__NR_faccessat2, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - // log_boot("hook __NR_faccessat2 rc: %d\n", rc); - - // #include - // __NR_execve 11 - rc = hook_compat_syscalln(11, 3, before_execve, after_execve, (void *)1); + rc = hook_compat_syscalln(11, 3, before_execve, 0, (void *)1); log_boot("hook 32 __NR_execve rc: %d\n", rc); - // __NR_execveat 387 - // rc = hook_compat_syscalln(387, 5, before_execveat, after_execveat, (void *)1); - // log_boot("hook 32 __NR_execveat rc: %d\n", rc); - - // __NR_statx 397 - // rc = hook_compat_syscalln(397, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - // log_boot("hook 32 __NR_statx rc: %d\n", rc); - - // #define __NR_stat 106 - // #define __NR_lstat 107 - // #define __NR_stat64 195 - // #define __NR_lstat64 196 - // __NR_fstatat64 327 - rc = hook_compat_syscalln(327, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + rc = hook_compat_syscalln(327, 4, su_handler_arg1_ufilename_before, 0, (void *)0); log_boot("hook 32 __NR_fstatat64 rc: %d\n", rc); // __NR_faccessat 334 - rc = hook_compat_syscalln(334, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + rc = hook_compat_syscalln(334, 3, su_handler_arg1_ufilename_before, 0, (void *)0); log_boot("hook 32 __NR_faccessat rc: %d\n", rc); - // __NR_faccessat2 439 - // rc = hook_compat_syscalln(439, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - // log_boot("hook 32 __NR_faccessat2 rc: %d\n", rc); - return 0; } \ No newline at end of file diff --git a/kernel/patch/common/sucompat.c.bak b/kernel/patch/common/sucompat.c.bak new file mode 100644 index 00000000..be3ab2e4 --- /dev/null +++ b/kernel/patch/common/sucompat.c.bak @@ -0,0 +1,554 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2023 bmax121. All Rights Reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +const char sh_path[] = SH_PATH; +const char default_su_path[] = SU_PATH; + +#ifdef ANDROID +const char legacy_su_path[] = LEGACY_SU_PATH; +const char apd_path[] = APD_PATH; +#endif + +static const char *current_su_path = 0; + +static struct list_head allow_uid_list; +static spinlock_t list_lock; + +static void allow_reclaim_callback(struct rcu_head *rcu) +{ + struct allow_uid *allow = container_of(rcu, struct allow_uid, rcu); + kvfree(allow); +} + +struct su_profile profile_su_allow_uid(uid_t uid) +{ + rcu_read_lock(); + struct allow_uid *pos; + struct su_profile profile = { 0 }; + list_for_each_entry_rcu(pos, &allow_uid_list, list) + { + if (pos->uid == uid) { + memcpy(&profile, &pos->profile, sizeof(struct su_profile)); + rcu_read_unlock(); + return profile; + } + } + rcu_read_unlock(); + return profile; +} +KP_EXPORT_SYMBOL(profile_su_allow_uid); + +int is_su_allow_uid(uid_t uid) +{ + rcu_read_lock(); + struct allow_uid *pos; + list_for_each_entry_rcu(pos, &allow_uid_list, list) + { + if (pos->uid == uid) { + rcu_read_unlock(); + return 1; + } + } + rcu_read_unlock(); + return 0; +} +KP_EXPORT_SYMBOL(is_su_allow_uid); + +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, int async) +{ + if (!scontext) scontext = ""; + + rcu_read_lock(); + struct allow_uid *pos, *old = 0; + list_for_each_entry(pos, &allow_uid_list, list) + { + if (pos->uid == uid) { + old = pos; + break; + } + } + // todo: vmalloc -> kmalloc, gfp + struct allow_uid *new = (struct allow_uid *)vmalloc(sizeof(struct allow_uid)); + new->uid = uid; + new->profile.uid = uid; + new->profile.to_uid = to_uid; + strncpy(new->profile.scontext, scontext, sizeof(new->profile.scontext)); + new->profile.scontext[sizeof(new->profile.scontext) - 1] = '\0'; + + spin_lock(&list_lock); + if (old) { // update + list_replace_rcu(&old->list, &new->list); + logkfi("update uid: %d, to_uid: %d, sctx: %s\n", uid, new->profile.to_uid, new->profile.scontext); + } else { // add new one + list_add_rcu(&new->list, &allow_uid_list); + logkfi("new uid: %d, to_uid: %d, sctx: %s\n", uid, new->profile.to_uid, new->profile.scontext); + } + spin_unlock(&list_lock); + + rcu_read_unlock(); + if (old) { + if (async) { + call_rcu(&old->rcu, allow_reclaim_callback); + } else { + synchronize_rcu(); + kvfree(old); + } + } + return 0; +} +KP_EXPORT_SYMBOL(su_add_allow_uid); + +int su_remove_allow_uid(uid_t uid, int async) +{ + struct allow_uid *pos; + spin_lock(&list_lock); + list_for_each_entry(pos, &allow_uid_list, list) + { + if (pos->uid == uid) { + list_del_rcu(&pos->list); + spin_unlock(&list_lock); + logkfi("uid: %d, to_uid: %d, sctx: %s\n", pos->uid, pos->profile.to_uid, pos->profile.scontext); + if (async) { + call_rcu(&pos->rcu, allow_reclaim_callback); + } else { + synchronize_rcu(); + kvfree(pos); + } + return 0; + } + } + spin_unlock(&list_lock); + return 0; +} +KP_EXPORT_SYMBOL(su_remove_allow_uid); + +int su_allow_uid_nums() +{ + int num = 0; + rcu_read_lock(); + struct allow_uid *pos; + list_for_each_entry(pos, &allow_uid_list, list) + { + num++; + } + rcu_read_unlock(); + logkfd("%d\n", num); + return num; +} +KP_EXPORT_SYMBOL(su_allow_uid_nums); + +int su_allow_uids(int is_user, uid_t *out_uids, int out_num) +{ + int rc = 0; + int num = 0; + rcu_read_lock(); + struct allow_uid *pos; + list_for_each_entry(pos, &allow_uid_list, list) + { + if (num >= out_num) goto out; + + uid_t uid = pos->profile.uid; + if (is_user) { + int cplen = compat_copy_to_user(out_uids + num, &uid, sizeof(uid)); + logkfd("uid: %d\n", uid); + if (cplen <= 0) { + logkfd("compat_copy_to_user error: %d", cplen); + rc = cplen; + goto out; + } + } else { + out_uids[num] = uid; + } + + num++; + } + rc = num; +out: + rcu_read_unlock(); + return rc; +} +KP_EXPORT_SYMBOL(su_allow_uids); + +int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile) +{ + int rc = -ENOENT; + rcu_read_lock(); + struct allow_uid *pos; + list_for_each_entry(pos, &allow_uid_list, list) + { + if (pos->profile.uid != uid) continue; + if (is_user) { + int cplen = compat_copy_to_user(profile, &pos->profile, sizeof(struct su_profile)); + logkfd("profile: %d %d %s\n", uid, pos->profile.to_uid, pos->profile.scontext); + if (cplen <= 0) { + logkfd("compat_copy_to_user error: %d", cplen); + rc = cplen; + goto out; + } + } else { + memcpy(profile, &pos->profile, sizeof(struct su_profile)); + } + rc = 0; + goto out; + } +out: + rcu_read_unlock(); + return rc; +} +KP_EXPORT_SYMBOL(su_allow_uid_profile); + +// no free, no lock +int su_reset_path(const char *path) +{ + if (!path) return -EINVAL; + if (IS_ERR(path)) return PTR_ERR(path); + current_su_path = path; + logkfd("%s\n", current_su_path); + dsb(ish); + return 0; +} +KP_EXPORT_SYMBOL(su_reset_path); + +const char *su_get_path() +{ + if (!current_su_path) current_su_path = default_su_path; + return current_su_path; +} +KP_EXPORT_SYMBOL(su_get_path); + +// #define TRY_DIRECT_MODIFY_USER + +#define INLINE_HOOK_SYSCALL + +static void handle_before_execve(hook_local_t *hook_local, char **__user u_filename_p, char **__user uargv, void *udata) +{ +#ifdef TRY_DIRECT_MODIFY_USER + // copy to user len + hook_local->data0 = 0; +#endif + + char __user *ufilename = *u_filename_p; + char filename[SU_PATH_MAX_LEN]; + int flen = compat_strncpy_from_user(filename, ufilename, sizeof(filename)); + if (flen <= 0) return; + + if (!strcmp(current_su_path, filename)) { + uid_t uid = current_uid(); + if (!is_su_allow_uid(uid)) return; + struct su_profile profile = profile_su_allow_uid(uid); + + uid_t to_uid = profile.to_uid; + const char *sctx = profile.scontext; + commit_su(to_uid, sctx); + +#ifdef ANDROID + struct file *filp = filp_open(apd_path, O_RDONLY, 0); + if (!filp || IS_ERR(filp)) { +#endif + int cplen = 0; +#ifdef TRY_DIRECT_MODIFY_USER + cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); + if (cplen > 0) { + hook_local->data0 = cplen; + hook_local->data1 = (uint64_t)u_filename_p; + logkfi("call su uid: %d, to_uid: %d, sctx: %s, cplen: %d\n", uid, to_uid, sctx, cplen); + } +#endif + if (cplen <= 0) { + void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); + if (uptr && !IS_ERR(uptr)) { + *u_filename_p = (char *__user)uptr; + } + logkfi("call su uid: %d, to_uid: %d, sctx: %s, uptr: %llx\n", uid, to_uid, sctx, uptr); + } + +#ifdef ANDROID + } else { + filp_close(filp, 0); + + // command + int cplen = 0; +#ifdef TRY_DIRECT_MODIFY_USER + cplen = compat_copy_to_user(*u_filename_p, apd_path, sizeof(apd_path)); + if (cplen > 0) { + hook_local->data0 = cplen; + hook_local->data1 = (uint64_t)u_filename_p; + } +#endif + uint64_t sp = 0; + if (cplen <= 0) { + sp = current_user_stack_pointer(); + sp -= sizeof(apd_path); + sp &= 0xFFFFFFFFFFFFFFF8; + cplen = compat_copy_to_user((void *)sp, apd_path, sizeof(apd_path)); + if (cplen > 0) { + *u_filename_p = (char *)sp; + } + } + + // argv + int argv_cplen = 0; + if (strcmp(legacy_su_path, filename)) { +#ifdef TRY_DIRECT_MODIFY_USER + const char __user *p1 = get_user_arg_ptr(0, *uargv, 0); + argv_cplen = compat_copy_to_user((void *__user)p1, legacy_su_path, sizeof(legacy_su_path)); +#endif + if (argv_cplen <= 0) { + sp = sp ?: current_user_stack_pointer(); + sp -= sizeof(legacy_su_path); + sp &= 0xFFFFFFFFFFFFFFF8; + argv_cplen = compat_copy_to_user((void *)sp, legacy_su_path, sizeof(legacy_su_path)); + if (argv_cplen > 0) { + int rc = set_user_arg_ptr(0, *uargv, 0, sp); + if (rc < 0) { // todo: modify entire argv + logkfi("call apd argv error, uid: %d, to_uid: %d, sctx: %s, rc: %d\n", uid, to_uid, sctx, + rc); + } + } + } + } + logkfi("call apd uid: %d, to_uid: %d, sctx: %s, cplen: %d, %d\n", uid, to_uid, sctx, cplen, argv_cplen); + } +#endif // ANDROID + } else if (!strcmp(SUPERCMD, filename)) { + handle_supercmd(u_filename_p, uargv); + return; + } +} + +#ifdef TRY_DIRECT_MODIFY_USER +static void handle_after_execve(hook_local_t *hook_local) +{ + int cplen = hook_local->data0; + char **__user u_filename_p = (char **__user)hook_local->data1; + if (cplen > 0) { + compat_copy_to_user((void *)*u_filename_p, current_su_path, cplen); + } +} +#endif + +// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2107 +// COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename, +// const compat_uptr_t __user *, argv, +// const compat_uptr_t __user *, envp) + +// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2087 +// SYSCALL_DEFINE3(execve, const char __user *, filename, const char __user *const __user *, argv, +// const char __user *const __user *, envp) + +static void before_execve(hook_fargs3_t *args, void *udata) +{ + void *arg0p = syscall_argn_p(args, 0); + void *arg1p = syscall_argn_p(args, 1); + handle_before_execve(&args->local, (char **)arg0p, (char **)arg1p, udata); +} + +#ifdef TRY_DIRECT_MODIFY_USER +static void after_execve(hook_fargs3_t *args, void *udata) +{ + handle_after_execve(&args->local); +} +#else +#define after_execve 0 +#endif + +// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2114 +// COMPAT_SYSCALL_DEFINE5(execveat, int, fd, +// const char __user *, filename, +// const compat_uptr_t __user *, argv, +// const compat_uptr_t __user *, envp, +// int, flags) + +// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2095 +// SYSCALL_DEFINE5(execveat, int, fd, const char __user *, filename, const char __user *const __user *, argv, +// const char __user *const __user *, envp, int, flags) +__maybe_unused static void before_execveat(hook_fargs5_t *args, void *udata) +{ + void *arg1p = syscall_argn_p(args, 1); + void *arg2p = syscall_argn_p(args, 2); + handle_before_execve(&args->local, (char **)arg1p, (char **)arg2p, udata); +} + +#ifdef TRY_DIRECT_MODIFY_USER +static void after_execveat(hook_fargs5_t *args, void *udata) +{ + handle_after_execve(&args->local); +} +#else +#define after_execveat 0 +#endif + +// https://elixir.bootlin.com/linux/v6.1/source/fs/stat.c#L431 +// SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename, +// struct stat __user *, statbuf, int, flag) + +// https://elixir.bootlin.com/linux/v6.1/source/fs/open.c#L492 +// SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) + +// https://elixir.bootlin.com/linux/v6.1/source/fs/open.c#L497 +// SYSCALL_DEFINE4(faccessat2, int, dfd, const char __user *, filename, int, mode, int, flags) + +// https://elixir.bootlin.com/linux/v6.1/source/fs/stat.c#L661 +// SYSCALL_DEFINE5(statx, +// int, dfd, const char __user *, filename, unsigned, flags, +// unsigned int, mask, +// struct statx __user *, buffer) +static void su_handler_arg1_ufilename_before(hook_fargs6_t *args, void *udata) +{ + // copy to user len + args->local.data0 = 0; + + uid_t uid = current_uid(); + if (!is_su_allow_uid(uid)) return; + + char __user **u_filename_p = (char __user **)syscall_argn_p(args, 1); + + char filename[SU_PATH_MAX_LEN]; + int flen = compat_strncpy_from_user(filename, *u_filename_p, sizeof(filename)); + if (flen <= 0) return; + + if (!strcmp(current_su_path, filename)) { +#ifdef TRY_DIRECT_MODIFY_USER + int cplen = 0; + cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); + if (cplen > 0) { + args->local.data0 = cplen; + args->local.data1 = (uint64_t)*u_filename_p; + logkfi("su uid: %d, cp: %d\n", uid, cplen); + } else { +#endif + void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); + if (uptr && !IS_ERR(uptr)) { + *u_filename_p = uptr; + } else { + logkfi("su uid: %d, cp stack error: %d\n", uid, uptr); + } +#ifdef TRY_DIRECT_MODIFY_USER + } +#endif + } +} + +#ifdef TRY_DIRECT_MODIFY_USER +static void su_handler_arg1_ufilename_after(hook_fargs6_t *args, void *udata) +{ + int cplen = args->local.data0; + if (cplen > 0) { + compat_copy_to_user((void *)args->local.data1, current_su_path, cplen); + } +} +#else +#define su_handler_arg1_ufilename_after 0 +#endif + +int su_compat_init() +{ + current_su_path = default_su_path; + + INIT_LIST_HEAD(&allow_uid_list); + spin_lock_init(&list_lock); + +#ifdef ANDROID + // default shell + if (!all_allow_sctx[0]) strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK); + su_add_allow_uid(2000, 0, all_allow_sctx, 1); + su_add_allow_uid(0, 0, all_allow_sctx, 1); +#endif + + hook_err_t rc = HOOK_NO_ERR; + + uint8_t su_config = patch_config->patch_su_config; + bool enable = su_config & PATCH_CONFIG_SU_ENABLE; + bool wrap = su_config & PATCH_CONFIG_SU_HOOK_NO_WRAP; + log_boot("su config, enable: %d, wrap: %d\n"); + + rc = hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)0); + log_boot("hook __NR_execve rc: %d\n", rc); + + // rc = hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)0); + // log_boot("hook __NR_execveat rc: %d\n", rc); + + rc = hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, + (void *)0); + log_boot("hook __NR3264_fstatat rc: %d\n", rc); + + // rc = hook_syscalln(__NR_statx, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + // log_boot("hook __NR_statx rc: %d\n", rc); + + rc = hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + log_boot("hook __NR_faccessat rc: %d\n", rc); + + // rc = + // hook_syscalln(__NR_faccessat2, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + // log_boot("hook __NR_faccessat2 rc: %d\n", rc); + + // #include + + // __NR_execve 11 + rc = hook_compat_syscalln(11, 3, before_execve, after_execve, (void *)1); + log_boot("hook 32 __NR_execve rc: %d\n", rc); + + // __NR_execveat 387 + // rc = hook_compat_syscalln(387, 5, before_execveat, after_execveat, (void *)1); + // log_boot("hook 32 __NR_execveat rc: %d\n", rc); + + // __NR_statx 397 + // rc = hook_compat_syscalln(397, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + // log_boot("hook 32 __NR_statx rc: %d\n", rc); + + // #define __NR_stat 106 + // #define __NR_lstat 107 + // #define __NR_stat64 195 + // #define __NR_lstat64 196 + + // __NR_fstatat64 327 + rc = hook_compat_syscalln(327, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + log_boot("hook 32 __NR_fstatat64 rc: %d\n", rc); + + // __NR_faccessat 334 + rc = hook_compat_syscalln(334, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + log_boot("hook 32 __NR_faccessat rc: %d\n", rc); + + // __NR_faccessat2 439 + // rc = hook_compat_syscalln(439, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); + // log_boot("hook 32 __NR_faccessat2 rc: %d\n", rc); + + return 0; +} \ No newline at end of file diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 05311e8f..f8bf6fb7 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -38,19 +38,6 @@ static long call_test(long arg1, long arg2, long arg3) { - // char *cmd = "/system/bin/touch"; - // // const char *superkey = get_superkey(); - // char *argv[] = { - // cmd, - // "/data/local/tmp/test.txt", - // NULL, - // }; - // char *envp[] = { - // "PATH=/system/bin:/data/adb", - // NULL, - // }; - // int rc = call_usermodehelper(cmd, argv, envp, UMH_WAIT_PROC); - // log_boot("user_init: %d\n", rc); return 0; } @@ -179,7 +166,7 @@ static long call_grant_uid(struct su_profile *__user uprofile) { struct su_profile *profile = memdup_user(uprofile, sizeof(struct su_profile)); if (!profile || IS_ERR(profile)) return PTR_ERR(profile); - int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext, &profile->ext, 1); + int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext, 1); kvfree(profile); return rc; } @@ -328,7 +315,6 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3 } switch (cmd) { - case SUPERCALL_MEM_PHYS: default: break; } diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index d63f92dd..afcc24e2 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -75,14 +75,14 @@ static const char supercmd_help[] = " whose full PATH is '/system/bin/kp'. This can avoid conflicts with the existing 'su' command.\n" " If you wish to modify this PATH, you can use the 'reset' command.\n" " SubCommand:\n" - " grant [TO_UID [SCONTEXT [EXCLUDE]]] Grant su permission to UID. EXCLUDE is 'true' or 'false'.\n" - " revoke Revoke su permission to UID.\n" - " num Get the number of uids with the aforementioned permissions.\n" - " list List all su allowed uids.\n" - " profile Get the profile of the uid configuration.\n" - " path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n" - " sctx [SCONTEXT] Get or Reset current all allowed security context, \n" - " event Report EVENT.\n" + " grant [TO_UID [SCONTEXT]] Grant su permission to UID.\n" + " revoke Revoke su permission to UID.\n" + " num Get the number of uids with the aforementioned permissions.\n" + " list List all su allowed uids.\n" + " profile Get the profile of the uid configuration.\n" + " path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n" + " sctx [SCONTEXT] Get or Reset current all allowed security context, \n" + " event Report EVENT.\n" "\n" "The command below requires superkey authentication.\n" " module [...]: KernelPatch Module manager\n" @@ -122,9 +122,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } if (carr[3]) kstrtoull(carr[3], 10, &to_uid); if (carr[4]) scontext = carr[4]; - struct su_profile_ext ext = { .exclude = false }; - if (carr[5] && !strcmp(carr[5], "true")) ext.exclude = true; - su_add_allow_uid(uid, to_uid, scontext, &ext, 1); + su_add_allow_uid(uid, to_uid, scontext, 1); sprintf(buffer, "grant %d, %d, %s", uid, to_uid, scontext); cmd_res->msg = buffer; } else if (!strcmp(sub_cmd, "revoke")) { @@ -163,8 +161,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char cmd_res->rc = su_allow_uid_profile(0, uid, &profile); if (cmd_res->rc) return; - sprintf(buffer, "uid: %d, to_uid: %d, scontext: %s, exclude: %d", profile.uid, profile.to_uid, profile.scontext, - profile.ext.exclude); + sprintf(buffer, "uid: %d, to_uid: %d, scontext: %s", profile.uid, profile.to_uid, profile.scontext); cmd_res->msg = buffer; } else if (!strcmp(sub_cmd, "path")) { diff --git a/kernel/patch/common/syscall.c b/kernel/patch/common/syscall.c index 17c64d6e..6a7c3909 100644 --- a/kernel/patch/common/syscall.c +++ b/kernel/patch/common/syscall.c @@ -265,7 +265,7 @@ long raw_syscall6(long nr, long arg0, long arg1, long arg2, long arg3, long arg4 } KP_EXPORT_SYMBOL(raw_syscall6); -hook_err_t __fp_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) +hook_err_t fp_wrap_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) { if (!is_compat) { if (!sys_call_table) return HOOK_BAD_ADDRESS; @@ -279,9 +279,9 @@ hook_err_t __fp_hook_syscalln(int nr, int narg, int is_compat, void *before, voi return fp_hook_wrap(fp_addr, narg, before, after, udata); } } -KP_EXPORT_SYMBOL(__fp_hook_syscalln); +KP_EXPORT_SYMBOL(fp_wrap_syscalln); -void __fp_unhook_syscalln(int nr, int is_compat, void *before, void *after) +void fp_unwrap_syscalln(int nr, int is_compat, void *before, void *after) { if (!is_compat) { if (!sys_call_table) return; @@ -293,7 +293,7 @@ void __fp_unhook_syscalln(int nr, int is_compat, void *before, void *after) fp_hook_unwrap(fp_addr, before, after); } } -KP_EXPORT_SYMBOL(__fp_unhook_syscalln); +KP_EXPORT_SYMBOL(fp_unwrap_syscalln); /* sys_xxx.cfi_jt @@ -301,47 +301,47 @@ sys_xxx.cfi_jt hint #0x22 # bti c b #0xfffffffffeb452f4 */ -hook_err_t __inline_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) +hook_err_t inline_wrap_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata) { uintptr_t addr = syscalln_name_addr(nr, is_compat); if (!addr) return -HOOK_BAD_ADDRESS; if (has_syscall_wrapper) narg = 1; return hook_wrap((void *)addr, narg, before, after, udata); } -KP_EXPORT_SYMBOL(__inline_hook_syscalln); +KP_EXPORT_SYMBOL(inline_wrap_syscalln); -void __inline_unhook_syscalln(int nr, int is_compat, void *before, void *after) +void inline_unwrap_syscalln(int nr, int is_compat, void *before, void *after) { uintptr_t addr = syscalln_name_addr(nr, is_compat); hook_unwrap((void *)addr, before, after); } -KP_EXPORT_SYMBOL(__inline_unhook_syscalln); +KP_EXPORT_SYMBOL(inline_unwrap_syscalln); hook_err_t hook_syscalln(int nr, int narg, void *before, void *after, void *udata) { - if (sys_call_table) return __fp_hook_syscalln(nr, narg, 0, before, after, udata); - return __inline_hook_syscalln(nr, narg, 0, before, after, udata); + if (sys_call_table) return fp_wrap_syscalln(nr, narg, 0, before, after, udata); + return inline_wrap_syscalln(nr, narg, 0, before, after, udata); } KP_EXPORT_SYMBOL(hook_syscalln); void unhook_syscalln(int nr, void *before, void *after) { - if (sys_call_table) return __fp_unhook_syscalln(nr, 0, before, after); - return __inline_unhook_syscalln(nr, 0, before, after); + if (sys_call_table) return fp_unwrap_syscalln(nr, 0, before, after); + return inline_unwrap_syscalln(nr, 0, before, after); } KP_EXPORT_SYMBOL(unhook_syscalln); hook_err_t hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) { - if (compat_sys_call_table) return __fp_hook_syscalln(nr, narg, 1, before, after, udata); - return __inline_hook_syscalln(nr, narg, 1, before, after, udata); + if (compat_sys_call_table) return fp_wrap_syscalln(nr, narg, 1, before, after, udata); + return inline_wrap_syscalln(nr, narg, 1, before, after, udata); } KP_EXPORT_SYMBOL(hook_compat_syscalln); void unhook_compat_syscalln(int nr, void *before, void *after) { - if (compat_sys_call_table) return __fp_unhook_syscalln(nr, 1, before, after); - return __inline_unhook_syscalln(nr, 1, before, after); + if (compat_sys_call_table) return fp_unwrap_syscalln(nr, 1, before, after); + return inline_unwrap_syscalln(nr, 1, before, after); } KP_EXPORT_SYMBOL(unhook_compat_syscalln); diff --git a/kernel/patch/include/accctl.h b/kernel/patch/include/accctl.h index ebc87b57..dd1f54ca 100644 --- a/kernel/patch/include/accctl.h +++ b/kernel/patch/include/accctl.h @@ -24,8 +24,8 @@ int commit_common_su(uid_t to_uid, const char *sctx); int commit_su(uid_t uid, const char *sctx); int task_su(pid_t pid, uid_t to_uid, const char *sctx); -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, struct su_profile_ext *ext, int async); -int su_remove_allow_uid(uid_t uid, int async); +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext); +int su_remove_allow_uid(uid_t uid); int su_allow_uid_nums(); int su_allow_uids(int is_user, uid_t *out_uids, int out_num); int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile); diff --git a/kernel/patch/include/kstorage.h b/kernel/patch/include/kstorage.h new file mode 100644 index 00000000..13159d2e --- /dev/null +++ b/kernel/patch/include/kstorage.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024 bmax121. All Rights Reserved. + */ + +#ifndef _KP_KSTORAGE_H_ +#define _KP_KSTORAGE_H_ + +#include +#include +#include + +struct kstorage +{ + struct list_head list; + struct rcu_head rcu; + + int gid; + long did; + int dlen; + char data[0]; +}; + +int try_alloc_kstroage_group(); + +int kstorage_group_size(int gid); + +int write_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user); + +// must surround with rcu read lock +const struct kstorage *get_kstorage(int gid, long did); + +typedef int (*on_kstorage_cb)(struct kstroage *kstorage, void *udata); +int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata); + +const struct kstorage *get_kstorage(int gid, long did); + +int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user); + +int remove_kstorage(int gid, long did); + +#endif \ No newline at end of file diff --git a/kernel/patch/include/syscall.h b/kernel/patch/include/syscall.h index d1d1d02d..a20bfc7f 100644 --- a/kernel/patch/include/syscall.h +++ b/kernel/patch/include/syscall.h @@ -81,7 +81,7 @@ static inline void *syscall_argn_p(void *fdata_args, int n) * @param udata * @return hook_err_t */ -hook_err_t __fp_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata); +hook_err_t fp_wrap_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata); /** * @brief @@ -91,26 +91,26 @@ hook_err_t __fp_hook_syscalln(int nr, int narg, int is_compat, void *before, voi * @param before * @param after */ -void __fp_unhook_syscalln(int nr, int is_compat, void *before, void *after); +void fp_unwrap_syscalln(int nr, int is_compat, void *before, void *after); static inline hook_err_t fp_hook_syscalln(int nr, int narg, void *before, void *after, void *udata) { - return __fp_hook_syscalln(nr, narg, 0, before, after, udata); + return fp_wrap_syscalln(nr, narg, 0, before, after, udata); } static inline void fp_unhook_syscalln(int nr, void *before, void *after) { - return __fp_unhook_syscalln(nr, 0, before, after); + return fp_unwrap_syscalln(nr, 0, before, after); } static inline hook_err_t fp_hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) { - return __fp_hook_syscalln(nr, narg, 1, before, after, udata); + return fp_wrap_syscalln(nr, narg, 1, before, after, udata); } static inline void fp_unhook_compat_syscalln(int nr, void *before, void *after) { - return __fp_unhook_syscalln(nr, 1, before, after); + return fp_unwrap_syscalln(nr, 1, before, after); } /** @@ -124,7 +124,7 @@ static inline void fp_unhook_compat_syscalln(int nr, void *before, void *after) * @param udata * @return hook_err_t */ -hook_err_t __inline_hook_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata); +hook_err_t inline_wrap_syscalln(int nr, int narg, int is_compat, void *before, void *after, void *udata); /** * @brief @@ -134,26 +134,26 @@ hook_err_t __inline_hook_syscalln(int nr, int narg, int is_compat, void *before, * @param before * @param after */ -void __inline_unhook_syscalln(int nr, int is_compat, void *before, void *after); +void inline_unwrap_syscalln(int nr, int is_compat, void *before, void *after); static inline hook_err_t inline_hook_syscalln(int nr, int narg, void *before, void *after, void *udata) { - return __inline_hook_syscalln(nr, narg, 0, before, after, udata); + return inline_wrap_syscalln(nr, narg, 0, before, after, udata); } static inline void inline_unhook_syscalln(int nr, void *before, void *after) { - __inline_unhook_syscalln(nr, 0, before, after); + inline_unwrap_syscalln(nr, 0, before, after); } static inline hook_err_t inline_hook_compat_syscalln(int nr, int narg, void *before, void *after, void *udata) { - return __inline_hook_syscalln(nr, narg, 1, before, after, udata); + return inline_wrap_syscalln(nr, narg, 1, before, after, udata); } static inline void inline_unhook_compat_syscalln(int nr, void *before, void *after) { - __inline_unhook_syscalln(nr, 0, before, after); + inline_unwrap_syscalln(nr, 0, before, after); } // diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 42234bb8..ff273b65 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -41,12 +41,22 @@ static inline long hash_key(const char *key) #define SUPERCALL_KPM_LIST 0x1031 #define SUPERCALL_KPM_INFO 0x1032 -#define SUPERCALL_MEM_PHYS 0x1041 -#define SUPERCALL_MEM_KERNEL_PHYS 0x1042 -#define SUPERCALL_MEM_MAP_KERNEL 0x1048 -#define SUPERCALL_MEM_MAP_USER 0x1049 -#define SUPERCALL_MEM_PROT 0x1049 -#define SUPERCALL_MEM_CACHE_FLUSH 0x1049 +struct kernel_storage +{ + void *data; + int len; +}; + +#define SUPERCALL_KSTORAGE_ALLOC_GROUP 0x1040 +#define SUPERCALL_KSTORAGE_SET 0x1041 +#define SUPERCALL_KSTORAGE_GET 0x1042 +#define SUPERCALL_KSTORAGE_REMOVE 0x1043 +#define SUPERCALL_KSTORAGE_REMOVE_GROUP 0x1044 + +#define KSTORAGE_SU_LIST_GROUP 0 +#define KSTORAGE_EXCLUDE_LIST_GROUP 1 +#define KSTORAGE_UNUSED_GROUP_2 2 +#define KSTORAGE_UNUSED_GROUP_3 3 #define SUPERCALL_BOOTLOG 0x10fd #define SUPERCALL_PANIC 0x10fe @@ -55,23 +65,6 @@ static inline long hash_key(const char *key) #define SUPERCALL_KEY_MAX_LEN 0x40 #define SUPERCALL_SCONTEXT_LEN 0x60 -struct su_profile_ext -{ - union - { - bool exclude; - }; - char _[32]; -}; - -struct su_profile -{ - uid_t uid; - uid_t to_uid; - char scontext[SUPERCALL_SCONTEXT_LEN]; - struct su_profile_ext ext; -}; - #ifdef ANDROID #define SH_PATH "/system/bin/sh" #define SU_PATH "/system/bin/kp" diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 9f30d866..44260e80 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -50,6 +50,7 @@ void linux_misc_symbol_init(); void linux_libs_symbol_init(); void module_init(); void syscall_init(); +int kstorage_init(); #ifdef ANDROID int android_user_init(); @@ -76,6 +77,9 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) rc = supercall_install(); log_boot("supercall_install done: %d\n", rc); + rc = kstorage_init(); + log_boot("kstorage_init done: %d\n", rc); + rc = su_compat_init(); log_boot("su_compat_init done: %d\n", rc); From f4a1aabf0599e2d4648ba54a7fd3c2977326f337 Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 30 Sep 2024 11:01:34 +0800 Subject: [PATCH 47/71] refactor: su command --- kernel/patch/common/kstorage.c | 7 +-- kernel/patch/common/sucompat.c | 83 +++++++++++++++--------------- kernel/patch/common/supercall.c | 4 +- kernel/patch/common/supercmd.c | 9 ++-- kernel/patch/include/accctl.h | 8 --- kernel/patch/include/kstorage.h | 4 +- kernel/patch/include/sucompat.h | 8 ++- kernel/patch/include/uapi/scdefs.h | 7 +++ 8 files changed, 68 insertions(+), 62 deletions(-) diff --git a/kernel/patch/common/kstorage.c b/kernel/patch/common/kstorage.c index 6fe80107..bf50d39d 100644 --- a/kernel/patch/common/kstorage.c +++ b/kernel/patch/common/kstorage.c @@ -1,10 +1,10 @@ #include + #include #include #include #include #include -#include #include #include #include @@ -127,7 +127,7 @@ KP_EXPORT_SYMBOL(get_kstorage); int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata) { - if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return; + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return 0; int rc = 0; @@ -153,7 +153,8 @@ int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_ int rc = 0; rcu_read_lock(); - struct kstorage *pos = get_kstorage(gid, did); + const struct kstorage *pos = get_kstorage(gid, did); + if (IS_ERR(pos)) return PTR_ERR(pos); int min_len = pos->dlen - offset > len ? len : pos->dlen - offset; diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 54e27de1..6a017d34 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -49,13 +49,6 @@ const char apd_path[] = APD_PATH; static const char *current_su_path = 0; -struct su_profile -{ - uid_t uid; - uid_t to_uid; - char scontext[SUPERCALL_SCONTEXT_LEN]; -}; - int is_su_allow_uid(uid_t uid) { rcu_read_lock(); @@ -70,7 +63,11 @@ KP_EXPORT_SYMBOL(is_su_allow_uid); int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext) { if (!scontext) scontext = ""; - struct su_profile profile = { uid, to_uid, scontext }; + struct su_profile profile = { + uid, + to_uid, + }; + memcpy(profile.scontext, scontext, SUPERCALL_SCONTEXT_LEN); int rc = write_kstorage(KSTORAGE_SU_LIST_GROUP, uid, &profile, 0, sizeof(struct su_profile), false); logkfd("uid: %d, to_uid: %d, sctx: %s, rc: %d\n", uid, to_uid, scontext, rc); return rc; @@ -98,16 +95,19 @@ static int allow_uids_cb(struct kstorage *kstorage, void *udata) int out_num; } *up = (typeof(up))udata; + struct su_profile *profile = (struct su_profile *)kstorage->data; + + int num = 0; + if (up->is_user) { - int cplen = compat_copy_to_user(up->out_uids + num, &uid, sizeof(uid)); - logkfd("uid: %d\n", uid); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; + int cprc = compat_copy_to_user(up->out_uids + num, &profile->uid, sizeof(uid_t)); + logkfd("uid: %d\n", profile->uid); + if (cprc <= 0) { + logkfd("compat_copy_to_user error: %d", cprc); + return cprc; } } else { - out_uids[num] = uid; + up->out_uids[num] = profile->uid; } num++; @@ -129,28 +129,29 @@ int su_allow_uids(int is_user, uid_t *out_uids, int out_num) } KP_EXPORT_SYMBOL(su_allow_uids); -int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile) +int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *out_profile) { - int rc = -ENOENT; + int rc = 0; + rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry(pos, &allow_uid_list, list) - { - if (pos->profile.uid != uid) continue; - if (is_user) { - int cplen = compat_copy_to_user(profile, &pos->profile, sizeof(struct su_profile)); - logkfd("profile: %d %d %s\n", uid, pos->profile.to_uid, pos->profile.scontext); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; - } - } else { - memcpy(profile, &pos->profile, sizeof(struct su_profile)); - } - rc = 0; + const struct kstorage *ks = get_kstorage(KSTORAGE_SU_LIST_GROUP, uid); + if (IS_ERR(ks)) { + rc = -ENOENT; goto out; } + struct su_profile *profile = (struct su_profile *)ks->data; + + if (is_user) { + rc = compat_copy_to_user(out_profile, profile, sizeof(struct su_profile)); + if (rc <= 0) { + logkfd("compat_copy_to_user error: %d", rc); + goto out; + } + logkfd("%d %d %s\n", profile->uid, profile->to_uid, profile->scontext); + } else { + memcpy(out_profile, profile, sizeof(struct su_profile)); + } + out: rcu_read_unlock(); return rc; @@ -185,8 +186,8 @@ static void handle_before_execve(char **__user u_filename_p, char **__user uargv if (!strcmp(current_su_path, filename)) { uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; - struct su_profile profile = profile_su_allow_uid(uid); + struct su_profile profile; + if (su_allow_uid_profile(0, uid, &profile)) return; uid_t to_uid = profile.to_uid; const char *sctx = profile.scontext; @@ -317,18 +318,18 @@ int su_compat_init() #ifdef ANDROID // default shell if (!all_allow_sctx[0]) strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK); - su_add_allow_uid(2000, 0, all_allow_sctx, 1); - su_add_allow_uid(0, 0, all_allow_sctx, 1); + su_add_allow_uid(2000, 0, all_allow_sctx); + su_add_allow_uid(0, 0, all_allow_sctx); #endif hook_err_t rc = HOOK_NO_ERR; uint8_t su_config = patch_config->patch_su_config; - bool enable = su_config & PATCH_CONFIG_SU_ENABLE; - bool wrap = su_config & PATCH_CONFIG_SU_HOOK_NO_WRAP; - log_boot("su config, enable: %d, wrap: %d\n"); + bool enable = !!(su_config & PATCH_CONFIG_SU_ENABLE); + bool wrap = !!(su_config & PATCH_CONFIG_SU_HOOK_NO_WRAP); + log_boot("su config: %x, enable: %d, wrap: %d\n", su_config, enable, wrap); - if (!enable) return; + // if (!enable) return; rc = hook_syscalln(__NR_execve, 3, before_execve, 0, (void *)0); log_boot("hook __NR_execve rc: %d\n", rc); diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index f8bf6fb7..0b358899 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -166,14 +166,14 @@ static long call_grant_uid(struct su_profile *__user uprofile) { struct su_profile *profile = memdup_user(uprofile, sizeof(struct su_profile)); if (!profile || IS_ERR(profile)) return PTR_ERR(profile); - int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext, 1); + int rc = su_add_allow_uid(profile->uid, profile->to_uid, profile->scontext); kvfree(profile); return rc; } static long call_revoke_uid(uid_t uid) { - return su_remove_allow_uid(uid, 1); + return su_remove_allow_uid(uid); } static long call_su_allow_uid_nums() diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index afcc24e2..1d9aa8ea 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -58,8 +58,7 @@ static const char supercmd_help[] = "" "KernelPatch supercmd:\n" "Usage: truncate [-uZc] [Command [[SubCommand]...]]\n" - "superkey|su: Authentication. For certain commands, if the current uid is allowed to use su,\n" - " the 'su' string can be used for authentication.\n" + "superkey|su: Authentication.\n" "Options:\n" " -u Change user id to UID.\n" " -Z Change security context to SCONTEXT.\n" @@ -122,7 +121,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } if (carr[3]) kstrtoull(carr[3], 10, &to_uid); if (carr[4]) scontext = carr[4]; - su_add_allow_uid(uid, to_uid, scontext, 1); + su_add_allow_uid(uid, to_uid, scontext); sprintf(buffer, "grant %d, %d, %s", uid, to_uid, scontext); cmd_res->msg = buffer; } else if (!strcmp(sub_cmd, "revoke")) { @@ -133,7 +132,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char cmd_res->err_msg = buffer; return; } - su_remove_allow_uid(uid, 1); + su_remove_allow_uid(uid); cmd_res->msg = suid; } else if (!strcmp(sub_cmd, "num")) { int num = su_allow_uid_nums(); @@ -298,7 +297,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } else if (!strcmp("su", arg1)) { uid_t uid = current_uid(); if (!is_su_allow_uid(uid)) return; - profile = profile_su_allow_uid(uid); + su_allow_uid_profile(0, uid, &profile); } else { return; } diff --git a/kernel/patch/include/accctl.h b/kernel/patch/include/accctl.h index dd1f54ca..829fe53f 100644 --- a/kernel/patch/include/accctl.h +++ b/kernel/patch/include/accctl.h @@ -24,14 +24,6 @@ int commit_common_su(uid_t to_uid, const char *sctx); int commit_su(uid_t uid, const char *sctx); int task_su(pid_t pid, uid_t to_uid, const char *sctx); -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext); -int su_remove_allow_uid(uid_t uid); -int su_allow_uid_nums(); -int su_allow_uids(int is_user, uid_t *out_uids, int out_num); -int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile); -int su_reset_path(const char *path); -const char *su_get_path(); - /** * @brief Whether to make the current task bypass all selinux permission checks. * diff --git a/kernel/patch/include/kstorage.h b/kernel/patch/include/kstorage.h index 13159d2e..8e7c0a27 100644 --- a/kernel/patch/include/kstorage.h +++ b/kernel/patch/include/kstorage.h @@ -6,8 +6,8 @@ #ifndef _KP_KSTORAGE_H_ #define _KP_KSTORAGE_H_ -#include #include +#include #include struct kstorage @@ -30,7 +30,7 @@ int write_kstorage(int gid, long did, void *data, int offset, int len, bool data // must surround with rcu read lock const struct kstorage *get_kstorage(int gid, long did); -typedef int (*on_kstorage_cb)(struct kstroage *kstorage, void *udata); +typedef int (*on_kstorage_cb)(struct kstorage *kstorage, void *udata); int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata); const struct kstorage *get_kstorage(int gid, long did); diff --git a/kernel/patch/include/sucompat.h b/kernel/patch/include/sucompat.h index 03a00bbd..d1da7bc8 100644 --- a/kernel/patch/include/sucompat.h +++ b/kernel/patch/include/sucompat.h @@ -23,8 +23,14 @@ struct allow_uid struct rcu_head rcu; }; -struct su_profile profile_su_allow_uid(uid_t uid); int is_su_allow_uid(uid_t uid); +int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext); +int su_remove_allow_uid(uid_t uid); +int su_allow_uid_nums(); +int su_allow_uids(int is_user, uid_t *out_uids, int out_num); +int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile); +int su_reset_path(const char *path); +const char *su_get_path(); void handle_supercmd(char **__user u_filename_p, char **__user uargv); diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index ff273b65..19ac252b 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -65,6 +65,13 @@ struct kernel_storage #define SUPERCALL_KEY_MAX_LEN 0x40 #define SUPERCALL_SCONTEXT_LEN 0x60 +struct su_profile +{ + uid_t uid; + uid_t to_uid; + char scontext[SUPERCALL_SCONTEXT_LEN]; +}; + #ifdef ANDROID #define SH_PATH "/system/bin/sh" #define SU_PATH "/system/bin/kp" From a4c4082acf7fd61ee8ff61fb66ba5698e1a631aa Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 30 Sep 2024 20:16:02 +0800 Subject: [PATCH 48/71] add exclude api, add exclude command to supercmd --- kernel/patch/common/selinuxhook.c.bak | 336 ---------------- kernel/patch/common/sucompat.c | 43 +- kernel/patch/common/sucompat.c.bak | 554 -------------------------- kernel/patch/common/supercmd.c | 23 +- kernel/patch/include/kstorage.h | 4 +- kernel/patch/include/sucompat.h | 3 +- kernel/patch/include/uapi/scdefs.h | 4 +- kernel/patch/patch.c | 8 +- user/supercall.h | 109 ++--- 9 files changed, 131 insertions(+), 953 deletions(-) delete mode 100644 kernel/patch/common/selinuxhook.c.bak delete mode 100644 kernel/patch/common/sucompat.c.bak diff --git a/kernel/patch/common/selinuxhook.c.bak b/kernel/patch/common/selinuxhook.c.bak deleted file mode 100644 index 20be0f2d..00000000 --- a/kernel/patch/common/selinuxhook.c.bak +++ /dev/null @@ -1,336 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2023 bmax121. All Rights Reserved. - */ - -#include "accctl.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SHOW_AVC_PASS_LOG - -#if 0 -static void _selinux_debug(u32 ssid, u32 tsid, u16 tclass, u32 requested) -{ - logkfd("ssid: %x, tsid: %x, tclass: %x, requested: %x\n", ssid, tsid, tclass, requested); - char *scontext = 0; - u32 sctx_len = 0; - char *tcontext = 0; - u32 tctx_len = 0; - security_sid_to_context(ssid, &scontext, &sctx_len); - security_sid_to_context(tsid, &tcontext, &tctx_len); - const char *stclass = kvar_val(secclass_map)[tclass - 1].name; - const char *const *perms = kvar_val(secclass_map)[tclass - 1].perms; - char buf[128] = { '\0' }; - for (int i = 0; i < (sizeof(u32) * 8); i++) { - if ((1 << i) & requested) { - int len = min_strlen(buf); - min_snprintf(buf + len, 128 - len, "%s ", perms[i]); - } - } - logkfd("context: %s, tcontext: %s, tclass: %s, perms: %s\n", scontext, tcontext, stclass, buf); -} -#endif - -#define hook_backup(func) (*backup_##func) -#define hook_replace(func) replace_##func -#define hook_call_backup(func, ...) backup_##func(__VA_ARGS__) - -#define hook_kfunc_with(func, replace, backup) \ - if (kfunc(func)) { \ - hook_err_t err_##func = hook(kfunc(func), replace, (void **)&backup); \ - if (err_##func != HOOK_NO_ERR) log_boot("hook %s, %llx, error: %d\n", #func, kfunc(func), err_##func); \ - } else { \ - log_boot("no symbol: %s\n", #func); \ - } - -#define hook_kfunc(func) hook_kfunc_with(func, replace_##func, backup_##func) - -#define find_and_hook_func_with(func, replace, backup) \ - unsigned long addr = kallsyms_lookup_name(#func); \ - if (addr) { \ - hook_err_t err_##func = hook(addr, replace, (void **)&backup); \ - if (err_##func != HOOK_NO_ERR) log_boot("hook %s, %llx, error: %d\n", #func, kfunc(func), err_##func); \ - } else { \ - log_boot("no symbol %s\n", #func); \ - } - -#define HOOK_AVC_RET_ZERO_BEFORE() \ - struct task_ext *ext = get_current_task_ext(); \ - if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { \ - return 0; \ - } - -static int (*avc_denied_backup)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, void *requested, - void *driver, void *xperm, void *flags, struct av_decision *avd) = 0; - -static int avc_denied_replace(struct selinux_state *_state, void *_ssid, void *_tsid, void *_tclass, void *_requested, - void *_driver, void *_xperm, void *_flags, struct av_decision *_avd) -{ - struct task_ext *ext = get_current_task_ext(); - if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { - struct av_decision *avd = (struct av_decision *)_avd; - if ((uint64_t)_state <= 0xffffffffL) { - avd = (struct av_decision *)_flags; - } - avd->allowed = 0xffffffff; - avd->auditallow = 0; - avd->auditdeny = 0; - return 0; - } - int rc = avc_denied_backup(_state, _ssid, _tsid, _tclass, _requested, _driver, _xperm, _flags, _avd); - return rc; -} - -static int (*slow_avc_audit_backup)(struct selinux_state *_state, void *_ssid, void *_tsid, void *_tclass, - void *_requested, void *_audited, void *_denied, void *_result, - struct common_audit_data *_a) = 0; - -static int slow_avc_audit_replace(struct selinux_state *_state, void *_ssid, void *_tsid, void *_tclass, - void *_requested, void *_audited, void *_denied, void *_result, - struct common_audit_data *_a) -{ - struct task_ext *ext = get_current_task_ext(); - if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { - return 0; - } - int rc = slow_avc_audit_backup(_state, _ssid, _tsid, _tclass, _requested, _audited, _denied, _result, _a); - return rc; -} - -// static inline void *min_memset(void *dst, int c, size_t n) -// { -// char *q = dst; -// while (n--) { -// *q++ = c; -// } -// return dst; -// } - -// static int hook_backup(avc_has_perm_noaudit)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, -// void *requested, void *flags, struct av_decision *avd) = 0; -// static int hook_replace(avc_has_perm_noaudit)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, -// void *requested, void *flags, struct av_decision *avd) -// { -// // HOOK_AVC_RET_ZERO_BEFORE(); - -// struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { -// struct av_decision *avd = (struct av_decision *)avd; -// if (((uint64_t)state & 0xF000000000000000) != 0xF000000000000000) { -// avd = (struct av_decision *)flags; -// } -// if (((uint64_t)avd & 0xF000000000000000) == 0xF000000000000000) { -// avd->allowed = 0xffffffff; -// avd->auditallow = 0; -// avd->auditdeny = 0; -// } -// return 0; -// } - -// int rc = hook_call_backup(avc_has_perm_noaudit, state, ssid, tsid, tclass, requested, flags, avd); - -// return rc; -// } - -// static int hook_backup(avc_has_perm)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, void *requested, -// struct common_audit_data *auditdata) = 0; -// static int hook_replace(avc_has_perm)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, -// void *requested, struct common_audit_data *auditdata) -// { -// HOOK_AVC_RET_ZERO_BEFORE(); -// int rc = hook_call_backup(avc_has_perm, state, ssid, tsid, tclass, requested, auditdata); -// return rc; -// } - -// static int hook_backup(avc_has_perm_flags)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, -// void *requested, struct common_audit_data *auditdata, void *flags) = 0; -// static int hook_replace(avc_has_perm_flags)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, -// void *requested, struct common_audit_data *auditdata, void *flags) -// { -// HOOK_AVC_RET_ZERO_BEFORE(); -// int rc = hook_call_backup(avc_has_perm_flags, state, ssid, tsid, tclass, requested, auditdata, flags); -// return rc; -// } - -// // int avc_has_extended_perms((struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, u32 requested, u8 driver, u8 xperm, struct common_audit_data *ad) -// static int hook_backup(avc_has_extended_perms)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, -// void *requested, void *driver, void *perm, struct common_audit_data *ad); -// static int hook_replace(avc_has_extended_perms)(struct selinux_state *state, void *ssid, void *tsid, void *tclass, -// void *requested, void *driver, void *perm, struct common_audit_data *ad) -// { -// HOOK_AVC_RET_ZERO_BEFORE(); -// int rc = hook_call_backup(avc_has_extended_perms, state, ssid, tsid, tclass, requested, driver, perm, ad); -// return rc; -// } - -// static void make_avc_node_all_perm(struct avc_node *node) -// { -// struct avc_entry *ae = &node->ae; -// struct av_decision *avd = &ae->avd; -// avd->allowed = 0xffffffff; -// avd->auditallow = 0; -// avd->auditdeny = 0; -// if (likely(kfunc(avc_has_extended_perms))) { -// struct avc_xperms_node *xp_node = ae->xp_node; -// if (xp_node) { -// struct extended_perms *xp = &xp_node->xp; -// min_memset(xp->drivers.p, 0xff, sizeof(xp->drivers.p)); -// } -// } -// } - -// struct avc_node *hook_backup(avc_lookup)(void *_state, void *_ssid, void *_tsid, void *_tclass) = 0; - -// // struct selinux_avc *avc, u32 ssid, u32 tsid, u16 tclass -// struct avc_node *hook_replace(avc_lookup)(void *_state, void *_ssid, void *_tsid, void *_tclass) -// { -// struct avc_node *node = hook_call_backup(avc_lookup, _state, _ssid, _tsid, _tclass); -// if (!node) return node; - -// struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { -// make_avc_node_all_perm(node); -// } -// return node; -// } - -// struct avc_node *hook_backup(avc_compute_av)(void *_state, void *_ssid, void *_tsid, void *_tclass, void *_avd, -// void *_xp_node); - -// // struct selinux_state *state,u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd, struct avc_xperms_node *xp_node -// struct avc_node *hook_replace(avc_compute_av)(void *_state, void *_ssid, void *_tsid, void *_tclass, void *_avd, -// void *_xp_node) -// { -// struct avc_node *node = hook_call_backup(avc_compute_av, _state, _ssid, _tsid, _tclass, _avd, _xp_node); -// struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { -// struct av_decision *avd = (struct av_decision *)_avd; -// struct avc_xperms_node *xp_node = (struct avc_xperms_node *)_xp_node; -// if ((uint64_t)_state <= 0xffffffffL) { -// avd = (struct av_decision *)_tclass; -// xp_node = (struct avc_xperms_node *)_avd; -// } -// avd->allowed = 0xffffffff; -// avd->auditallow = 0; -// avd->auditdeny = 0; -// if (xp_node) { -// struct extended_perms *xp = &xp_node->xp; -// min_memset(xp->drivers.p, 0xff, sizeof(xp->drivers.p)); -// } -// make_avc_node_all_perm(node); -// } -// return node; -// } - -// static void hook_backup(security_compute_av)(void *_state, void *_ssid, void *_tsid, void *_orig_tclass, void *_avd, -// void *_xperms) = 0; - -// // struct selinux_state *state, u32 ssid, u32 tsid, u16 orig_tclass, struct av_decision *avd, struct extended_perms *xperms -// static void hook_replace(security_compute_av)(void *_state, void *_ssid, void *_tsid, void *_orig_tclass, void *_avd, -// void *_xperms) -// { -// hook_call_backup(security_compute_av, _state, _ssid, _tsid, _orig_tclass, _avd, _xperms); - -// struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { -// struct av_decision *avd = (struct av_decision *)_avd; -// struct extended_perms *xperms = (struct extended_perms *)_xperms; -// if ((uint64_t)_state <= 0xffffffffL) { -// avd = (struct av_decision *)_orig_tclass; -// xperms = (struct extended_perms *)_avd; -// } -// avd->allowed = 0xffffffff; -// avd->auditallow = 0; -// avd->auditdeny = 0; -// if (xperms) { -// min_memset(xperms->drivers.p, 0xff, sizeof(xperms->drivers.p)); -// } -// } -// } - -// static void hook_backup(security_compute_xperms_decision)(void *_state, void *_ssid, void *_tsid, void *_orig_tclass, -// void *_driver, void *_xpermd) = 0; - -// //struct selinux_state *state, u32 ssid, u32 tsid, u16 orig_tclass, u8 driver, struct extended_perms_decision *xpermd -// static void hook_replace(security_compute_xperms_decision)(void *_state, void *_ssid, void *_tsid, void *_orig_tclass, -// void *_driver, void *_xpermd) -// { -// hook_call_backup(security_compute_xperms_decision, _state, _ssid, _tsid, _orig_tclass, _driver, _xpermd); -// struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { -// struct extended_perms_decision *xpermd = (struct extended_perms_decision *)_xpermd; -// if ((uint64_t)_state <= 0xffffffffL) { -// xpermd = (struct extended_perms_decision *)_driver; -// } -// min_memset(xpermd->allowed->p, 0xff, sizeof(xpermd->allowed->p)); -// min_memset(xpermd->auditallow->p, 0, sizeof(xpermd->auditallow->p)); -// min_memset(xpermd->dontaudit->p, 0xff, sizeof(xpermd->dontaudit->p)); -// } -// } - -// static void hook_backup(security_compute_av_user)(void *_state, void *_ssid, void *_tsid, void *_tclass, -// void *_avd) = 0; - -// // struct selinux_state *state, u32 ssid, u32 tsid, u16 tclass, struct av_decision *avd -// static void hook_replace(security_compute_av_user)(void *_state, void *_ssid, void *_tsid, void *_tclass, void *_avd) -// { -// hook_call_backup(security_compute_av_user, _state, _ssid, _tsid, _tclass, _avd); - -// struct task_ext *ext = get_current_task_ext(); -// if (unlikely(task_ext_valid(ext) && (ext->sel_allow || ext->priv_sel_allow))) { -// struct av_decision *avd = (struct av_decision *)_avd; -// if ((uint64_t)_state <= 0xffffffffL) { -// avd = (struct av_decision *)_tclass; -// } -// avd->allowed = 0xffffffff; -// avd->auditallow = 0; -// avd->auditdeny = 0; -// } -// } - -int selinux_hook_install() -{ - unsigned long avc_denied_addr = patch_config->avc_denied; - if (avc_denied_addr) { - hook_err_t err = hook((void *)avc_denied_addr, (void *)avc_denied_replace, (void **)&avc_denied_backup); - if (err != HOOK_NO_ERR) { - log_boot("hook avc_denied_addr: %llx, error: %d\n", avc_denied_addr, err); - } - } - - unsigned long slow_avc_audit_addr = patch_config->slow_avc_audit; - if (slow_avc_audit_addr) { - hook_err_t err = - hook((void *)slow_avc_audit_addr, (void *)slow_avc_audit_replace, (void **)&slow_avc_audit_backup); - if (err != HOOK_NO_ERR) { - log_boot("hook slow_avc_audit: %llx, error: %d\n", slow_avc_audit_addr, err); - } - } - - // hook_kfunc(avc_denied); - // hook_kfunc(slow_avc_audit); - - // hook_kfunc(avc_has_perm_noaudit); - // hook_kfunc(avc_has_perm); - // hook_kfunc(avc_has_perm_flags); - // hook_kfunc(avc_has_extended_perms); - - // we can't hook avc_compute_av and ..., it will 'avc_update_node' with diffused permission allowed - // hook_kfunc(avc_lookup); - // hook_kfunc(avc_compute_av); - - // hook_kfunc(security_compute_av); - // hook_kfunc(security_compute_xperms_decision); - // hook_kfunc(security_compute_av_user); - - return 0; -} \ No newline at end of file diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 6a017d34..13cfc4d4 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -49,10 +49,13 @@ const char apd_path[] = APD_PATH; static const char *current_su_path = 0; +static int su_kstorage_gid = -1; +static int exclude_kstorage_gid = -1; + int is_su_allow_uid(uid_t uid) { rcu_read_lock(); - const struct kstorage *ks = get_kstorage(KSTORAGE_SU_LIST_GROUP, uid); + const struct kstorage *ks = get_kstorage(su_kstorage_gid, uid); struct su_profile *profile = (struct su_profile *)ks->data; int rc = profile != 0; rcu_read_unlock(); @@ -68,7 +71,7 @@ int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext) to_uid, }; memcpy(profile.scontext, scontext, SUPERCALL_SCONTEXT_LEN); - int rc = write_kstorage(KSTORAGE_SU_LIST_GROUP, uid, &profile, 0, sizeof(struct su_profile), false); + int rc = write_kstorage(su_kstorage_gid, uid, &profile, 0, sizeof(struct su_profile), false); logkfd("uid: %d, to_uid: %d, sctx: %s, rc: %d\n", uid, to_uid, scontext, rc); return rc; } @@ -76,13 +79,13 @@ KP_EXPORT_SYMBOL(su_add_allow_uid); int su_remove_allow_uid(uid_t uid) { - return remove_kstorage(KSTORAGE_SU_LIST_GROUP, uid); + return remove_kstorage(su_kstorage_gid, uid); } KP_EXPORT_SYMBOL(su_remove_allow_uid); int su_allow_uid_nums() { - return kstorage_group_size(KSTORAGE_SU_LIST_GROUP); + return kstorage_group_size(su_kstorage_gid); } KP_EXPORT_SYMBOL(su_allow_uid_nums); @@ -124,7 +127,7 @@ int su_allow_uids(int is_user, uid_t *out_uids, int out_num) uid_t *up; int un; } udata = { is_user, out_uids, out_num }; - on_each_kstorage_elem(KSTORAGE_SU_LIST_GROUP, allow_uids_cb, &udata); + on_each_kstorage_elem(su_kstorage_gid, allow_uids_cb, &udata); return rc; } KP_EXPORT_SYMBOL(su_allow_uids); @@ -134,7 +137,7 @@ int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *out_profile) int rc = 0; rcu_read_lock(); - const struct kstorage *ks = get_kstorage(KSTORAGE_SU_LIST_GROUP, uid); + const struct kstorage *ks = get_kstorage(su_kstorage_gid, uid); if (IS_ERR(ks)) { rc = -ENOENT; goto out; @@ -237,6 +240,7 @@ static void handle_before_execve(char **__user u_filename_p, char **__user uargv } #endif // ANDROID } else if (!strcmp(SUPERCMD, filename)) { + void handle_supercmd(char **__user u_filename_p, char **__user uargv); handle_supercmd(u_filename_p, uargv); return; } @@ -311,6 +315,27 @@ static void su_handler_arg1_ufilename_before(hook_fargs6_t *args, void *udata) } } +int set_su_mod_exclude(uid_t uid, int exclude) +{ + int rc = 0; + if (exclude) { + rc = write_kstorage(exclude_kstorage_gid, uid, &exclude, 0, sizeof(exclude), false); + } else { + rc = remove_kstorage(exclude_kstorage_gid, uid); + } + return rc; +} +KP_EXPORT_SYMBOL(set_su_mod_exclude); + +int get_su_mod_exclude(uid_t uid) +{ + int exclude = 0; + int rc = read_kstorage(exclude_kstorage_gid, uid, &exclude, 0, sizeof(exclude), false); + if (rc < 0) return false; + return exclude; +} +KP_EXPORT_SYMBOL(get_su_mod_exclude); + int su_compat_init() { current_su_path = default_su_path; @@ -331,6 +356,12 @@ int su_compat_init() // if (!enable) return; + su_kstorage_gid = try_alloc_kstroage_group(); + if (su_kstorage_gid < 0) return -ENOMEM; + + exclude_kstorage_gid = try_alloc_kstroage_group(); + if (exclude_kstorage_gid < 0) return -ENOMEM; + rc = hook_syscalln(__NR_execve, 3, before_execve, 0, (void *)0); log_boot("hook __NR_execve rc: %d\n", rc); diff --git a/kernel/patch/common/sucompat.c.bak b/kernel/patch/common/sucompat.c.bak deleted file mode 100644 index be3ab2e4..00000000 --- a/kernel/patch/common/sucompat.c.bak +++ /dev/null @@ -1,554 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2023 bmax121. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -const char sh_path[] = SH_PATH; -const char default_su_path[] = SU_PATH; - -#ifdef ANDROID -const char legacy_su_path[] = LEGACY_SU_PATH; -const char apd_path[] = APD_PATH; -#endif - -static const char *current_su_path = 0; - -static struct list_head allow_uid_list; -static spinlock_t list_lock; - -static void allow_reclaim_callback(struct rcu_head *rcu) -{ - struct allow_uid *allow = container_of(rcu, struct allow_uid, rcu); - kvfree(allow); -} - -struct su_profile profile_su_allow_uid(uid_t uid) -{ - rcu_read_lock(); - struct allow_uid *pos; - struct su_profile profile = { 0 }; - list_for_each_entry_rcu(pos, &allow_uid_list, list) - { - if (pos->uid == uid) { - memcpy(&profile, &pos->profile, sizeof(struct su_profile)); - rcu_read_unlock(); - return profile; - } - } - rcu_read_unlock(); - return profile; -} -KP_EXPORT_SYMBOL(profile_su_allow_uid); - -int is_su_allow_uid(uid_t uid) -{ - rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry_rcu(pos, &allow_uid_list, list) - { - if (pos->uid == uid) { - rcu_read_unlock(); - return 1; - } - } - rcu_read_unlock(); - return 0; -} -KP_EXPORT_SYMBOL(is_su_allow_uid); - -int su_add_allow_uid(uid_t uid, uid_t to_uid, const char *scontext, int async) -{ - if (!scontext) scontext = ""; - - rcu_read_lock(); - struct allow_uid *pos, *old = 0; - list_for_each_entry(pos, &allow_uid_list, list) - { - if (pos->uid == uid) { - old = pos; - break; - } - } - // todo: vmalloc -> kmalloc, gfp - struct allow_uid *new = (struct allow_uid *)vmalloc(sizeof(struct allow_uid)); - new->uid = uid; - new->profile.uid = uid; - new->profile.to_uid = to_uid; - strncpy(new->profile.scontext, scontext, sizeof(new->profile.scontext)); - new->profile.scontext[sizeof(new->profile.scontext) - 1] = '\0'; - - spin_lock(&list_lock); - if (old) { // update - list_replace_rcu(&old->list, &new->list); - logkfi("update uid: %d, to_uid: %d, sctx: %s\n", uid, new->profile.to_uid, new->profile.scontext); - } else { // add new one - list_add_rcu(&new->list, &allow_uid_list); - logkfi("new uid: %d, to_uid: %d, sctx: %s\n", uid, new->profile.to_uid, new->profile.scontext); - } - spin_unlock(&list_lock); - - rcu_read_unlock(); - if (old) { - if (async) { - call_rcu(&old->rcu, allow_reclaim_callback); - } else { - synchronize_rcu(); - kvfree(old); - } - } - return 0; -} -KP_EXPORT_SYMBOL(su_add_allow_uid); - -int su_remove_allow_uid(uid_t uid, int async) -{ - struct allow_uid *pos; - spin_lock(&list_lock); - list_for_each_entry(pos, &allow_uid_list, list) - { - if (pos->uid == uid) { - list_del_rcu(&pos->list); - spin_unlock(&list_lock); - logkfi("uid: %d, to_uid: %d, sctx: %s\n", pos->uid, pos->profile.to_uid, pos->profile.scontext); - if (async) { - call_rcu(&pos->rcu, allow_reclaim_callback); - } else { - synchronize_rcu(); - kvfree(pos); - } - return 0; - } - } - spin_unlock(&list_lock); - return 0; -} -KP_EXPORT_SYMBOL(su_remove_allow_uid); - -int su_allow_uid_nums() -{ - int num = 0; - rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry(pos, &allow_uid_list, list) - { - num++; - } - rcu_read_unlock(); - logkfd("%d\n", num); - return num; -} -KP_EXPORT_SYMBOL(su_allow_uid_nums); - -int su_allow_uids(int is_user, uid_t *out_uids, int out_num) -{ - int rc = 0; - int num = 0; - rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry(pos, &allow_uid_list, list) - { - if (num >= out_num) goto out; - - uid_t uid = pos->profile.uid; - if (is_user) { - int cplen = compat_copy_to_user(out_uids + num, &uid, sizeof(uid)); - logkfd("uid: %d\n", uid); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; - } - } else { - out_uids[num] = uid; - } - - num++; - } - rc = num; -out: - rcu_read_unlock(); - return rc; -} -KP_EXPORT_SYMBOL(su_allow_uids); - -int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile) -{ - int rc = -ENOENT; - rcu_read_lock(); - struct allow_uid *pos; - list_for_each_entry(pos, &allow_uid_list, list) - { - if (pos->profile.uid != uid) continue; - if (is_user) { - int cplen = compat_copy_to_user(profile, &pos->profile, sizeof(struct su_profile)); - logkfd("profile: %d %d %s\n", uid, pos->profile.to_uid, pos->profile.scontext); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); - rc = cplen; - goto out; - } - } else { - memcpy(profile, &pos->profile, sizeof(struct su_profile)); - } - rc = 0; - goto out; - } -out: - rcu_read_unlock(); - return rc; -} -KP_EXPORT_SYMBOL(su_allow_uid_profile); - -// no free, no lock -int su_reset_path(const char *path) -{ - if (!path) return -EINVAL; - if (IS_ERR(path)) return PTR_ERR(path); - current_su_path = path; - logkfd("%s\n", current_su_path); - dsb(ish); - return 0; -} -KP_EXPORT_SYMBOL(su_reset_path); - -const char *su_get_path() -{ - if (!current_su_path) current_su_path = default_su_path; - return current_su_path; -} -KP_EXPORT_SYMBOL(su_get_path); - -// #define TRY_DIRECT_MODIFY_USER - -#define INLINE_HOOK_SYSCALL - -static void handle_before_execve(hook_local_t *hook_local, char **__user u_filename_p, char **__user uargv, void *udata) -{ -#ifdef TRY_DIRECT_MODIFY_USER - // copy to user len - hook_local->data0 = 0; -#endif - - char __user *ufilename = *u_filename_p; - char filename[SU_PATH_MAX_LEN]; - int flen = compat_strncpy_from_user(filename, ufilename, sizeof(filename)); - if (flen <= 0) return; - - if (!strcmp(current_su_path, filename)) { - uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; - struct su_profile profile = profile_su_allow_uid(uid); - - uid_t to_uid = profile.to_uid; - const char *sctx = profile.scontext; - commit_su(to_uid, sctx); - -#ifdef ANDROID - struct file *filp = filp_open(apd_path, O_RDONLY, 0); - if (!filp || IS_ERR(filp)) { -#endif - int cplen = 0; -#ifdef TRY_DIRECT_MODIFY_USER - cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); - if (cplen > 0) { - hook_local->data0 = cplen; - hook_local->data1 = (uint64_t)u_filename_p; - logkfi("call su uid: %d, to_uid: %d, sctx: %s, cplen: %d\n", uid, to_uid, sctx, cplen); - } -#endif - if (cplen <= 0) { - void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); - if (uptr && !IS_ERR(uptr)) { - *u_filename_p = (char *__user)uptr; - } - logkfi("call su uid: %d, to_uid: %d, sctx: %s, uptr: %llx\n", uid, to_uid, sctx, uptr); - } - -#ifdef ANDROID - } else { - filp_close(filp, 0); - - // command - int cplen = 0; -#ifdef TRY_DIRECT_MODIFY_USER - cplen = compat_copy_to_user(*u_filename_p, apd_path, sizeof(apd_path)); - if (cplen > 0) { - hook_local->data0 = cplen; - hook_local->data1 = (uint64_t)u_filename_p; - } -#endif - uint64_t sp = 0; - if (cplen <= 0) { - sp = current_user_stack_pointer(); - sp -= sizeof(apd_path); - sp &= 0xFFFFFFFFFFFFFFF8; - cplen = compat_copy_to_user((void *)sp, apd_path, sizeof(apd_path)); - if (cplen > 0) { - *u_filename_p = (char *)sp; - } - } - - // argv - int argv_cplen = 0; - if (strcmp(legacy_su_path, filename)) { -#ifdef TRY_DIRECT_MODIFY_USER - const char __user *p1 = get_user_arg_ptr(0, *uargv, 0); - argv_cplen = compat_copy_to_user((void *__user)p1, legacy_su_path, sizeof(legacy_su_path)); -#endif - if (argv_cplen <= 0) { - sp = sp ?: current_user_stack_pointer(); - sp -= sizeof(legacy_su_path); - sp &= 0xFFFFFFFFFFFFFFF8; - argv_cplen = compat_copy_to_user((void *)sp, legacy_su_path, sizeof(legacy_su_path)); - if (argv_cplen > 0) { - int rc = set_user_arg_ptr(0, *uargv, 0, sp); - if (rc < 0) { // todo: modify entire argv - logkfi("call apd argv error, uid: %d, to_uid: %d, sctx: %s, rc: %d\n", uid, to_uid, sctx, - rc); - } - } - } - } - logkfi("call apd uid: %d, to_uid: %d, sctx: %s, cplen: %d, %d\n", uid, to_uid, sctx, cplen, argv_cplen); - } -#endif // ANDROID - } else if (!strcmp(SUPERCMD, filename)) { - handle_supercmd(u_filename_p, uargv); - return; - } -} - -#ifdef TRY_DIRECT_MODIFY_USER -static void handle_after_execve(hook_local_t *hook_local) -{ - int cplen = hook_local->data0; - char **__user u_filename_p = (char **__user)hook_local->data1; - if (cplen > 0) { - compat_copy_to_user((void *)*u_filename_p, current_su_path, cplen); - } -} -#endif - -// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2107 -// COMPAT_SYSCALL_DEFINE3(execve, const char __user *, filename, -// const compat_uptr_t __user *, argv, -// const compat_uptr_t __user *, envp) - -// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2087 -// SYSCALL_DEFINE3(execve, const char __user *, filename, const char __user *const __user *, argv, -// const char __user *const __user *, envp) - -static void before_execve(hook_fargs3_t *args, void *udata) -{ - void *arg0p = syscall_argn_p(args, 0); - void *arg1p = syscall_argn_p(args, 1); - handle_before_execve(&args->local, (char **)arg0p, (char **)arg1p, udata); -} - -#ifdef TRY_DIRECT_MODIFY_USER -static void after_execve(hook_fargs3_t *args, void *udata) -{ - handle_after_execve(&args->local); -} -#else -#define after_execve 0 -#endif - -// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2114 -// COMPAT_SYSCALL_DEFINE5(execveat, int, fd, -// const char __user *, filename, -// const compat_uptr_t __user *, argv, -// const compat_uptr_t __user *, envp, -// int, flags) - -// https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2095 -// SYSCALL_DEFINE5(execveat, int, fd, const char __user *, filename, const char __user *const __user *, argv, -// const char __user *const __user *, envp, int, flags) -__maybe_unused static void before_execveat(hook_fargs5_t *args, void *udata) -{ - void *arg1p = syscall_argn_p(args, 1); - void *arg2p = syscall_argn_p(args, 2); - handle_before_execve(&args->local, (char **)arg1p, (char **)arg2p, udata); -} - -#ifdef TRY_DIRECT_MODIFY_USER -static void after_execveat(hook_fargs5_t *args, void *udata) -{ - handle_after_execve(&args->local); -} -#else -#define after_execveat 0 -#endif - -// https://elixir.bootlin.com/linux/v6.1/source/fs/stat.c#L431 -// SYSCALL_DEFINE4(newfstatat, int, dfd, const char __user *, filename, -// struct stat __user *, statbuf, int, flag) - -// https://elixir.bootlin.com/linux/v6.1/source/fs/open.c#L492 -// SYSCALL_DEFINE3(faccessat, int, dfd, const char __user *, filename, int, mode) - -// https://elixir.bootlin.com/linux/v6.1/source/fs/open.c#L497 -// SYSCALL_DEFINE4(faccessat2, int, dfd, const char __user *, filename, int, mode, int, flags) - -// https://elixir.bootlin.com/linux/v6.1/source/fs/stat.c#L661 -// SYSCALL_DEFINE5(statx, -// int, dfd, const char __user *, filename, unsigned, flags, -// unsigned int, mask, -// struct statx __user *, buffer) -static void su_handler_arg1_ufilename_before(hook_fargs6_t *args, void *udata) -{ - // copy to user len - args->local.data0 = 0; - - uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; - - char __user **u_filename_p = (char __user **)syscall_argn_p(args, 1); - - char filename[SU_PATH_MAX_LEN]; - int flen = compat_strncpy_from_user(filename, *u_filename_p, sizeof(filename)); - if (flen <= 0) return; - - if (!strcmp(current_su_path, filename)) { -#ifdef TRY_DIRECT_MODIFY_USER - int cplen = 0; - cplen = compat_copy_to_user(*u_filename_p, sh_path, sizeof(sh_path)); - if (cplen > 0) { - args->local.data0 = cplen; - args->local.data1 = (uint64_t)*u_filename_p; - logkfi("su uid: %d, cp: %d\n", uid, cplen); - } else { -#endif - void *uptr = copy_to_user_stack(sh_path, sizeof(sh_path)); - if (uptr && !IS_ERR(uptr)) { - *u_filename_p = uptr; - } else { - logkfi("su uid: %d, cp stack error: %d\n", uid, uptr); - } -#ifdef TRY_DIRECT_MODIFY_USER - } -#endif - } -} - -#ifdef TRY_DIRECT_MODIFY_USER -static void su_handler_arg1_ufilename_after(hook_fargs6_t *args, void *udata) -{ - int cplen = args->local.data0; - if (cplen > 0) { - compat_copy_to_user((void *)args->local.data1, current_su_path, cplen); - } -} -#else -#define su_handler_arg1_ufilename_after 0 -#endif - -int su_compat_init() -{ - current_su_path = default_su_path; - - INIT_LIST_HEAD(&allow_uid_list); - spin_lock_init(&list_lock); - -#ifdef ANDROID - // default shell - if (!all_allow_sctx[0]) strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK); - su_add_allow_uid(2000, 0, all_allow_sctx, 1); - su_add_allow_uid(0, 0, all_allow_sctx, 1); -#endif - - hook_err_t rc = HOOK_NO_ERR; - - uint8_t su_config = patch_config->patch_su_config; - bool enable = su_config & PATCH_CONFIG_SU_ENABLE; - bool wrap = su_config & PATCH_CONFIG_SU_HOOK_NO_WRAP; - log_boot("su config, enable: %d, wrap: %d\n"); - - rc = hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)0); - log_boot("hook __NR_execve rc: %d\n", rc); - - // rc = hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)0); - // log_boot("hook __NR_execveat rc: %d\n", rc); - - rc = hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)0); - log_boot("hook __NR3264_fstatat rc: %d\n", rc); - - // rc = hook_syscalln(__NR_statx, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - // log_boot("hook __NR_statx rc: %d\n", rc); - - rc = hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - log_boot("hook __NR_faccessat rc: %d\n", rc); - - // rc = - // hook_syscalln(__NR_faccessat2, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - // log_boot("hook __NR_faccessat2 rc: %d\n", rc); - - // #include - - // __NR_execve 11 - rc = hook_compat_syscalln(11, 3, before_execve, after_execve, (void *)1); - log_boot("hook 32 __NR_execve rc: %d\n", rc); - - // __NR_execveat 387 - // rc = hook_compat_syscalln(387, 5, before_execveat, after_execveat, (void *)1); - // log_boot("hook 32 __NR_execveat rc: %d\n", rc); - - // __NR_statx 397 - // rc = hook_compat_syscalln(397, 5, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - // log_boot("hook 32 __NR_statx rc: %d\n", rc); - - // #define __NR_stat 106 - // #define __NR_lstat 107 - // #define __NR_stat64 195 - // #define __NR_lstat64 196 - - // __NR_fstatat64 327 - rc = hook_compat_syscalln(327, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - log_boot("hook 32 __NR_fstatat64 rc: %d\n", rc); - - // __NR_faccessat 334 - rc = hook_compat_syscalln(334, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - log_boot("hook 32 __NR_faccessat rc: %d\n", rc); - - // __NR_faccessat2 439 - // rc = hook_compat_syscalln(439, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, (void *)0); - // log_boot("hook 32 __NR_faccessat2 rc: %d\n", rc); - - return 0; -} \ No newline at end of file diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 1d9aa8ea..d5736425 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -80,7 +80,8 @@ static const char supercmd_help[] = " list List all su allowed uids.\n" " profile Get the profile of the uid configuration.\n" " path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n" - " sctx [SCONTEXT] Get or Reset current all allowed security context, \n" + " sctx [SCONTEXT] Get or Reset current all allowed security context.\n" + " exclude [1|0] Get or Reset exclude policy for UID.\n" " event Report EVENT.\n" "\n" "The command below requires superkey authentication.\n" @@ -179,6 +180,26 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } else { cmd_res->msg = all_allow_sctx; } + } else if (!strcmp(sub_cmd, "exclude")) { + unsigned long long uid; + if (!carr[2] || kstrtoull(carr[2], 10, &uid)) { + cmd_res->err_msg = "invalid uid"; + return; + } else { + if (!carr[3]) { + int exclude = get_su_mod_exclude(uid); + sprintf(buffer, "%d", exclude); + cmd_res->msg = buffer; + } else { + if (carr[3][0] == '0') { + set_su_mod_exclude(uid, 0); + cmd_res->msg = "0"; + } else { + set_su_mod_exclude(uid, 1); + cmd_res->msg = "1"; + } + } + } } else { cmd_res->err_msg = "invalid subcommand"; } diff --git a/kernel/patch/include/kstorage.h b/kernel/patch/include/kstorage.h index 8e7c0a27..b011c110 100644 --- a/kernel/patch/include/kstorage.h +++ b/kernel/patch/include/kstorage.h @@ -27,14 +27,12 @@ int kstorage_group_size(int gid); int write_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user); -// must surround with rcu read lock +// must within rcu read lock const struct kstorage *get_kstorage(int gid, long did); typedef int (*on_kstorage_cb)(struct kstorage *kstorage, void *udata); int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata); -const struct kstorage *get_kstorage(int gid, long did); - int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user); int remove_kstorage(int gid, long did); diff --git a/kernel/patch/include/sucompat.h b/kernel/patch/include/sucompat.h index d1da7bc8..f4035b7a 100644 --- a/kernel/patch/include/sucompat.h +++ b/kernel/patch/include/sucompat.h @@ -32,6 +32,7 @@ int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile); int su_reset_path(const char *path); const char *su_get_path(); -void handle_supercmd(char **__user u_filename_p, char **__user uargv); +int get_su_mod_exclude(uid_t uid); +int set_su_mod_exclude(uid_t uid, int exclude); #endif diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 19ac252b..76291459 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -48,8 +48,8 @@ struct kernel_storage }; #define SUPERCALL_KSTORAGE_ALLOC_GROUP 0x1040 -#define SUPERCALL_KSTORAGE_SET 0x1041 -#define SUPERCALL_KSTORAGE_GET 0x1042 +#define SUPERCALL_KSTORAGE_WRITE 0x1041 +#define SUPERCALL_KSTORAGE_READ 0x1042 #define SUPERCALL_KSTORAGE_REMOVE 0x1043 #define SUPERCALL_KSTORAGE_REMOVE_GROUP 0x1044 diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 44260e80..1f3d4dd8 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -38,19 +38,19 @@ void before_panic(hook_fargs12_t *args, void *udata) printk("==== End KernelPatch for Kernel panic ====\n"); } +void linux_misc_symbol_init(); +void linux_libs_symbol_init(); + int resolve_struct(); int task_observer(); int bypass_kcfi(); int bypass_selinux(); int resolve_pt_regs(); int supercall_install(); -int su_compat_init(); - -void linux_misc_symbol_init(); -void linux_libs_symbol_init(); void module_init(); void syscall_init(); int kstorage_init(); +int su_compat_init(); #ifdef ANDROID int android_user_init(); diff --git a/user/supercall.h b/user/supercall.h index 1e0ab50d..b2850023 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -16,14 +16,6 @@ #include "uapi/scdefs.h" #include "version" -/// @deprecated -/// KernelPatch version less than 0xa05 -static inline long hash_key_cmd(const char *key, long cmd) -{ - long hash = hash_key(key); - return hash & 0xFFFF0000 | cmd; -} - /// KernelPatch version is greater than or equal to 0x0a05 static inline long ver_and_cmd(const char *key, long cmd) { @@ -31,15 +23,6 @@ static inline long ver_and_cmd(const char *key, long cmd) return ((long)version_code << 32) | (0x1158 << 16) | (cmd & 0xFFFF); } -static inline long compact_cmd(const char *key, long cmd) -{ -#if 1 - long ver = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KERNELPATCH_VER)); - if (ver >= 0xa05) return ver_and_cmd(key, cmd); -#endif - return hash_key_cmd(key, cmd); -} - /** * @brief If KernelPatch installed, @see SUPERCALL_HELLO_ECHO will echoed. * @@ -49,7 +32,7 @@ static inline long compact_cmd(const char *key, long cmd) static inline long sc_hello(const char *key) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_HELLO)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_HELLO)); return ret; } @@ -76,7 +59,7 @@ static inline long sc_klog(const char *key, const char *msg) { if (!key || !key[0]) return -EINVAL; if (!msg || strlen(msg) <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KLOG), msg); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KLOG), msg); return ret; } @@ -89,7 +72,7 @@ static inline long sc_klog(const char *key, const char *msg) static inline uint32_t sc_kp_ver(const char *key) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KERNELPATCH_VER)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KERNELPATCH_VER)); return (uint32_t)ret; } @@ -102,7 +85,7 @@ static inline uint32_t sc_kp_ver(const char *key) static inline uint32_t sc_k_ver(const char *key) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KERNEL_VER)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KERNEL_VER)); return (uint32_t)ret; } @@ -118,12 +101,12 @@ static inline long sc_su(const char *key, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL; if (strlen(profile->scontext) >= SUPERCALL_SCONTEXT_LEN) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU), profile); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU), profile); return ret; } /** - * @brief Substitute user of tid specfied + * @brief Substitute user of tid specfied thread * * @param key : superkey or 'su' string if caller uid is su allowed * @param tid : target thread id @@ -134,7 +117,41 @@ static inline long sc_su(const char *key, struct su_profile *profile) static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_TASK), tid, profile); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_TASK), tid, profile); + return ret; +} + +/** + * @brief + * + * @param key + * @param gid group id + * @param did data id + * @param data + * @param dlen + * @return long + */ +static inline long sc_kstorage_write(const char *key, int gid, long did, void *data, int dlen) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, dlen); + return ret; +} + +/** + * @brief + * + * @param key + * @param gid + * @param did + * @param out_data + * @param dlen + * @return long + */ +static inline long sc_kstorage_read(const char *key, int gid, long did, void *out_data, int dlen) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, dlen); return ret; } @@ -148,7 +165,7 @@ static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *pro static inline long sc_su_grant_uid(const char *key, struct su_profile *profile) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GRANT_UID), profile); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_GRANT_UID), profile); return ret; } @@ -162,7 +179,7 @@ static inline long sc_su_grant_uid(const char *key, struct su_profile *profile) static inline long sc_su_revoke_uid(const char *key, uid_t uid) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_REVOKE_UID), uid); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_REVOKE_UID), uid); return ret; } @@ -175,7 +192,7 @@ static inline long sc_su_revoke_uid(const char *key, uid_t uid) static inline long sc_su_uid_nums(const char *key) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_NUMS)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_NUMS)); return ret; } @@ -191,7 +208,7 @@ static inline long sc_su_allow_uids(const char *key, uid_t *buf, int num) { if (!key || !key[0]) return -EINVAL; if (!buf || num <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_LIST), buf, num); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_LIST), buf, num); return ret; } @@ -206,7 +223,7 @@ static inline long sc_su_allow_uids(const char *key, uid_t *buf, int num) static inline long sc_su_uid_profile(const char *key, uid_t uid, struct su_profile *out_profile) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_PROFILE), uid, out_profile); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_PROFILE), uid, out_profile); return ret; } @@ -222,7 +239,7 @@ static inline long sc_su_get_path(const char *key, char *out_path, int path_len) { if (!key || !key[0]) return -EINVAL; if (!out_path || out_path <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_PATH), out_path, path_len); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_GET_PATH), out_path, path_len); return ret; } @@ -237,7 +254,7 @@ static inline long sc_su_reset_path(const char *key, const char *path) { if (!key || !key[0]) return -EINVAL; if (!path || !path[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_RESET_PATH), path); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_RESET_PATH), path); return ret; } @@ -253,7 +270,7 @@ static inline long sc_su_get_all_allow_sctx(const char *key, char *out_sctx, int { if (!key || !key[0]) return -EINVAL; if (!out_sctx) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_ALLOW_SCTX), out_sctx); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_GET_ALLOW_SCTX), out_sctx); return ret; } @@ -269,7 +286,7 @@ static inline long sc_su_reset_all_allow_sctx(const char *key, const char *sctx) { if (!key || !key[0]) return -EINVAL; if (!sctx) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_SET_ALLOW_SCTX), sctx); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_SET_ALLOW_SCTX), sctx); return ret; } @@ -286,7 +303,7 @@ static inline long sc_kpm_load(const char *key, const char *path, const char *ar { if (!key || !key[0]) return -EINVAL; if (!path || strlen(path) <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_LOAD), path, args, reserved); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KPM_LOAD), path, args, reserved); return ret; } @@ -305,7 +322,7 @@ static inline long sc_kpm_control(const char *key, const char *name, const char if (!key || !key[0]) return -EINVAL; if (!name || strlen(name) <= 0) return -EINVAL; if (!ctl_args || strlen(ctl_args) <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_CONTROL), name, ctl_args, out_msg, outlen); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KPM_CONTROL), name, ctl_args, out_msg, outlen); return ret; } @@ -321,7 +338,7 @@ static inline long sc_kpm_unload(const char *key, const char *name, void *reserv { if (!key || !key[0]) return -EINVAL; if (!name || strlen(name) <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_UNLOAD), name, reserved); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KPM_UNLOAD), name, reserved); return ret; } @@ -334,7 +351,7 @@ static inline long sc_kpm_unload(const char *key, const char *name, void *reserv static inline long sc_kpm_nums(const char *key) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_NUMS)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KPM_NUMS)); return ret; } @@ -350,7 +367,7 @@ static inline long sc_kpm_list(const char *key, char *names_buf, int buf_len) { if (!key || !key[0]) return -EINVAL; if (!names_buf || buf_len <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_LIST), names_buf, buf_len); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KPM_LIST), names_buf, buf_len); return ret; } @@ -367,7 +384,7 @@ static inline long sc_kpm_info(const char *key, const char *name, char *buf, int { if (!key || !key[0]) return -EINVAL; if (!buf || buf_len <= 0) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_KPM_INFO), name, buf, buf_len); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KPM_INFO), name, buf, buf_len); return ret; } @@ -383,7 +400,7 @@ static inline long sc_skey_get(const char *key, char *out_key, int outlen) { if (!key || !key[0]) return -EINVAL; if (outlen < SUPERCALL_KEY_MAX_LEN) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_GET), out_key, outlen); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_GET), out_key, outlen); return ret; } @@ -398,7 +415,7 @@ static inline long sc_skey_set(const char *key, const char *new_key) { if (!key || !key[0]) return -EINVAL; if (!new_key || !new_key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_SET), new_key); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_SET), new_key); return ret; } @@ -412,7 +429,7 @@ static inline long sc_skey_set(const char *key, const char *new_key) static inline long sc_skey_root_enable(const char *key, bool enable) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SKEY_ROOT_ENABLE), (long)enable); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SKEY_ROOT_ENABLE), (long)enable); return ret; } @@ -425,25 +442,25 @@ static inline long sc_skey_root_enable(const char *key, bool enable) static inline long sc_su_get_safemode(const char *key) { if (!key || !key[0]) return -EINVAL; - return syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_SU_GET_SAFEMODE)); + return syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_GET_SAFEMODE)); } static inline long sc_bootlog(const char *key) { - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_BOOTLOG)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_BOOTLOG)); return ret; } static inline long sc_panic(const char *key) { - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_PANIC)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_PANIC)); return ret; } static inline long __sc_test(const char *key, long a1, long a2, long a3) { - long ret = syscall(__NR_supercall, key, compact_cmd(key, SUPERCALL_TEST), a1, a2, a3); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_TEST), a1, a2, a3); return ret; } From 74a299dbfa3dd4a4217a61b2c49beaeb305b43da Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 30 Sep 2024 20:19:48 +0800 Subject: [PATCH 49/71] a --- user/supercall.h | 66 ++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/user/supercall.h b/user/supercall.h index b2850023..200a39ea 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -121,39 +121,39 @@ static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *pro return ret; } -/** - * @brief - * - * @param key - * @param gid group id - * @param did data id - * @param data - * @param dlen - * @return long - */ -static inline long sc_kstorage_write(const char *key, int gid, long did, void *data, int dlen) -{ - if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, dlen); - return ret; -} - -/** - * @brief - * - * @param key - * @param gid - * @param did - * @param out_data - * @param dlen - * @return long - */ -static inline long sc_kstorage_read(const char *key, int gid, long did, void *out_data, int dlen) -{ - if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, dlen); - return ret; -} +// /** +// * @brief +// * +// * @param key +// * @param gid group id +// * @param did data id +// * @param data +// * @param dlen +// * @return long +// */ +// static inline long sc_kstorage_write(const char *key, int gid, long did, void *data, int offset, int dlen) +// { +// if (!key || !key[0]) return -EINVAL; +// long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, dlen); +// return ret; +// } + +// /** +// * @brief +// * +// * @param key +// * @param gid +// * @param did +// * @param out_data +// * @param dlen +// * @return long +// */ +// static inline long sc_kstorage_read(const char *key, int gid, long did, void *out_data, int offset, int dlen) +// { +// if (!key || !key[0]) return -EINVAL; +// long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, dlen); +// return ret; +// } /** * @brief Grant su permission From f01a1f39499b633875cdd88d0731e0fdce319a7f Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 2 Oct 2024 08:51:46 +0800 Subject: [PATCH 50/71] a --- kernel/base/predata.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 1809a41b..3ea7fc82 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -29,10 +29,14 @@ static bool enable_root_key = false; int auth_superkey(const char *key) { int rc = 0; - rc = lib_strncmp(superkey, key, SUPER_KEY_LEN); - if (!rc) return rc; + for (int i = 0; i < SUPER_KEY_LEN; i++) { + if (key[i] && key[i] != superkey[i]) { + rc++; + } + } + if (!rc) goto out; - if (!enable_root_key) return rc; + if (!enable_root_key) goto out; BYTE hash[SHA256_BLOCK_SIZE]; SHA256_CTX ctx; @@ -49,7 +53,8 @@ int auth_superkey(const char *key) enable_root_key = false; } - return rc; +out: + return !!rc; } void reset_superkey(const char *key) From 03e9738542c828f3a5319e07ee7478d54c671551 Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 2 Oct 2024 08:55:16 +0800 Subject: [PATCH 51/71] a --- kernel/base/predata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 3ea7fc82..61e0812f 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -30,7 +30,7 @@ int auth_superkey(const char *key) { int rc = 0; for (int i = 0; i < SUPER_KEY_LEN; i++) { - if (key[i] && key[i] != superkey[i]) { + if (superkey[i] && key[i] != superkey[i]) { rc++; } } From 9d90bf044f1ff9128d3a5b062c1f5c5666b58114 Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 2 Oct 2024 09:00:51 +0800 Subject: [PATCH 52/71] a --- kernel/base/predata.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index 61e0812f..afb61943 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -29,10 +29,8 @@ static bool enable_root_key = false; int auth_superkey(const char *key) { int rc = 0; - for (int i = 0; i < SUPER_KEY_LEN; i++) { - if (superkey[i] && key[i] != superkey[i]) { - rc++; - } + for (int i = 0; superkey[i]; i++) { + rc |= (superkey[i] ^ key[i]); } if (!rc) goto out; From 67ab867e87969e71f2f2eac13f8fa0a620596492 Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 3 Oct 2024 09:59:17 +0800 Subject: [PATCH 53/71] add exclude supercall --- kernel/patch/common/sucompat.c | 10 +-- kernel/patch/common/supercall.c | 25 +++++++ kernel/patch/common/supercmd.c | 6 +- kernel/patch/include/sucompat.h | 4 +- user/supercall.h | 118 +++++++++++++++++++++++--------- 5 files changed, 119 insertions(+), 44 deletions(-) diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 13cfc4d4..b06c30f4 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -315,7 +315,7 @@ static void su_handler_arg1_ufilename_before(hook_fargs6_t *args, void *udata) } } -int set_su_mod_exclude(uid_t uid, int exclude) +int set_ap_mod_exclude(uid_t uid, int exclude) { int rc = 0; if (exclude) { @@ -325,16 +325,16 @@ int set_su_mod_exclude(uid_t uid, int exclude) } return rc; } -KP_EXPORT_SYMBOL(set_su_mod_exclude); +KP_EXPORT_SYMBOL(set_ap_mod_exclude); -int get_su_mod_exclude(uid_t uid) +int get_ap_mod_exclude(uid_t uid) { int exclude = 0; int rc = read_kstorage(exclude_kstorage_gid, uid, &exclude, 0, sizeof(exclude), false); - if (rc < 0) return false; + if (rc < 0) return 0; return exclude; } -KP_EXPORT_SYMBOL(get_su_mod_exclude); +KP_EXPORT_SYMBOL(get_ap_mod_exclude); int su_compat_init() { diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 0b358899..926c6d37 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -31,6 +31,7 @@ #include #include #include +#include #define MAX_KEY_LEN 128 @@ -230,6 +231,21 @@ static long call_su_set_allow_sctx(char *__user usctx) return set_all_allow_sctx(buf); } +static long call_kstorage_read(int gid, long did, void *out_data, int offset, int dlen) +{ + return read_kstorage(gid, did, out_data, offset, dlen, true); +} + +static long call_kstorage_write(int gid, long did, void *data, int offset, int dlen) +{ + return write_kstorage(gid, did, data, offset, dlen, true); +} + +static long call_kstorage_remove(int gid, long did) +{ + return remove_kstorage(gid, did); +} + static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3, long arg4) { switch (cmd) { @@ -268,6 +284,15 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3 return call_su_get_allow_sctx((char *__user)arg1, (int)arg2); case SUPERCALL_SU_SET_ALLOW_SCTX: return call_su_set_allow_sctx((char *__user)arg1); + + case SUPERCALL_KSTORAGE_READ: + return call_kstorage_read((int)arg1, (long)arg2, (void *)arg3, (int)((long)arg4 >> 32), (long)arg4 << 32 >> 32); + case SUPERCALL_KSTORAGE_WRITE: + return call_kstorage_write((int)arg1, (long)arg2, (void *)arg3, (int)((long)arg4 >> 32), + (long)arg4 << 32 >> 32); + case SUPERCALL_KSTORAGE_REMOVE: + return call_kstorage_remove((int)arg1, (long)arg2); + #ifdef ANDROID case SUPERCALL_SU_GET_SAFEMODE: return call_su_get_safemode(); diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index d5736425..1316c4bf 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -187,15 +187,15 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char return; } else { if (!carr[3]) { - int exclude = get_su_mod_exclude(uid); + int exclude = get_ap_mod_exclude(uid); sprintf(buffer, "%d", exclude); cmd_res->msg = buffer; } else { if (carr[3][0] == '0') { - set_su_mod_exclude(uid, 0); + set_ap_mod_exclude(uid, 0); cmd_res->msg = "0"; } else { - set_su_mod_exclude(uid, 1); + set_ap_mod_exclude(uid, 1); cmd_res->msg = "1"; } } diff --git a/kernel/patch/include/sucompat.h b/kernel/patch/include/sucompat.h index f4035b7a..0dc6a902 100644 --- a/kernel/patch/include/sucompat.h +++ b/kernel/patch/include/sucompat.h @@ -32,7 +32,7 @@ int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *profile); int su_reset_path(const char *path); const char *su_get_path(); -int get_su_mod_exclude(uid_t uid); -int set_su_mod_exclude(uid_t uid, int exclude); +int get_ap_mod_exclude(uid_t uid); +int set_ap_mod_exclude(uid_t uid, int exclude); #endif diff --git a/user/supercall.h b/user/supercall.h index 200a39ea..2484c4b9 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -121,39 +121,89 @@ static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *pro return ret; } -// /** -// * @brief -// * -// * @param key -// * @param gid group id -// * @param did data id -// * @param data -// * @param dlen -// * @return long -// */ -// static inline long sc_kstorage_write(const char *key, int gid, long did, void *data, int offset, int dlen) -// { -// if (!key || !key[0]) return -EINVAL; -// long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, dlen); -// return ret; -// } - -// /** -// * @brief -// * -// * @param key -// * @param gid -// * @param did -// * @param out_data -// * @param dlen -// * @return long -// */ -// static inline long sc_kstorage_read(const char *key, int gid, long did, void *out_data, int offset, int dlen) -// { -// if (!key || !key[0]) return -EINVAL; -// long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, dlen); -// return ret; -// } +/** + * @brief + * + * @param key + * @param gid group id + * @param did data id + * @param data + * @param dlen + * @return long + */ +static inline long sc_kstorage_write(const char *key, int gid, long did, void *data, int offset, int dlen) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, ((offset << 32) | dlen)); + return ret; +} + +/** + * @brief + * + * @param key + * @param gid + * @param did + * @param out_data + * @param dlen + * @return long + */ +static inline long sc_kstorage_read(const char *key, int gid, long did, void *out_data, int offset, int dlen) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, ((offset << 32) | dlen)); + return ret; +} + +/** + * @brief + * + * @param key + * @param gid + * @param did + * @return long + */ +static inline long sc_kstorage_remove(const char *key, int gid, long did) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_REMOVE), gid, did); + return ret; +} + + +/** + * @brief + * + * @param key + * @param uid + * @param exclude + * @return long + */ +static inline long sc_set_ap_mod_exclude(const char *key, uid_t uid, int exclude) +{ + if(exclude) { + return sc_kstorage_write(key, KSTORAGE_EXCLUDE_LIST_GROUP, uid, &exclude, 0, sizeof(exclude)); + } else { + return sc_kstorage_remove(key, SUPERCALL_KSTORAGE_REMOVE, uid, gid); + } +} + + +/** + * @brief + * + * @param key + * @param uid + * @param exclude + * @return long + */ +static inline int sc_get_ap_mod_exclude(const char *key, uid_t uid) +{ + int exclude = 0; + int rc = sc_kstorage_read(key, KSTORAGE_EXCLUDE_LIST_GROUP, uid, &exclude, 0, sizeof(exclude)); + if (rc < 0) return 0; + return exclude; +} /** * @brief Grant su permission @@ -238,7 +288,7 @@ static inline long sc_su_uid_profile(const char *key, uid_t uid, struct su_profi static inline long sc_su_get_path(const char *key, char *out_path, int path_len) { if (!key || !key[0]) return -EINVAL; - if (!out_path || out_path <= 0) return -EINVAL; + if (!out_path || path_len <= 0) return -EINVAL; long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_GET_PATH), out_path, path_len); return ret; } From 124f704dc9ff0278a51b6873b44d36ef0621707d Mon Sep 17 00:00:00 2001 From: bmax Date: Sat, 5 Oct 2024 12:08:08 +0800 Subject: [PATCH 54/71] add kstorage list interface, android exclude list interface --- kernel/patch/common/kstorage.c | 80 ++++++++++++++++++++++-------- kernel/patch/common/sucompat.c | 27 +++++++--- kernel/patch/common/supercall.c | 7 +++ kernel/patch/common/supercmd.c | 24 ++++++++- kernel/patch/include/kstorage.h | 4 +- kernel/patch/include/sucompat.h | 1 + kernel/patch/include/uapi/scdefs.h | 5 +- user/supercall.h | 24 +++++++-- 8 files changed, 136 insertions(+), 36 deletions(-) diff --git a/kernel/patch/common/kstorage.c b/kernel/patch/common/kstorage.c index bf50d39d..cbced6c2 100644 --- a/kernel/patch/common/kstorage.c +++ b/kernel/patch/common/kstorage.c @@ -19,23 +19,23 @@ #define KSTRORAGE_MAX_GROUP_NUM 4 // static atomic64_t used_max_group = ATOMIC_INIT(0); -static int used_max_group = 0; +static int used_max_group = -1; static struct list_head kstorage_groups[KSTRORAGE_MAX_GROUP_NUM]; static spinlock_t kstorage_glocks[KSTRORAGE_MAX_GROUP_NUM]; static int group_sizes[KSTRORAGE_MAX_GROUP_NUM] = { 0 }; static spinlock_t used_max_group_lock; -// static void reclaim_callback(struct rcu_head *rcu) -// { -// struct kstorage *ks = container_of(rcu, struct kstorage, rcu); -// kvfree(ks); -// } +static void reclaim_callback(struct rcu_head *rcu) +{ + struct kstorage *ks = container_of(rcu, struct kstorage, rcu); + kvfree(ks); +} int try_alloc_kstroage_group() { spin_lock(&used_max_group_lock); used_max_group++; - if (used_max_group >= KSTRORAGE_MAX_GROUP_NUM) return -1; + if (used_max_group < 0 || used_max_group >= KSTRORAGE_MAX_GROUP_NUM) return -1; spin_unlock(&used_max_group_lock); return used_max_group; } @@ -96,12 +96,13 @@ int write_kstorage(int gid, long did, void *data, int offset, int len, bool data rcu_read_unlock(); if (old) { - // if (async) { - // call_rcu(&old->rcu, reclaim_callback); - // } else { - synchronize_rcu(); - kvfree(old); - // } + bool async = true; + if (async) { + call_rcu(&old->rcu, reclaim_callback); + } else { + synchronize_rcu(); + kvfree(old); + } } return 0; } @@ -127,7 +128,7 @@ KP_EXPORT_SYMBOL(get_kstorage); int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata) { - if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return 0; + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return -ENOENT; int rc = 0; @@ -155,7 +156,10 @@ int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_ const struct kstorage *pos = get_kstorage(gid, did); - if (IS_ERR(pos)) return PTR_ERR(pos); + if (IS_ERR(pos)) { + rcu_read_unlock(); + return PTR_ERR(pos); + } int min_len = pos->dlen - offset > len ? len : pos->dlen - offset; @@ -176,6 +180,39 @@ int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_ } KP_EXPORT_SYMBOL(read_kstorage); +int list_kstorage_ids(int gid, long *ids, int idslen, bool data_is_user) +{ + if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return -ENOENT; + + int cnt = 0; + + struct list_head *head = &kstorage_groups[gid]; + struct kstorage *pos = 0; + + rcu_read_lock(); + + list_for_each_entry(pos, head, list) + { + if (cnt >= idslen) break; + + if (data_is_user) { + int cplen = compat_copy_to_user(ids + cnt, &pos->did, sizeof(pos->did)); + if (cplen <= 0) { + logkfd("compat_copy_to_user error: %d", cplen); + cnt = cplen; + } + } else { + memcpy(ids + cnt, &pos->did, sizeof(pos->did)); + } + cnt++; + } + + rcu_read_unlock(); + + return cnt; +} +KP_EXPORT_SYMBOL(list_kstorage_ids); + int remove_kstorage(int gid, long did) { int rc = -ENOENT; @@ -197,12 +234,13 @@ int remove_kstorage(int gid, long did) logkfi("%d %ld\n", gid, did); - // if (async) { - // call_rcu(&pos->rcu, reclaim_callback); - // } else { - synchronize_rcu(); - kvfree(pos); - // } + bool async = true; + if (async) { + call_rcu(&pos->rcu, reclaim_callback); + } else { + synchronize_rcu(); + kvfree(pos); + } return 0; } } diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index b06c30f4..9a00f10a 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -336,13 +336,32 @@ int get_ap_mod_exclude(uid_t uid) } KP_EXPORT_SYMBOL(get_ap_mod_exclude); +int list_ap_mod_exclude(uid_t *uids, int len) +{ + long ids[len]; + int cnt = list_kstorage_ids(exclude_kstorage_gid, ids, len, false); + for (int i = 0; i < len; i++) { + uids[i] = (uid_t)ids[i]; + } + return cnt; +} +KP_EXPORT_SYMBOL(list_ap_mod_exclude); + int su_compat_init() { current_su_path = default_su_path; + su_kstorage_gid = try_alloc_kstroage_group(); + if (su_kstorage_gid != KSTORAGE_SU_LIST_GROUP) return -ENOMEM; + + exclude_kstorage_gid = try_alloc_kstroage_group(); + if (exclude_kstorage_gid != KSTORAGE_EXCLUDE_LIST_GROUP) return -ENOMEM; + #ifdef ANDROID // default shell - if (!all_allow_sctx[0]) strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK); + if (!all_allow_sctx[0]) { + strcpy(all_allow_sctx, ALL_ALLOW_SCONTEXT_MAGISK); + } su_add_allow_uid(2000, 0, all_allow_sctx); su_add_allow_uid(0, 0, all_allow_sctx); #endif @@ -356,12 +375,6 @@ int su_compat_init() // if (!enable) return; - su_kstorage_gid = try_alloc_kstroage_group(); - if (su_kstorage_gid < 0) return -ENOMEM; - - exclude_kstorage_gid = try_alloc_kstroage_group(); - if (exclude_kstorage_gid < 0) return -ENOMEM; - rc = hook_syscalln(__NR_execve, 3, before_execve, 0, (void *)0); log_boot("hook __NR_execve rc: %d\n", rc); diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 926c6d37..5a6f5bc8 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -241,6 +241,11 @@ static long call_kstorage_write(int gid, long did, void *data, int offset, int d return write_kstorage(gid, did, data, offset, dlen, true); } +static long call_list_kstorage_ids(int gid, long *ids, int ids_len) +{ + return list_kstorage_ids(gid, ids, ids_len, false); +} + static long call_kstorage_remove(int gid, long did) { return remove_kstorage(gid, did); @@ -290,6 +295,8 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3 case SUPERCALL_KSTORAGE_WRITE: return call_kstorage_write((int)arg1, (long)arg2, (void *)arg3, (int)((long)arg4 >> 32), (long)arg4 << 32 >> 32); + case SUPERCALL_KSTORAGE_LIST_IDS: + return call_list_kstorage_ids((int)arg1, (long *)arg2, (int)arg3); case SUPERCALL_KSTORAGE_REMOVE: return call_kstorage_remove((int)arg1, (long)arg2); diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 1316c4bf..cf5c1439 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -81,7 +81,10 @@ static const char supercmd_help[] = " profile Get the profile of the uid configuration.\n" " path [PATH] Get or Reset current su path. The length of PATH must 2-127.\n" " sctx [SCONTEXT] Get or Reset current all allowed security context.\n" +#ifdef ANDROID + " exclude_list List all exclude UIDs.\n" " exclude [1|0] Get or Reset exclude policy for UID.\n" +#endif " event Report EVENT.\n" "\n" "The command below requires superkey authentication.\n" @@ -180,7 +183,9 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } else { cmd_res->msg = all_allow_sctx; } - } else if (!strcmp(sub_cmd, "exclude")) { + } +#ifdef ANDROID + else if (!strcmp(sub_cmd, "exclude")) { unsigned long long uid; if (!carr[2] || kstrtoull(carr[2], 10, &uid)) { cmd_res->err_msg = "invalid uid"; @@ -200,7 +205,22 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } } } - } else { + } else if (!strcmp(sub_cmd, "exclude_list")) { + uid_t uids[128]; + int offset = 0; + int cnt = list_ap_mod_exclude(uids, sizeof(uids) / sizeof(uids[0])); + if (cnt < 0) { + cmd_res->rc = cnt; + } else { + for (int i = 0; i < cnt; i++) { + offset += sprintf(buffer + offset, "%d\n", uids[i]); + }; + if (offset > 0) buffer[offset - 1] = '\0'; + cmd_res->msg = buffer; + } + } +#endif + else { cmd_res->err_msg = "invalid subcommand"; } } diff --git a/kernel/patch/include/kstorage.h b/kernel/patch/include/kstorage.h index b011c110..fca8c68a 100644 --- a/kernel/patch/include/kstorage.h +++ b/kernel/patch/include/kstorage.h @@ -27,7 +27,7 @@ int kstorage_group_size(int gid); int write_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user); -// must within rcu read lock +/// must within rcu read lock const struct kstorage *get_kstorage(int gid, long did); typedef int (*on_kstorage_cb)(struct kstorage *kstorage, void *udata); @@ -35,6 +35,8 @@ int on_each_kstorage_elem(int gid, on_kstorage_cb cb, void *udata); int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_is_user); +int list_kstorage_ids(int gid, long *ids, int idslen, bool data_is_user); + int remove_kstorage(int gid, long did); #endif \ No newline at end of file diff --git a/kernel/patch/include/sucompat.h b/kernel/patch/include/sucompat.h index 0dc6a902..f09a95e7 100644 --- a/kernel/patch/include/sucompat.h +++ b/kernel/patch/include/sucompat.h @@ -34,5 +34,6 @@ const char *su_get_path(); int get_ap_mod_exclude(uid_t uid); int set_ap_mod_exclude(uid_t uid, int exclude); +int list_ap_mod_exclude(uid_t *uids, int len); #endif diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 76291459..1752e761 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -50,8 +50,9 @@ struct kernel_storage #define SUPERCALL_KSTORAGE_ALLOC_GROUP 0x1040 #define SUPERCALL_KSTORAGE_WRITE 0x1041 #define SUPERCALL_KSTORAGE_READ 0x1042 -#define SUPERCALL_KSTORAGE_REMOVE 0x1043 -#define SUPERCALL_KSTORAGE_REMOVE_GROUP 0x1044 +#define SUPERCALL_KSTORAGE_LIST_IDS 0x1043 +#define SUPERCALL_KSTORAGE_REMOVE 0x1044 +#define SUPERCALL_KSTORAGE_REMOVE_GROUP 0x1045 #define KSTORAGE_SU_LIST_GROUP 0 #define KSTORAGE_EXCLUDE_LIST_GROUP 1 diff --git a/user/supercall.h b/user/supercall.h index 2484c4b9..89591411 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -134,7 +134,7 @@ static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *pro static inline long sc_kstorage_write(const char *key, int gid, long did, void *data, int offset, int dlen) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, ((offset << 32) | dlen)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, (((long)offset << 32) | dlen)); return ret; } @@ -151,10 +151,28 @@ static inline long sc_kstorage_write(const char *key, int gid, long did, void *d static inline long sc_kstorage_read(const char *key, int gid, long did, void *out_data, int offset, int dlen) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, ((offset << 32) | dlen)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, (((long)offset << 32) | dlen)); return ret; } + +/** + * @brief + * + * @param key + * @param gid + * @param ids + * @param ids_len + * @return long numbers of listed ids + */ +static inline long sc_kstorage_list_ids(const char *key, int gid, long *ids, int ids_len) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_LIST_IDS), gid, ids, ids_len); + return ret; +} + + /** * @brief * @@ -166,7 +184,7 @@ static inline long sc_kstorage_read(const char *key, int gid, long did, void *ou static inline long sc_kstorage_remove(const char *key, int gid, long did) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_REMOVE), gid, did); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_REMOVE), gid); return ret; } From bce85b14c042f1815aa6c8a6ec92467ecbe55b1e Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 6 Oct 2024 15:42:31 +0800 Subject: [PATCH 55/71] fix su list, opt user init --- kernel/patch/android/gen/user_init.c | 2 +- kernel/patch/android/user_init.sh | 5 ++++- kernel/patch/android/userd.c | 8 ++++---- kernel/patch/common/sucompat.c | 20 +++++++++++--------- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/kernel/patch/android/gen/user_init.c b/kernel/patch/android/gen/user_init.c index b625bf16..4dafabdc 100644 --- a/kernel/patch/android/gen/user_init.c +++ b/kernel/patch/android/gen/user_init.c @@ -1 +1 @@ -static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nLOG_FILE=\"/dev/user_init_\"\"$event\"\".log\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event \"before\"\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\") ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n $SUPERCMD su -Z $MAGISK_SCTX exec $APD_PATH uid-listener &\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event \"after\"\n}\n\nhandle\n"; +static const char user_init[] = "#!/bin/sh\n\nKPMS_DIR=\"/data/adb/ap/kpms/\"\nMAGISK_POLICY_PATH=\"/data/adb/ap/bin/magiskpolicy\"\nSUPERCMD=\"truncate\"\nMAGISK_SCTX=\"u:r:magisk:s0\"\nAPD_PATH=\"/data/adb/apd\"\nDEV_LOG_DIR=\"/dev/user_init_log/\"\n\nskey=\"$1\"\nevent=\"$2\"\n\nmkdir -p \"$DEV_LOG_DIR\"\n\nLOG_FILE=\"$DEV_LOG_DIR\"\"$event\"\n\nexec >>$LOG_FILE 2>&1\n\nset -x\n\nload_modules() {\n for dir in \"$KPMS_DIR/*\"; do\n if [ ! -d \"$dir\" ]; then continue; fi\n if [ -e \"$dir/disable\" ]; then continue; fi\n main_sh=\"$dir/main.sh\"\n if [ -e \"$main_sh\" ]; then\n touch \"$dir/disable\"\n echo \"loading $dir/main.sh ...\"\n . \"$main_sh\"\n rm -f \"$dir/disable\"\n else\n echo \"Error: $main_sh not found in $dir\"\n fi\n done\n}\n\nhandle() {\n $SUPERCMD $skey event $event \"before\"\n case \"$event\" in\n \"early-init\" | \"init\" | \"late-init\") ;;\n \"post-fs-data\")\n $MAGISK_POLICY_PATH --magisk --live\n load_modules $skey $event\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"services\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n ;;\n \"boot-completed\")\n $SUPERCMD $skey -Z $MAGISK_SCTX exec $APD_PATH -s $skey $event\n $SUPERCMD su -Z $MAGISK_SCTX exec $APD_PATH uid-listener &\n ;;\n *)\n echo \"unknown user_init event: $event\"\n ;;\n esac\n $SUPERCMD $skey event $event \"after\"\n}\n\nhandle\n"; diff --git a/kernel/patch/android/user_init.sh b/kernel/patch/android/user_init.sh index 3546e269..77fe51a5 100644 --- a/kernel/patch/android/user_init.sh +++ b/kernel/patch/android/user_init.sh @@ -5,11 +5,14 @@ MAGISK_POLICY_PATH="/data/adb/ap/bin/magiskpolicy" SUPERCMD="truncate" MAGISK_SCTX="u:r:magisk:s0" APD_PATH="/data/adb/apd" +DEV_LOG_DIR="/dev/user_init_log/" skey="$1" event="$2" -LOG_FILE="/dev/user_init_""$event"".log" +mkdir -p "$DEV_LOG_DIR" + +LOG_FILE="$DEV_LOG_DIR""$event" exec >>$LOG_FILE 2>&1 diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 2c20299c..a2597523 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -38,12 +38,12 @@ #define ADB_FLODER "/data/adb/" #define AP_DIR "/data/adb/ap/" +#define DEV_LOG_DIR "/dev/user_init_log/" #define AP_BIN_DIR AP_DIR "bin/" #define AP_LOG_DIR AP_DIR "log/" #define AP_MAGISKPOLICY_PATH AP_BIN_DIR "magiskpolicy" #define MAGISK_SCTX "u:r:magisk:s0" #define USER_INIT_SH_PATH "/dev/user_init.sh" -#define USER_INIT_LOG "/dev/user_init*.log" #include "gen/user_init.c" @@ -62,9 +62,9 @@ static const char user_rc_data[] = { // "on property:vold.decrypt=trigger_restart_framework\n" " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s services\n" "on property:sys.boot_completed=1\n" - // " rm " REPLACE_RC_FILE "\n" - // " rm " USER_INIT_SH_PATH "\n" - // " rm " USER_INIT_LOG "\n" + " rm " REPLACE_RC_FILE "\n" + " rm " USER_INIT_SH_PATH "\n" + " mv -f " DEV_LOG_DIR AP_LOG_DIR "\n" " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s boot-completed\n" "" }; diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 9a00f10a..638eb7ca 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -95,25 +95,27 @@ static int allow_uids_cb(struct kstorage *kstorage, void *udata) { int is_user; uid_t *out_uids; + int idx; int out_num; } *up = (typeof(up))udata; - struct su_profile *profile = (struct su_profile *)kstorage->data; + if (up->idx >= up->out_num) { + return -ENOBUFS; + } - int num = 0; + struct su_profile *profile = (struct su_profile *)kstorage->data; if (up->is_user) { - int cprc = compat_copy_to_user(up->out_uids + num, &profile->uid, sizeof(uid_t)); - logkfd("uid: %d\n", profile->uid); + int cprc = compat_copy_to_user(up->out_uids + up->idx, &profile->uid, sizeof(uid_t)); if (cprc <= 0) { logkfd("compat_copy_to_user error: %d", cprc); return cprc; } } else { - up->out_uids[num] = profile->uid; + up->out_uids[up->idx] = profile->uid; } - num++; + up->idx++; return 0; } @@ -125,8 +127,9 @@ int su_allow_uids(int is_user, uid_t *out_uids, int out_num) { int iu; uid_t *up; - int un; - } udata = { is_user, out_uids, out_num }; + int idx; + int out_num; + } udata = { is_user, out_uids, 0, out_num }; on_each_kstorage_elem(su_kstorage_gid, allow_uids_cb, &udata); return rc; } @@ -150,7 +153,6 @@ int su_allow_uid_profile(int is_user, uid_t uid, struct su_profile *out_profile) logkfd("compat_copy_to_user error: %d", rc); goto out; } - logkfd("%d %d %s\n", profile->uid, profile->to_uid, profile->scontext); } else { memcpy(out_profile, profile, sizeof(struct su_profile)); } From f5766807a98fea1a503b481e8f93e44dbff8b916 Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 6 Oct 2024 19:38:09 +0800 Subject: [PATCH 56/71] fix allow uids --- kernel/patch/common/sucompat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 638eb7ca..5d4f9173 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -122,7 +122,6 @@ static int allow_uids_cb(struct kstorage *kstorage, void *udata) int su_allow_uids(int is_user, uid_t *out_uids, int out_num) { - int rc = 0; struct { int iu; @@ -130,8 +129,10 @@ int su_allow_uids(int is_user, uid_t *out_uids, int out_num) int idx; int out_num; } udata = { is_user, out_uids, 0, out_num }; + on_each_kstorage_elem(su_kstorage_gid, allow_uids_cb, &udata); - return rc; + + return udata.idx; } KP_EXPORT_SYMBOL(su_allow_uids); From 13af9375a1c871ff1754522bedbd9b65c2fe37ad Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 7 Oct 2024 09:17:56 +0800 Subject: [PATCH 57/71] fix su compat permission check --- kernel/patch/common/kstorage.c | 12 +++--------- kernel/patch/common/sucompat.c | 7 ++++++- kernel/patch/common/supercmd.c | 10 +++++----- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/kernel/patch/common/kstorage.c b/kernel/patch/common/kstorage.c index cbced6c2..18912a49 100644 --- a/kernel/patch/common/kstorage.c +++ b/kernel/patch/common/kstorage.c @@ -85,11 +85,9 @@ int write_kstorage(int gid, long did, void *data, int offset, int len, bool data spin_lock(lock); if (old) { // update list_replace_rcu(&old->list, &new->list); - logkfi("update %d %d\n", gid, did); } else { // add new one list_add_rcu(&new->list, head); group_sizes[gid]++; - logkfi("new %d %d\n", gid, did); } spin_unlock(lock); @@ -165,10 +163,8 @@ int read_kstorage(int gid, long did, void *data, int offset, int len, bool data_ if (data_is_user) { int cplen = compat_copy_to_user(data, pos->data + offset, min_len); - logkfd("%d %ld %d\n", gid, did, pos->dlen); - if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); + logkfe("compat_copy_to_user error: %d", cplen); rc = cplen; } } else { @@ -198,7 +194,7 @@ int list_kstorage_ids(int gid, long *ids, int idslen, bool data_is_user) if (data_is_user) { int cplen = compat_copy_to_user(ids + cnt, &pos->did, sizeof(pos->did)); if (cplen <= 0) { - logkfd("compat_copy_to_user error: %d", cplen); + logkfe("compat_copy_to_user error: %d", cplen); cnt = cplen; } } else { @@ -222,7 +218,7 @@ int remove_kstorage(int gid, long did) spinlock_t *lock = &kstorage_glocks[gid]; struct kstorage *pos = 0; - spin_lock(&kstorage_glocks[gid]); + spin_lock(lock); list_for_each_entry(pos, head, list) { @@ -232,8 +228,6 @@ int remove_kstorage(int gid, long did) group_sizes[did]--; - logkfi("%d %ld\n", gid, did); - bool async = true; if (async) { call_rcu(&pos->rcu, reclaim_callback); diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index 5d4f9173..97c484f0 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -54,10 +54,15 @@ static int exclude_kstorage_gid = -1; int is_su_allow_uid(uid_t uid) { + int rc = 0; rcu_read_lock(); const struct kstorage *ks = get_kstorage(su_kstorage_gid, uid); + if (IS_ERR_OR_NULL(ks) || ks->dlen <= 0) goto out; + struct su_profile *profile = (struct su_profile *)ks->data; - int rc = profile != 0; + rc = profile->uid == uid; + +out: rcu_read_unlock(); return rc; } diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index cf5c1439..8c95e26a 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -143,11 +143,10 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char sprintf(buffer, "%d", num); cmd_res->msg = buffer; } else if (!strcmp(sub_cmd, "list")) { - int num = su_allow_uid_nums(); - uid_t uids[num]; // stack overflow + uid_t uids[128]; // default max size 128 int offset = 0; - su_allow_uids(0, uids, num); - + buffer[0] = '\0'; + int num = su_allow_uids(0, uids, sizeof(uids) / sizeof(uids[0])); for (int i = 0; i < num; i++) { offset += sprintf(buffer + offset, "%d\n", uids[i]); }; @@ -208,6 +207,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } else if (!strcmp(sub_cmd, "exclude_list")) { uid_t uids[128]; int offset = 0; + buffer[0] = '\0'; int cnt = list_ap_mod_exclude(uids, sizeof(uids) / sizeof(uids[0])); if (cnt < 0) { cmd_res->rc = cnt; @@ -396,7 +396,7 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) strncpy(profile.scontext, parr[pi++], sizeof(profile.scontext) - 1); profile.scontext[sizeof(profile.scontext) - 1] = '\0'; } else { - supercmd_echo(u_filename_p, uargv, &sp, "supercmd error: invalid scontext"); + supercmd_echo(u_filename_p, uargv, &sp, "supercmd error: invalid scontext\n"); goto free; } break; From 9ba7e3d1973c42ddef42464e14ff4c14c07f4758 Mon Sep 17 00:00:00 2001 From: bmax Date: Wed, 23 Oct 2024 20:29:00 +0800 Subject: [PATCH 58/71] fix and opt: kallsyms_marker --- tools/kallsym.c | 60 +++++++++++++------------------------------------ tools/kallsym.h | 3 +++ 2 files changed, 19 insertions(+), 44 deletions(-) diff --git a/tools/kallsym.c b/tools/kallsym.c index 8717bb27..680210a5 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -187,15 +187,12 @@ static int find_token_index(kallsym_t *info, char *img, int32_t imglen) static int get_markers_elem_size(kallsym_t *info) { - /* - Before 4.20, type of kallsyms_markers is PTR which - depends on macro BITS_PER_LONG. When BITS_PER_LONG is 64, PTR is .quad (8 - bytes), otherwise .long (4bytes). Since 4.20, type of kallsyms_markers is - .long (4 bytes) - */ + if (info->kallsyms_markers_elem_size) return info->kallsyms_markers_elem_size; + int32_t elem_size = info->asm_long_size; if (info->version.major < 4 || (info->version.major == 4 && info->version.minor < 20)) elem_size = info->asm_PTR_size; + return elem_size; } @@ -469,48 +466,20 @@ static int find_num_syms(kallsym_t *info, char *img, int32_t imglen) return 0; } -static int find_markers_1(kallsym_t *info, char *img, int32_t imglen) +static int find_markers_internal(kallsym_t *info, char *img, int32_t imglen, int32_t elem_size) { - int32_t elem_size = get_markers_elem_size(info); - int32_t cand = info->kallsyms_token_table_offset - elem_size; - int64_t marker; - for (;; cand -= elem_size) { - marker = int_unpack(img + cand, elem_size, info->is_be); - if (marker) break; - } - int32_t marker_end = cand + elem_size; - int64_t last_marker = 0x7fffffff; - for (;; cand -= elem_size) { - marker = int_unpack(img + cand, elem_size, info->is_be); - if (!marker || last_marker <= marker) break; - last_marker = marker; - } - int32_t marker_num = (marker_end - cand) / elem_size; - if (marker || marker_num < KSYM_MIN_MARKER) { - tools_loge("find kallsyms_markers error\n"); - return -1; - } - info->kallsyms_markers_offset = cand; - info->_marker_num = marker_num; - tools_logi("kallsyms_markers range: [0x%08x, 0x%08x), count: 0x%08x\n", cand, marker_end, marker_num); - return 0; -} + int32_t cand = info->kallsyms_token_table_offset; -static int find_markers_2(kallsym_t *info, char *img, int32_t imglen) -{ - int32_t elem_size = get_markers_elem_size(info); - int32_t cand = info->kallsyms_token_table_offset - KSYM_MIN_MARKER * elem_size; - - int64_t marker, last_marker = 0x7fffffff; + int64_t marker, last_marker = imglen; int count = 0; - while (cand > 0x1000) { + while (cand > 0x10000) { marker = int_unpack(img + cand, elem_size, info->is_be); if (last_marker > marker) { count++; if (!marker && count > KSYM_MIN_MARKER) break; } else { count = 0; - last_marker = 0x7fffffff; + last_marker = imglen; } last_marker = marker; @@ -525,17 +494,20 @@ static int find_markers_2(kallsym_t *info, char *img, int32_t imglen) int32_t marker_end = cand + count * elem_size + elem_size; info->kallsyms_markers_offset = cand; info->_marker_num = count; + info->kallsyms_markers_elem_size = elem_size; tools_logi("kallsyms_markers range: [0x%08x, 0x%08x), count: 0x%08x\n", cand, marker_end, count); return 0; } -static inline int find_markers(kallsym_t *info, char *img, int32_t imglen) +static int find_markers(kallsym_t *info, char *img, int32_t imglen) { - // todo: remove one - int rc = find_markers_1(info, img, imglen); - if (!rc) return rc; - return find_markers_2(info, img, imglen); + int32_t elem_size = get_markers_elem_size(info); + int rc = find_markers_internal(info, img, imglen, elem_size); + if (rc && elem_size == 8) { + return find_markers_internal(info, img, imglen, 4); + } + return rc; } static int decompress_symbol_name(kallsym_t *info, char *img, int32_t *pos_to_next, char *out_type, char *out_symbol) diff --git a/tools/kallsym.h b/tools/kallsym.h index 22d0e05c..d535359d 100644 --- a/tools/kallsym.h +++ b/tools/kallsym.h @@ -14,6 +14,8 @@ #define KSYM_TOKEN_NUMS 256 #define KSYM_SYMBOL_LEN 512 +#define KSYM_MAX_SYMS 1000000 + #define KSYM_MIN_NEQ_SYMS 25600 #define KSYM_MIN_MARKER (KSYM_MIN_NEQ_SYMS / 256) #define KSYM_FIND_NAMES_USED_MARKER 5 @@ -84,6 +86,7 @@ typedef struct char *kallsyms_token_table[KSYM_TOKEN_NUMS]; int32_t asm_long_size; int32_t asm_PTR_size; + int32_t kallsyms_markers_elem_size; int32_t kallsyms_num_syms; int32_t has_relative_base; From 4a628730b77544cd4605f309301780ebb667635e Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 24 Oct 2024 09:58:33 +0800 Subject: [PATCH 59/71] fix patch option --root-skey --- tools/kptools.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/kptools.c b/tools/kptools.c index 99f60c2b..560c9e9d 100644 --- a/tools/kptools.c +++ b/tools/kptools.c @@ -51,7 +51,7 @@ void print_usage(char **argv) " -i, --image PATH Kernel image path.\n" " -k, --kpimg PATH KernelPatch image path.\n" " -s, --skey KEY Set the superkey and save it directly in the boot.img.\n" - " -S, --root-skey KEY Set the root-superkey that uses hash verification, and the superkey can be changed dynamically.\n" + " -S, --root-skey KEY Set the root-superkey useing hash verification, and the superkey can be changed dynamically.\n" " -o, --out PATH Patched image path.\n" " -a --addition KEY=VALUE Add additional information.\n" @@ -87,7 +87,7 @@ int main(int argc, char *argv[]) { "image", required_argument, NULL, 'i' }, { "kpimg", required_argument, NULL, 'k' }, { "skey", required_argument, NULL, 's' }, - { "skey-hash", required_argument, NULL, 'S' }, + { "root-skey", required_argument, NULL, 'S' }, { "out", required_argument, NULL, 'o' }, { "addition", required_argument, NULL, 'a' }, From 50e6a1567b13da2c676fe46675c7b8111ed87998 Mon Sep 17 00:00:00 2001 From: 1f2003d5 <2652609017@qq.com> Date: Sat, 26 Oct 2024 22:46:28 +0800 Subject: [PATCH 60/71] userd: Fix `boot-completed` event trigger (#134) Signed-off-by: GarfieldHan <2652609017@qq.com> --- kernel/patch/android/userd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index a2597523..8dc1538b 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -62,10 +62,10 @@ static const char user_rc_data[] = { // "on property:vold.decrypt=trigger_restart_framework\n" " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s services\n" "on property:sys.boot_completed=1\n" + " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s boot-completed\n" " rm " REPLACE_RC_FILE "\n" " rm " USER_INIT_SH_PATH "\n" " mv -f " DEV_LOG_DIR AP_LOG_DIR "\n" - " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s boot-completed\n" "" }; @@ -379,4 +379,4 @@ int android_user_init() } return ret; -} \ No newline at end of file +} From 6a55d8c36544285b766a77e239cdb425e13fc36b Mon Sep 17 00:00:00 2001 From: bmax Date: Sun, 27 Oct 2024 20:56:31 +0800 Subject: [PATCH 61/71] add buildtime --- kernel/base/predata.c | 5 +++++ kernel/base/start.c | 16 +++++++--------- kernel/include/kallsyms.h | 2 -- kernel/include/predata.h | 2 ++ kernel/patch/common/supercall.c | 13 ++++++++++++- kernel/patch/common/supercmd.c | 6 +++++- kernel/patch/include/uapi/scdefs.h | 1 + user/supercall.h | 15 +++++++++++++++ 8 files changed, 47 insertions(+), 13 deletions(-) diff --git a/kernel/base/predata.c b/kernel/base/predata.c index afb61943..35f50494 100644 --- a/kernel/base/predata.c +++ b/kernel/base/predata.c @@ -77,6 +77,11 @@ const char *get_superkey() return superkey; } +const char *get_build_time() +{ + return setup_header->compile_time; +} + int on_each_extra_item(int (*callback)(const patch_extra_item_t *extra, const char *arg, const void *con, void *udata), void *udata) { diff --git a/kernel/base/start.c b/kernel/base/start.c index 4ba1c03b..5784755e 100644 --- a/kernel/base/start.c +++ b/kernel/base/start.c @@ -27,6 +27,9 @@ start_preset_t start_preset __attribute__((section(".start.data"))); +setup_header_t *setup_header = 0; +KP_EXPORT_SYMBOL(setup_header); + int (*kallsyms_on_each_symbol)(int (*fn)(void *data, const char *name, struct module *module, unsigned long addr), void *data) = 0; KP_EXPORT_SYMBOL(kallsyms_on_each_symbol); @@ -34,10 +37,6 @@ KP_EXPORT_SYMBOL(kallsyms_on_each_symbol); unsigned long (*kallsyms_lookup_name)(const char *name) = 0; KP_EXPORT_SYMBOL(kallsyms_lookup_name); -int (*lookup_symbol_attrs)(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, - char *name) = 0; -KP_EXPORT_SYMBOL(lookup_symbol_attrs); - void (*printk)(const char *fmt, ...) = 0; KP_EXPORT_SYMBOL(printk); @@ -396,23 +395,22 @@ static void start_init(uint64_t kimage_voff, uint64_t linear_voff) log_boot(KERNEL_PATCH_BANNER); endian = *(unsigned char *)&(uint16_t){ 1 } ? little : big; - setup_header_t *header = &start_preset.header; + setup_header = &start_preset.header; kver = VERSION(start_preset.kernel_version.major, start_preset.kernel_version.minor, start_preset.kernel_version.patch); - kpver = VERSION(header->kp_version.major, header->kp_version.minor, header->kp_version.patch); + kpver = VERSION(setup_header->kp_version.major, setup_header->kp_version.minor, setup_header->kp_version.patch); log_boot("Kernel pa: %llx\n", kernel_pa); log_boot("Kernel va: %llx\n", kernel_va); log_boot("Kernel Version: %x\n", kver); log_boot("KernelPatch Version: %x\n", kpver); - log_boot("KernelPatch Config: %llx\n", header->config_flags); - log_boot("KernelPatch Compile Time: %s\n", (uint64_t)header->compile_time); + log_boot("KernelPatch Config: %llx\n", setup_header->config_flags); + log_boot("KernelPatch Compile Time: %s\n", (uint64_t)setup_header->compile_time); log_boot("KernelPatch link base: %llx, runtime base: %llx\n", link_base_addr, runtime_base_addr); kallsyms_on_each_symbol = (typeof(kallsyms_on_each_symbol))kallsyms_lookup_name("kallsyms_on_each_symbol"); - lookup_symbol_attrs = (typeof(lookup_symbol_attrs))kallsyms_lookup_name("lookup_symbol_attrs"); uint64_t tcr_el1; asm volatile("mrs %0, tcr_el1" : "=r"(tcr_el1)); diff --git a/kernel/include/kallsyms.h b/kernel/include/kallsyms.h index 7e75e672..049da1a1 100644 --- a/kernel/include/kallsyms.h +++ b/kernel/include/kallsyms.h @@ -7,7 +7,5 @@ struct module; extern int (*kallsyms_on_each_symbol)(int (*fn)(void *, const char *, struct module *, unsigned long), void *data); extern unsigned long (*kallsyms_lookup_name)(const char *name); -extern int (*lookup_symbol_attrs)(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, - char *name); #endif \ No newline at end of file diff --git a/kernel/include/predata.h b/kernel/include/predata.h index 136b77eb..15683937 100644 --- a/kernel/include/predata.h +++ b/kernel/include/predata.h @@ -10,11 +10,13 @@ #include extern struct patch_config *patch_config; +extern setup_header_t *setup_header; int auth_superkey(const char *key); void reset_superkey(const char *key); void enable_auth_root_key(bool enable); const char *get_superkey(); +const char *get_build_time(); uint64_t rand_next(); int on_each_extra_item(int (*callback)(const patch_extra_item_t *extra, const char *arg, const void *data, void *udata), diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 5a6f5bc8..0ac5f37a 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -64,6 +64,15 @@ static long call_klog(const char __user *arg1) return 0; } +static long call_buildtime(char __user *out_buildtime, int u_len) +{ + const char *buildtime = get_build_time(); + int len = strlen(buildtime); + if (len >= u_len) return -ENOMEM; + int rc = compat_copy_to_user(out_buildtime, buildtime, len + 1); + return rc; +} + static long call_kpm_load(const char __user *arg1, const char *__user arg2, void *__user reserved) { char path[1024], args[KPM_ARGS_LEN]; @@ -144,7 +153,7 @@ static long call_skey_get(char *__user out_key, int out_len) const char *key = get_superkey(); int klen = strlen(key); if (klen >= out_len) return -ENOMEM; - int rc = compat_copy_to_user(out_key, get_superkey(), klen + 1); + int rc = compat_copy_to_user(out_key, key, klen + 1); return rc; } @@ -263,6 +272,8 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3 return kpver; case SUPERCALL_KERNEL_VER: return kver; + case SUPERCALL_BUILD_TIME: + return call_buildtime((char *__user)arg1, (int)arg2); } switch (cmd) { diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 8c95e26a..122bff39 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -65,7 +65,8 @@ static const char supercmd_help[] = "\n" "Command:\n" " help: Print this help message.\n" - " version: Print Kernel version and KernelPatch version,\n " + " version: Print Kernel version and KernelPatch version.\n " + " buildtime: Print KernelPatch build time.\n " " eg: 50a0a,a06 means kernel version 5.10.10, KernelPatch version 0.10.6.\n" " -c [...]: Pass a single COMMAND to the default shell.\n" " exec [...]: Execute command with full PATH.\n" @@ -446,6 +447,9 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) } else if (!strcmp("version", cmd)) { supercmd_echo(u_filename_p, uargv, &sp, "%x,%x", kver, kpver); goto free; + } else if (!strcmp("buildtime", cmd)) { + cmd_res.msg = get_build_time(); + goto echo; } else if (!strcmp("sumgr", cmd)) { handle_cmd_sumgr(u_filename_p, carr, buffer, sizeof(buffer), &cmd_res); } else if (!strcmp("event", cmd)) { diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index 1752e761..eb5dc8ba 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -25,6 +25,7 @@ static inline long hash_key(const char *key) #define SUPERCALL_KERNELPATCH_VER 0x1008 #define SUPERCALL_KERNEL_VER 0x1009 +#define SUPERCALL_BUILD_TIME 0x1010 #define SUPERCALL_SKEY_GET 0x100a #define SUPERCALL_SKEY_SET 0x100b diff --git a/user/supercall.h b/user/supercall.h index 89591411..a0d69059 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -89,6 +89,21 @@ static inline uint32_t sc_k_ver(const char *key) return (uint32_t)ret; } +/** + * @brief KernelPatch build time + * + * @param key : superkey or 'su' string if caller uid is su allowed + * @param out_buildtime + * @param outlen + * @return long + */ +static inline long sc_k_ver(const char *key, char *out_buildtime, int outlen) +{ + if (!key || !key[0]) return -EINVAL; + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_BUILD_TIME, out_buildtime, outlen)); + return (uint32_t)ret; +} + /** * @brief Substitute user of current thread * From 77b26e972b3ab9e3fd5f3bb6c3ba102e41bfa518 Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 28 Oct 2024 18:51:18 +0800 Subject: [PATCH 62/71] fix, typo --- user/supercall.h | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/user/supercall.h b/user/supercall.h index a0d69059..f27d539d 100644 --- a/user/supercall.h +++ b/user/supercall.h @@ -97,7 +97,7 @@ static inline uint32_t sc_k_ver(const char *key) * @param outlen * @return long */ -static inline long sc_k_ver(const char *key, char *out_buildtime, int outlen) +static inline long sc_kp_buildtime(const char *key, char *out_buildtime, int outlen) { if (!key || !key[0]) return -EINVAL; long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_BUILD_TIME, out_buildtime, outlen)); @@ -149,7 +149,8 @@ static inline long sc_su_task(const char *key, pid_t tid, struct su_profile *pro static inline long sc_kstorage_write(const char *key, int gid, long did, void *data, int offset, int dlen) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, (((long)offset << 32) | dlen)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_WRITE), gid, did, data, + (((long)offset << 32) | dlen)); return ret; } @@ -166,11 +167,11 @@ static inline long sc_kstorage_write(const char *key, int gid, long did, void *d static inline long sc_kstorage_read(const char *key, int gid, long did, void *out_data, int offset, int dlen) { if (!key || !key[0]) return -EINVAL; - long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, (((long)offset << 32) | dlen)); + long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_KSTORAGE_READ), gid, did, out_data, + (((long)offset << 32) | dlen)); return ret; } - /** * @brief * @@ -187,7 +188,6 @@ static inline long sc_kstorage_list_ids(const char *key, int gid, long *ids, int return ret; } - /** * @brief * @@ -203,7 +203,6 @@ static inline long sc_kstorage_remove(const char *key, int gid, long did) return ret; } - /** * @brief * @@ -214,14 +213,13 @@ static inline long sc_kstorage_remove(const char *key, int gid, long did) */ static inline long sc_set_ap_mod_exclude(const char *key, uid_t uid, int exclude) { - if(exclude) { + if (exclude) { return sc_kstorage_write(key, KSTORAGE_EXCLUDE_LIST_GROUP, uid, &exclude, 0, sizeof(exclude)); } else { return sc_kstorage_remove(key, SUPERCALL_KSTORAGE_REMOVE, uid, gid); } } - /** * @brief * @@ -528,7 +526,6 @@ static inline long sc_su_get_safemode(const char *key) return syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_SU_GET_SAFEMODE)); } - static inline long sc_bootlog(const char *key) { long ret = syscall(__NR_supercall, key, ver_and_cmd(key, SUPERCALL_BOOTLOG)); From e70b5298368059b93849825cf9f4a74f1a001075 Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 28 Oct 2024 18:55:48 +0800 Subject: [PATCH 63/71] format --- kernel/patch/common/supercmd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 122bff39..059503bc 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -65,7 +65,7 @@ static const char supercmd_help[] = "\n" "Command:\n" " help: Print this help message.\n" - " version: Print Kernel version and KernelPatch version.\n " + " version: Print Kernel version and KernelPatch version.\n" " buildtime: Print KernelPatch build time.\n " " eg: 50a0a,a06 means kernel version 5.10.10, KernelPatch version 0.10.6.\n" " -c [...]: Pass a single COMMAND to the default shell.\n" From 82a2849bf83d629d7882d3c15196b3d76e95f9c9 Mon Sep 17 00:00:00 2001 From: bmax Date: Mon, 28 Oct 2024 19:17:24 +0800 Subject: [PATCH 64/71] fix: duplicate supercall id --- kernel/patch/include/uapi/scdefs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/patch/include/uapi/scdefs.h b/kernel/patch/include/uapi/scdefs.h index eb5dc8ba..0cd22f0c 100644 --- a/kernel/patch/include/uapi/scdefs.h +++ b/kernel/patch/include/uapi/scdefs.h @@ -23,9 +23,9 @@ static inline long hash_key(const char *key) #define SUPERCALL_HELLO 0x1000 #define SUPERCALL_KLOG 0x1004 +#define SUPERCALL_BUILD_TIME 0x1007 #define SUPERCALL_KERNELPATCH_VER 0x1008 #define SUPERCALL_KERNEL_VER 0x1009 -#define SUPERCALL_BUILD_TIME 0x1010 #define SUPERCALL_SKEY_GET 0x100a #define SUPERCALL_SKEY_SET 0x100b From 7b0295d7a5021ae62beae5eb590c6ddb1fb9f012 Mon Sep 17 00:00:00 2001 From: Admire <43035036+Admirepowered@users.noreply.github.com> Date: Fri, 15 Nov 2024 10:20:14 +0800 Subject: [PATCH 65/71] kptools: add dump iconfig (#140) Signed-off-by: SakuraKyuo --- .github/workflows/build.yml | 48 +------------------------ tools/CMakeLists.txt | 8 ++++- tools/Makefile | 4 +-- tools/kallsym.c | 72 +++++++++++++++++++++++++++++++++++++ tools/kallsym.h | 1 + tools/kptools.c | 8 +++-- tools/patch.c | 14 ++++++++ tools/patch.h | 1 + 8 files changed, 104 insertions(+), 52 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a667ca7c..4bde6df0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -253,6 +253,7 @@ jobs: install: >- msys/make msys/gcc + msys/zlib-devel - name: Copyfile shell: pwsh run: | @@ -281,53 +282,6 @@ jobs: allowUpdates: true replacesArtifacts: true - Build-kptools-windows-llvm: - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Check out - uses: actions/checkout@v3 - - name: Install mingw32 cross toolchains - run: | - MINGW_LLVM_URL="https://github.com/mstorsjo/llvm-mingw/releases/download/20231128/llvm-mingw-20231128-msvcrt-ubuntu-20.04-x86_64.tar.xz" - mkdir -p $HOME/mingw-llvm - wget $MINGW_LLVM_URL -O $HOME/mingw-llvm/llvm.tar.xz - cd $HOME/mingw-llvm - tar -xvf llvm.tar.xz --strip-components 1 - - name: Generate version - id: parse_version - run: | - MAJOR=$(grep '#define MAJOR' version | awk '{print $3}') - MINOR=$(grep '#define MINOR' version | awk '{print $3}') - PATCH=$(grep '#define PATCH' version | awk '{print $3}') - VERSION="$MAJOR.$MINOR.$PATCH" - echo "Generated Version: $VERSION" - echo "VERSION=$VERSION" >> $GITHUB_OUTPUT - - name: Build kptools - run: | - export PATH="$HOME/mingw-llvm/bin:$PATH" - export ANDROID=1 - ABIS="x86_64 i686 aarch64 armv7" - for i in $ABIS; do - make -C kernel hdr TARGET_COMPILE=placeholder - echo "- Compiling kptools-$i-win.exe" - make -C tools CC=$i-w64-mingw32-clang - mv tools/kptools.exe kptools-$i-win.exe - make -C tools clean - done - 7za a kptools-llvm-win.zip -tZIP *.exe - - name: Release - uses: ncipollo/release-action@v1.12.0 - with: - token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ steps.parse_version.outputs.VERSION }} - artifacts: | - kptools-llvm-win.zip - allowUpdates: true - replacesArtifacts: true - omitBodyDuringUpdate: true - Build-kptools-mac: runs-on: macos-latest permissions: diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index d6ddfc7b..f998fd87 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -19,4 +19,10 @@ set(SOURCES add_executable( kptools ${SOURCES} -) \ No newline at end of file +) + +find_package(ZLIB REQUIRED) + +target_link_libraries(kptools PRIVATE ${ZLIB_LIBRARIES}) + +target_include_directories(kptools PRIVATE ${ZLIB_INCLUDE_DIRS}) \ No newline at end of file diff --git a/tools/Makefile b/tools/Makefile index 4218ac6c..a065542b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,6 +1,6 @@ CFLAGS = -std=c11 -Wall -Wextra -Wno-unused -Wno-unused-parameter - +LDFLAGS = -lz ifdef DEBUG CFLAGS += -DDEBUG -g endif @@ -13,7 +13,7 @@ all: kptools .PHONY: kptools kptools: ${objs} - ${CC} -o $@ $^ + ${CC} -o $@ $^ $(LDFLAGS) %.o : %.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ diff --git a/tools/kallsym.c b/tools/kallsym.c index 680210a5..2a09dc0c 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -17,6 +17,10 @@ #include "insn.h" #include "common.h" +#define IKCFG_ST "IKCFG_ST" +#define IKCFG_ED "IKCFG_ED" +#include "zlib.h" + #ifdef _WIN32 #include static void *memmem(const void *haystack, size_t haystack_len, const void *const needle, const size_t needle_len) @@ -961,6 +965,74 @@ int dump_all_symbols(kallsym_t *info, char *img) } return 0; } +int decompress_data(const unsigned char *compressed_data, size_t compressed_size) { + FILE *temp = fopen("temp.gz", "wb"); + if (!temp) { + fprintf(stderr, "Failed to create temp file\n"); + return -1; + } + + fwrite(compressed_data, 1, compressed_size, temp); + fclose(temp); + + gzFile gz = gzopen("temp.gz", "rb"); + if (!gz) { + fprintf(stderr, "Failed to open temp file for decompression\n"); + return -1; + } + + char buffer[1024]; + int bytes_read; + while ((bytes_read = gzread(gz, buffer, sizeof(buffer))) > 0) { + fwrite(buffer, 1, bytes_read, stdout); + } + + gzclose(gz); + return 0; +} + +int dump_all_ikconfig(char *img, int32_t imglen) +{ + + char *pos_start = memmem(img, imglen, IKCFG_ST, strlen(IKCFG_ST)); + if (pos_start == NULL) { + fprintf(stderr, "Cannot find kernel config start (IKCFG_ST).\n"); + return 1; + } + size_t kcfg_start = pos_start - img + 8; + + // 查找 "IKCFG_ED" + char *pos_end = memmem(img, imglen, IKCFG_ED, strlen(IKCFG_ED)); + if (pos_end == NULL) { + fprintf(stderr, "Cannot find kernel config end (IKCFG_ED).\n"); + return 1; + } + size_t kcfg_end = pos_end - img - 1; + size_t kcfg_bytes = kcfg_end - kcfg_start + 1; + + printf("Kernel config start: %zu, end: %zu, bytes: %zu\n", kcfg_start, kcfg_end, kcfg_bytes); + + + unsigned char *extracted_data = (unsigned char *)malloc(kcfg_bytes); + if (!extracted_data) { + fprintf(stderr, "Memory allocation for extracted data failed.\n"); + return 1; + } + + memcpy(extracted_data, img + kcfg_start, kcfg_bytes); + + + + int ret = decompress_data(extracted_data, kcfg_bytes); + + + + + free(extracted_data); + + + return 0; +} int on_each_symbol(kallsym_t *info, char *img, void *userdata, int32_t (*fn)(int32_t index, char type, const char *symbol, int32_t offset, void *userdata)) diff --git a/tools/kallsym.h b/tools/kallsym.h index d535359d..28e9fe05 100644 --- a/tools/kallsym.h +++ b/tools/kallsym.h @@ -119,6 +119,7 @@ typedef struct int analyze_kallsym_info(kallsym_t *info, char *img, int32_t imglen, enum arch_type arch, int32_t is_64); int dump_all_symbols(kallsym_t *info, char *img); +int dump_all_ikconfig(char *img, int32_t imglen); int get_symbol_index_offset(kallsym_t *info, char *img, int32_t index); int get_symbol_offset_and_size(kallsym_t *info, char *img, char *symbol, int32_t *size); int get_symbol_offset(kallsym_t *info, char *img, char *symbol); diff --git a/tools/kptools.c b/tools/kptools.c index 560c9e9d..a322141e 100644 --- a/tools/kptools.c +++ b/tools/kptools.c @@ -43,6 +43,7 @@ void print_usage(char **argv) " -u, --unpatch Unpatch patched kernel image(-i).\n" " -r, --reset-skey Reset superkey of patched image(-i).\n" " -d, --dump Dump kallsyms infomations of kernel image(-i).\n" + " -f, --flag Dump ikconfig infomations of kernel image(-i).\n" " -l, --list Print all patch informations of kernel image if (-i) specified.\n" " Print extra item informations if (-M) specified.\n" " Print KernelPatch image informations if (-k) specified.\n" @@ -81,7 +82,7 @@ int main(int argc, char *argv[]) { "unpatch", no_argument, NULL, 'u' }, { "resetkey", no_argument, NULL, 'r' }, { "dump", no_argument, NULL, 'd' }, - + { "flag", no_argument, NULL, 'f' }, { "list", no_argument, NULL, 'l' }, { "image", required_argument, NULL, 'i' }, @@ -98,7 +99,7 @@ int main(int argc, char *argv[]) { "extra-event", required_argument, NULL, 'V' }, { "extra-args", required_argument, NULL, 'A' }, { 0, 0, 0, 0 } }; - char *optstr = "hvpurdli:s:S:k:o:a:M:E:T:N:V:A:"; + char *optstr = "hvpurdfli:s:S:k:o:a:M:E:T:N:V:A:"; char *kimg_path = NULL; char *kpimg_path = NULL; @@ -126,6 +127,7 @@ int main(int argc, char *argv[]) case 'u': case 'r': case 'd': + case 'f': case 'l': cmd = opt; break; @@ -189,6 +191,8 @@ int main(int argc, char *argv[]) extra_config_num); } else if (cmd == 'd') { ret = dump_kallsym(kimg_path); + } else if (cmd == 'f') { + ret = dump_ikconfig(kimg_path); } else if (cmd == 'u') { ret = unpatch_img(kimg_path, out_path); } else if (cmd == 'r') { diff --git a/tools/patch.c b/tools/patch.c index cb2d0d21..9302929a 100644 --- a/tools/patch.c +++ b/tools/patch.c @@ -683,4 +683,18 @@ int dump_kallsym(const char *kimg_path) set_log_enable(false); free_kernel_file(&kernel_file); return 0; +} +int dump_ikconfig(const char *kimg_path) +{ + if (!kimg_path) tools_loge_exit("empty kernel image\n"); + set_log_enable(true); + // read image files + kernel_file_t kernel_file; + read_kernel_file(kimg_path, &kernel_file); + + + dump_all_ikconfig(kernel_file.kimg,kernel_file.kimg_len); + set_log_enable(false); + free_kernel_file(&kernel_file); + return 0; } \ No newline at end of file diff --git a/tools/patch.h b/tools/patch.h index 0882b457..d253087d 100644 --- a/tools/patch.h +++ b/tools/patch.h @@ -73,6 +73,7 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * int unpatch_img(const char *kimg_path, const char *out_path); int reset_key(const char *kimg_path, const char *out_path, const char *key); int dump_kallsym(const char *kimg_path); +int dump_ikconfig(const char *kimg_path); int print_kp_image_info_path(const char *kpimg_path); int print_image_patch_info(patched_kimg_t *pimg); From d2e86e3874b12a13aa745216c954dc13759354e6 Mon Sep 17 00:00:00 2001 From: bmax Date: Thu, 21 Nov 2024 19:41:11 +0800 Subject: [PATCH 66/71] fix patch failed for linux 6.1.99 (pixel6,pixel8) --- tools/kallsym.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/tools/kallsym.c b/tools/kallsym.c index 2a09dc0c..9961a73f 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -103,6 +103,7 @@ static int find_token_table(kallsym_t *info, char *img, int32_t imglen) char nums_syms[20] = { '\0' }; for (int32_t i = 0; i < 10; i++) nums_syms[i * 2] = '0' + i; + // We just check first 10 letters, not all letters are guaranteed to appear, // In fact, the previous numbers may not always appear too. char letters_syms[20] = { '\0' }; @@ -136,7 +137,11 @@ static int find_token_table(kallsym_t *info, char *img, int32_t imglen) } int32_t offset = pos + 2 - img; + // align + offset = align_ceil(offset, 4); + info->kallsyms_token_table_offset = offset; + tools_logi("kallsyms_token_table offset: 0x%08x\n", offset); // rebuild token_table @@ -965,8 +970,9 @@ int dump_all_symbols(kallsym_t *info, char *img) } return 0; } -int decompress_data(const unsigned char *compressed_data, size_t compressed_size) { - FILE *temp = fopen("temp.gz", "wb"); +int decompress_data(const unsigned char *compressed_data, size_t compressed_size) +{ + FILE *temp = fopen("temp.gz", "wb"); if (!temp) { fprintf(stderr, "Failed to create temp file\n"); return -1; @@ -984,7 +990,7 @@ int decompress_data(const unsigned char *compressed_data, size_t compressed_size char buffer[1024]; int bytes_read; while ((bytes_read = gzread(gz, buffer, sizeof(buffer))) > 0) { - fwrite(buffer, 1, bytes_read, stdout); + fwrite(buffer, 1, bytes_read, stdout); } gzclose(gz); @@ -993,13 +999,12 @@ int decompress_data(const unsigned char *compressed_data, size_t compressed_size int dump_all_ikconfig(char *img, int32_t imglen) { - char *pos_start = memmem(img, imglen, IKCFG_ST, strlen(IKCFG_ST)); if (pos_start == NULL) { fprintf(stderr, "Cannot find kernel config start (IKCFG_ST).\n"); return 1; } - size_t kcfg_start = pos_start - img + 8; + size_t kcfg_start = pos_start - img + 8; // 查找 "IKCFG_ED" char *pos_end = memmem(img, imglen, IKCFG_ED, strlen(IKCFG_ED)); @@ -1007,12 +1012,11 @@ int dump_all_ikconfig(char *img, int32_t imglen) fprintf(stderr, "Cannot find kernel config end (IKCFG_ED).\n"); return 1; } - size_t kcfg_end = pos_end - img - 1; + size_t kcfg_end = pos_end - img - 1; size_t kcfg_bytes = kcfg_end - kcfg_start + 1; printf("Kernel config start: %zu, end: %zu, bytes: %zu\n", kcfg_start, kcfg_end, kcfg_bytes); - unsigned char *extracted_data = (unsigned char *)malloc(kcfg_bytes); if (!extracted_data) { fprintf(stderr, "Memory allocation for extracted data failed.\n"); @@ -1021,16 +1025,10 @@ int dump_all_ikconfig(char *img, int32_t imglen) memcpy(extracted_data, img + kcfg_start, kcfg_bytes); - - int ret = decompress_data(extracted_data, kcfg_bytes); - - - free(extracted_data); - return 0; } From fa35fded337e0d2a10b89d687c47deefaf31f2da Mon Sep 17 00:00:00 2001 From: 1f2003d5 <2652609017@qq.com> Date: Wed, 27 Nov 2024 17:32:46 +0800 Subject: [PATCH 67/71] userd: Fix `/dev/user_init_log` moving (#147) Signed-off-by: GarfieldHan <2652609017@qq.com> Co-authored-by: NepXIN --- kernel/patch/android/userd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 8dc1538b..8e73f0c4 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -65,7 +65,7 @@ static const char user_rc_data[] = { // " exec -- " SUPERCMD " su exec " USER_INIT_SH_PATH " %s boot-completed\n" " rm " REPLACE_RC_FILE "\n" " rm " USER_INIT_SH_PATH "\n" - " mv -f " DEV_LOG_DIR AP_LOG_DIR "\n" + " exec -- " SUPERCMD " su -c \"mv -f " DEV_LOG_DIR " " AP_LOG_DIR "\"\n" "" }; From fe8603f3f6768624ed43ffbed33f2e2234716b9e Mon Sep 17 00:00:00 2001 From: Admire <43035036+Admirepowered@users.noreply.github.com> Date: Thu, 5 Dec 2024 18:41:52 +0800 Subject: [PATCH 68/71] add zlib in windows (#149) --- .github/workflows/build.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4bde6df0..7e69287c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -270,8 +270,11 @@ jobs: - name: Copyfile2 shell: pwsh run: | - cp .\tools\kptools.exe .\tools\kptools-msys2.exe - 7z a kptools-msys2-win .\tools\kptools-msys2.exe D:\a\_temp\msys64\usr\bin\msys-2.0.dll + mkdir .\win + cp .\tools\kptools.exe .\win\kptools-msys2.exe + cp D:\a\_temp\msys64\usr\bin\msys-2.0.dll .\win + cp D:\a\_temp\msys64\usr\bin\msys-z.dll .\win + 7z a kptools-msys2-win .\win - name: Release uses: ncipollo/release-action@v1.12.0 with: From 40492c8fc11e29e93b9a7ede6247c25db7d80c43 Mon Sep 17 00:00:00 2001 From: Tr33NewBee <166474602+Tr33NewBee@users.noreply.github.com> Date: Tue, 7 Jan 2025 20:53:11 +0800 Subject: [PATCH 69/71] fix:#148 (#154) --- tools/kallsym.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/kallsym.c b/tools/kallsym.c index 9961a73f..ce0e3e0b 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -63,8 +63,13 @@ static int find_linux_banner(kallsym_t *info, char *img, int32_t imglen) info->linux_banner_offset[info->banner_num++] = (int32_t)(banner - img); tools_logi("linux_banner %d: %s", info->banner_num, banner); tools_logi("linux_banner offset: 0x%lx\n", banner - img); + break; } } + if(info->banner_num<=0) { + tools_loge("find linux_banner error\n"); + return -1; + } banner = img + info->linux_banner_offset[info->banner_num - 1]; char *uts_release_start = banner + prefix_len; From d2aa8429f95de6a7320b9c90fcbfe1b101d22eb7 Mon Sep 17 00:00:00 2001 From: bmax121 Date: Tue, 7 Jan 2025 20:54:59 +0800 Subject: [PATCH 70/71] Revert "fix:#148 (#154)" (#155) This reverts commit 40492c8fc11e29e93b9a7ede6247c25db7d80c43. --- tools/kallsym.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tools/kallsym.c b/tools/kallsym.c index ce0e3e0b..9961a73f 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -63,13 +63,8 @@ static int find_linux_banner(kallsym_t *info, char *img, int32_t imglen) info->linux_banner_offset[info->banner_num++] = (int32_t)(banner - img); tools_logi("linux_banner %d: %s", info->banner_num, banner); tools_logi("linux_banner offset: 0x%lx\n", banner - img); - break; } } - if(info->banner_num<=0) { - tools_loge("find linux_banner error\n"); - return -1; - } banner = img + info->linux_banner_offset[info->banner_num - 1]; char *uts_release_start = banner + prefix_len; From fd4d5a78951e5d2c75f07f87fcee48b4df38c367 Mon Sep 17 00:00:00 2001 From: bmax121 Date: Tue, 11 Feb 2025 22:11:08 +0800 Subject: [PATCH 71/71] fix memmem --- tools/kallsym.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/kallsym.c b/tools/kallsym.c index 9961a73f..e49777fb 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -58,7 +58,7 @@ static int find_linux_banner(kallsym_t *info, char *img, int32_t imglen) char *imgend = img + imglen; char *banner = (char *)img; info->banner_num = 0; - while ((banner = (char *)memmem(banner + 1, imgend - banner, linux_banner_prefix, prefix_len)) != NULL) { + while ((banner = (char *)memmem(banner + 1, imgend - banner - 1, linux_banner_prefix, prefix_len)) != NULL) { if (isdigit(*(banner + prefix_len)) && *(banner + prefix_len + 1) == '.') { info->linux_banner_offset[info->banner_num++] = (int32_t)(banner - img); tools_logi("linux_banner %d: %s", info->banner_num, banner);