diff --git a/kernel/include/preset.h b/kernel/include/preset.h index 2a8b3c3f..845d6251 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -115,19 +115,9 @@ struct patch_symbol uint64_t __cfi_slowpath; uint64_t copy_process; uint64_t cgroup_post_fork; - uint64_t __do_execve_file; - uint64_t do_execveat_common; - uint64_t do_execve_common; uint64_t avc_denied; uint64_t slow_avc_audit; uint64_t input_handle_event; - uint64_t vfs_statx; - uint64_t vfs_stat; - uint64_t do_statx; - uint64_t vfs_fstatat; - uint64_t do_faccessat; - uint64_t sys_faccessat; - uint64_t sys_faccessat2; }; char _cap[PATCH_SYMBOL_LEN]; }; @@ -160,15 +150,19 @@ typedef int32_t extra_item_type; // todo #define EXTRA_EVENT_PAGING_INIT "paging-init" + #define EXTRA_EVENT_PRE_KERNEL_INIT "pre-kernel-init" #define EXTRA_EVENT_KPM_DEFAULT EXTRA_EVENT_PRE_KERNEL_INIT #define EXTRA_EVENT_POST_KERNEL_INIT "post-kernel-init" -#define EXTRA_EVENT_PRE_INIT "pre-init" -#define EXTRA_EVENT_POST_INIT "post-init" -#define EXTRA_EVENT_PRE_SECOND_STAGE "pre-second-stage" -#define EXTRA_EVENT_POST_SECOND_STAGE "post-second-stage" -#define EXTRA_EVENT_PRE_ZYGOTE_START "pre-zygote-start" -#define EXTRA_EVENT_POST_ZYGOTE_START "post-zygote-start" + +#define EXTRA_EVENT_PRE_FIRST_STAGE "pre-init-first-stage" +#define EXTRA_EVENT_POST_FIRST_STAGE "post-init-first-stage" + +#define EXTRA_EVENT_PRE_EXEC_INIT "pre-exec-init" +#define EXTRA_EVENT_POST_EXEC_INIT "post-exec-init" + +#define EXTRA_EVENT_PRE_SECOND_STAGE "pre-init-second-stage" +#define EXTRA_EVENT_POST_SECOND_STAGE "post-init-second-stage" struct _patch_extra_item { diff --git a/kernel/patch/android/kpuserd.c b/kernel/patch/android/kpuserd.c index 8b329c8e..37236a66 100644 --- a/kernel/patch/android/kpuserd.c +++ b/kernel/patch/android/kpuserd.c @@ -31,28 +31,11 @@ #include #include -#define ORIGIN_RC_FILE "/system/etc/init/atrace.rc" -#define REPLACE_RC_FILE "/dev/.atrace.rc" - -static const char patch_rc[] = "" - "\n" - "on late-init\n" - " rm " REPLACE_RC_FILE "\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 -k\n" - "on nonencrypted\n" - " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user services -k\n" - "on property:vold.decrypt=trigger_restart_framework\n" - " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user services -k\n" - "on property:sys.boot_completed=1\n" - " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user boot-completed -k\n" - "\n\n" - ""; - static const void *kernel_read_file(const char *path, loff_t *len) { + set_priv_selinx_allow(current, 1); void *data = 0; + struct file *filp = filp_open(path, O_RDONLY, 0); if (!filp || IS_ERR(filp)) { log_boot("open file: %s error: %d\n", path, PTR_ERR(filp)); @@ -64,112 +47,132 @@ static const void *kernel_read_file(const char *path, loff_t *len) loff_t pos = 0; kernel_read(filp, data, *len, &pos); filp_close(filp, 0); + out: + set_priv_selinx_allow(current, 0); return data; } -static void kernel_write_file(const char *path, const void *data, loff_t len, umode_t mode) +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); + 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; } - loff_t off = 0; 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_selinx_allow(current, 0); + return off; } -static void kernel_write_exec(const char *path, const void *data, loff_t len) +static loff_t kernel_write_exec(const char *path, const void *data, loff_t len) { - kernel_write_file(path, data, len, 0744); + 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 *path = (const char *)udata; + const char *event = (const char *)udata; if (extra->type == EXTRA_TYPE_EXEC && !strcmp("kpatch", extra->name)) { - log_boot("write kpatch to %s\n", path); - kernel_write_exec(path, con, extra->con_size); + 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 before_first_stage() +static void try_extract_kpatch(const char *event) { - const char *path = KPATCH_DEV_PATH; - on_each_extra_item(extract_kpatch_call_back, (void *)path); + 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 before_second_stage() +static void pre_user_exec_init() { + log_boot("event: %s\n", EXTRA_EVENT_PRE_EXEC_INIT); + try_extract_kpatch(EXTRA_EVENT_PRE_EXEC_INIT); } -static void on_zygote_start() +static void pre_init_second_stage() { + log_boot("event: %s\n", EXTRA_EVENT_PRE_SECOND_STAGE); + try_extract_kpatch(EXTRA_EVENT_PRE_SECOND_STAGE); } -// 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) +static void on_first_app_process() { - int filename_index = 0; - if ((((uintptr_t)args->arg0) & 0xF000000000000000) != 0xF000000000000000) { - filename_index = 1; - } - struct filename *filename = (struct filename *)args->args[filename_index]; - if (!filename || IS_ERR(filename)) return; +} - const char app_process[] = "/system/bin/app_process"; - static int first_app_process = 1; +#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) +{ + // unhook flag + hook_local->data7 = 0; + + static char app_process[] = "/system/bin/app_process"; + static char app_process64[] = "/system/bin/app_process64"; + static int first_app_process_execed = 0; static const char system_bin_init[] = "/system/bin/init"; static const char root_init[] = "/init"; - static int init_first_stage_executed = 0; + static int first_user_init_executed = 0; static int init_second_stage_executed = 0; - if (!strcmp(system_bin_init, filename->name) || !strcmp(root_init, filename->name)) { + char __user *ufilename = *u_filename_p; + char filename[SU_PATH_MAX_LEN]; + int flen = compact_strncpy_from_user(filename, ufilename, sizeof(filename)); + if (flen <= 0) return; + + if (!strcmp(system_bin_init, filename) || !strcmp(root_init, filename)) { // - if (!init_first_stage_executed) { - init_first_stage_executed = 1; - log_boot("exec %s first stage\n", filename->name); - before_first_stage(); + if (!first_user_init_executed) { + first_user_init_executed = 1; + log_boot("exec first user init: %s\n", filename); + pre_user_exec_init(); } if (!init_second_stage_executed) { for (int i = 1;; i++) { - const char *__user p1 = - get_user_arg_ptr((void *)args->args[filename_index + 1], (void *)args->args[filename_index + 2], i); + const char __user *p1 = get_user_arg_ptr(0, *uargv, i); if (!p1 || IS_ERR(p1)) break; char arg[16] = { '\0' }; if (compact_strncpy_from_user(arg, p1, sizeof(arg)) <= 0) break; + if (!strcmp(arg, "second_stage") || !strcmp(arg, "--second-stage")) { - log_boot("exec %s second stage 0\n", filename->name); - before_second_stage(); + log_boot("exec %s second stage 0\n", filename); + pre_init_second_stage(); init_second_stage_executed = 1; } } } if (!init_second_stage_executed) { - int envp_index = filename_index + (has_config_compat ? 3 : 2); for (int i = 0;; i++) { - const char *__user up = - get_user_arg_ptr((void *)args->args[envp_index], (void *)args->args[envp_index + 1], i); - if (!up || IS_ERR(up)) break; + const char *__user uenv = get_user_arg_ptr(0, *uenvp, i); + if (!uenv || IS_ERR(uenv)) break; + char env[256]; - if (compact_strncpy_from_user(env, up, sizeof(env)) <= 0) break; + if (compact_strncpy_from_user(env, uenv, sizeof(env)) <= 0) break; char *env_name = env; char *env_value = strchr(env, '='); if (env_value) { @@ -177,8 +180,8 @@ static void before_do_execve(hook_fargs8_t *args, void *udata) env_value++; if (!strcmp(env_name, "INIT_SECOND_STAGE") && (!strcmp(env_value, "1") || !strcmp(env_value, "true"))) { - log_boot("exec %s second stage 1\n", filename->name); - before_second_stage(); + log_boot("exec %s second stage 1\n", filename); + pre_init_second_stage(); init_second_stage_executed = 1; } } @@ -186,18 +189,90 @@ static void before_do_execve(hook_fargs8_t *args, void *udata) } } - if (unlikely(first_app_process && !strcmp(app_process, filename->name))) { - first_app_process = 0; - log_boot("exec app_process, /data prepared, second_stage: %d\n", init_second_stage_executed); - on_zygote_start(); - remove_execv_hook(before_do_execve, 0); + if (!first_app_process_execed && (!strcmp(app_process, filename) || !strcmp(app_process64, filename))) { + first_app_process_execed = 1; + log_boot("exec first app_process: %s\n", filename); + on_first_app_process(); + hook_local->data7 = 1; + return; } } +static void before_execve(hook_fargs3_t *args, void *udata); +static void after_execve(hook_fargs3_t *args, void *udata); +static void before_execveat(hook_fargs5_t *args, void *udata); +static void after_execveat(hook_fargs5_t *args, void *udata); + +static void handle_after_execve(hook_local_t *hook_local) +{ + int unhook = hook_local->data7; + if (unhook) { + inline_unhook_syscall(__NR_execve, before_execve, after_execve); + inline_unhook_syscall(__NR_execveat, before_execveat, after_execveat); + } +} + +// 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); + void *arg2p = syscall_argn_p(args, 2); + handle_before_execve(&args->local, (char **)arg0p, (char **)arg1p, (char **)arg2p, udata); +} + +static void after_execve(hook_fargs3_t *args, void *udata) +{ + handle_after_execve(&args->local); +} + +// 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) +{ + void *arg1p = syscall_argn_p(args, 1); + void *arg2p = syscall_argn_p(args, 2); + void *arg3p = syscall_argn_p(args, 3); + handle_before_execve(&args->local, (char **)arg1p, (char **)arg2p, (char **)arg3p, udata); +} + +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/.atrace.rc" + +static const char patch_rc[] = "" + "\n" + "on late-init\n" + " rm " REPLACE_RC_FILE "\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 -k\n" + "on nonencrypted\n" + " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user services -k\n" + "on property:vold.decrypt=trigger_restart_framework\n" + " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user services -k\n" + "on property:sys.boot_completed=1\n" + " exec -- " SUPERCMD " %s " KPATCH_DATA_PATH " %s android_user boot-completed -k\n" + "\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) { - // clear local + // cp len args->local.data0 = 0; + // cp ptr + args->local.data1 = 0; + // unhook flag + args->local.data2 = 0; static int replaced = 0; if (replaced) return; @@ -209,20 +284,20 @@ static void before_openat(hook_fargs4_t *args, void *udata) replaced = 1; - set_priv_selinx_allow(current, 1); - // create replace file and redirect loff_t ori_len = 0; struct file *newfp = filp_open(REPLACE_RC_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (!newfp || IS_ERR(newfp)) { log_boot("create replace rc error: %d\n", PTR_ERR(newfp)); goto out; } + const char *ori_rc_data = kernel_read_file(ORIGIN_RC_FILE, &ori_len); if (!ori_rc_data) goto out; + char *replace_rc_data = vmalloc(sizeof(patch_rc) + 10 * SUPER_KEY_LEN); - const char *superkey = get_superkey(); - sprintf(replace_rc_data, patch_rc, superkey, superkey, superkey, superkey, superkey, superkey, superkey, superkey, - superkey, superkey); + const char *sk = get_superkey(); + sprintf(replace_rc_data, patch_rc, sk, sk, sk, sk, sk, sk, sk, sk, sk, sk); + loff_t off = 0; kernel_write(newfp, replace_rc_data, strlen(replace_rc_data), &off); kernel_write(newfp, ori_rc_data, ori_len, &off); @@ -230,26 +305,37 @@ static void before_openat(hook_fargs4_t *args, void *udata) log_boot("write replace rc error: %x\n", off); goto free; } - // yes, filename is not read only - args->local.data0 = compat_copy_to_user((void *)filename, REPLACE_RC_FILE, sizeof(REPLACE_RC_FILE)); - log_boot("redirect rc file: %x\n", args->local.data0); + + int cplen = 0; + cplen = compat_copy_to_user((void *)filename, REPLACE_RC_FILE, sizeof(REPLACE_RC_FILE)); + if (cplen > 0) { + args->local.data0 = cplen; + args->local.data1 = (uint64_t)args->arg1; + log_boot("redirect rc file: %x\n", args->local.data0); + } else { + void *__user up = copy_to_user_stack(REPLACE_RC_FILE, sizeof(REPLACE_RC_FILE)); + args->arg1 = (uint64_t)up; + log_boot("redirect rc file stack: %llx\n", up); + } + free: filp_close(newfp, 0); kvfree(ori_rc_data); kvfree(replace_rc_data); + out: - // read file not require selinux permission, reset not allow now - set_priv_selinx_allow(current, 0); + args->local.data2 = 1; return; } static void after_openat(hook_fargs4_t *args, void *udata) { if (args->local.data0) { - const char __user *filename = (typeof(filename))syscall_argn(args, 1); - int len = compat_copy_to_user((void *)filename, ORIGIN_RC_FILE, sizeof(ORIGIN_RC_FILE)); - log_boot("restore rc file: %x\n", len); - fp_unhook_syscall(__NR_openat, before_openat, after_openat); + compat_copy_to_user((void *)args->local.data1, ORIGIN_RC_FILE, sizeof(ORIGIN_RC_FILE)); + log_boot("restore rc file: %x\n", args->local.data0); + } + if (args->local.data2) { + inline_unhook_syscall(__NR_openat, before_openat, after_openat); } } @@ -275,27 +361,27 @@ static void before_input_handle_event(hook_fargs4_t *args, void *udata) int kpuserd_init() { - int rc = 0; - hook_err_t err = HOOK_NO_ERR; - err |= inline_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)__NR_execve); - err |= inline_hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)__NR_execveat); + hook_err_t ret = 0; + hook_err_t rc = HOOK_NO_ERR; + + rc = inline_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)__NR_execve); + log_boot("hook rc: %d\n", rc); + ret |= rc; - err |= inline_hook_syscalln(__NR_openat, 4, before_openat, after_openat, 0); + rc = inline_hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)__NR_execveat); + log_boot("hook rc: %d\n", rc); + ret |= rc; + + rc = inline_hook_syscalln(__NR_openat, 4, before_openat, after_openat, 0); + log_boot("hook rc: %d\n", rc); + ret |= rc; unsigned long input_handle_event_addr = get_preset_patch_sym()->input_handle_event; if (!input_handle_event_addr) { - log_boot("no symbol input_handle_event_addr\n"); - rc = -ENOENT; - goto out; - } else { - hook_err_t err = hook_wrap4((void *)input_handle_event_addr, before_input_handle_event, 0, 0); - if (err) { - log_boot("hook do_faccessat error: %d\n", err); - rc = err; - goto out; - } + rc = hook_wrap4((void *)input_handle_event_addr, before_input_handle_event, 0, 0); + ret |= rc; + log_boot("hook rc: %d\n", rc); } -out: - return rc; + return ret; } \ No newline at end of file diff --git a/kernel/patch/common/accctl.c b/kernel/patch/common/accctl.c index dd2acd31..e8b345d2 100644 --- a/kernel/patch/common/accctl.c +++ b/kernel/patch/common/accctl.c @@ -24,6 +24,7 @@ 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; } diff --git a/kernel/patch/common/extrainit.c b/kernel/patch/common/extrainit.c deleted file mode 100644 index 0747a425..00000000 --- a/kernel/patch/common/extrainit.c +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2024 bmax121. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include - -static int extra_load_kpm_callback(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(event, extra->event) || (!extra->event[0] && !strcmp(EXTRA_EVENT_KPM_DEFAULT, event))) { - int rc = load_module(data, extra->con_size, args, event, 0); - log_boot("%s loading extra kpm return: %d\n", event, rc); - } - } - return 0; -} - -int extra_load_kpm(const char *event) -{ - on_each_extra_item(extra_load_kpm_callback, (void *)event); - return 0; -} diff --git a/kernel/patch/common/sucompat.c b/kernel/patch/common/sucompat.c index cd4be6c2..61441fec 100644 --- a/kernel/patch/common/sucompat.c +++ b/kernel/patch/common/sucompat.c @@ -67,6 +67,7 @@ static struct su_profile *search_allow_uid(uid_t uid) { if (pos->uid == uid) { // make a deep copy + // todo: use stack struct su_profile *profile = (struct su_profile *)vmalloc(sizeof(struct su_profile)); memcpy(profile, &pos->profile, sizeof(struct su_profile)); rcu_read_unlock(); @@ -344,6 +345,8 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen commit_su(0, 0); + // command + // shift args *uargv += 2 * 8; } @@ -457,18 +460,25 @@ int su_compat_init() }; su_add_allow_uid(default_shell_profile.uid, &default_shell_profile, 1); - hook_err_t err = HOOK_NO_ERR; + hook_err_t rc = HOOK_NO_ERR; + + rc = inline_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)__NR_execve); + log_boot("hook rc: %d\n", rc); - err |= inline_hook_syscalln(__NR_execve, 3, before_execve, after_execve, (void *)__NR_execve); - err |= inline_hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)__NR_execveat); + rc = inline_hook_syscalln(__NR_execveat, 5, before_execveat, after_execveat, (void *)__NR_execveat); + log_boot("hook rc: %d\n", rc); - err |= inline_hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)__NR3264_fstatat); + rc = inline_hook_syscalln(__NR3264_fstatat, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, + (void *)__NR3264_fstatat); + log_boot("hook rc: %d\n", rc); - err |= inline_hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)__NR_faccessat); - err |= inline_hook_syscalln(__NR_faccessat2, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, - (void *)__NR_faccessat2); + rc = inline_hook_syscalln(__NR_faccessat, 3, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, + (void *)__NR_faccessat); + log_boot("hook rc: %d\n", rc); - return err; + rc = inline_hook_syscalln(__NR_faccessat2, 4, su_handler_arg1_ufilename_before, su_handler_arg1_ufilename_after, + (void *)__NR_faccessat2); + log_boot("hook rc: %d\n", rc); + + return rc; } \ No newline at end of file diff --git a/kernel/patch/include/extrainit.h b/kernel/patch/include/extrainit.h deleted file mode 100644 index c9f4954e..00000000 --- a/kernel/patch/include/extrainit.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Copyright (C) 2024 bmax121. All Rights Reserved. - */ - -#ifndef _KP_EXTRAINIT_H_ -#define _KP_EXTRAINIT_H_ - -int extra_load_kpm(); - -#endif \ No newline at end of file diff --git a/kernel/patch/ksyms/pt_regs.c b/kernel/patch/ksyms/execv.c similarity index 72% rename from kernel/patch/ksyms/pt_regs.c rename to kernel/patch/ksyms/execv.c index 119d754a..31d95f5e 100644 --- a/kernel/patch/ksyms/pt_regs.c +++ b/kernel/patch/ksyms/execv.c @@ -6,9 +6,15 @@ #include #include #include +#include static int first_init_execed = 0; +static void before_first_exec() +{ + log_boot("event: %s\n", EXTRA_EVENT_PRE_EXEC_INIT); +} + // 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) @@ -16,10 +22,13 @@ static int first_init_execed = 0; // 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_execve(hook_fargs5_t *args, void *udata) +static void before_execve(hook_fargs3_t *args, void *udata) { if (first_init_execed) return; first_init_execed = 1; + before_first_exec(); + + log_boot("kernel stack:\n"); uint64_t arg0 = syscall_argn(args, 0); uint64_t arg1 = syscall_argn(args, 1); @@ -38,14 +47,11 @@ static void before_execve(hook_fargs5_t *args, void *udata) struct pt_regs *regs = (struct pt_regs *)i; if (regs->orig_x0 == arg0 && regs->syscallno == nr && regs->regs[8] == nr) { pt_regs_offset = addr - i; - log_boot("pt_regs offset of stack top: %llx\n", pt_regs_offset); break; } } } - if (pt_regs_offset < 0) { - log_boot("can't resolve pt_regs\n"); - } + log_boot(" pt_regs offset: %x\n", pt_regs_offset); } static void after_execv(hook_fargs5_t *args, void *udata) @@ -56,7 +62,16 @@ static void after_execv(hook_fargs5_t *args, void *udata) int resolve_pt_regs() { - inline_hook_syscalln(__NR_execve, 3, before_execve, after_execv, (void *)__NR_execve); - inline_hook_syscalln(__NR_execveat, 5, before_execve, after_execv, (void *)__NR_execveat); - return 0; + hook_err_t ret = 0; + hook_err_t rc = HOOK_NO_ERR; + + rc = inline_hook_syscalln(__NR_execve, 3, before_execve, after_execv, (void *)__NR_execve); + log_boot("hook rc: %d\n", rc); + ret |= rc; + + rc = inline_hook_syscalln(__NR_execveat, 5, before_execve, after_execv, (void *)__NR_execveat); + log_boot("hook rc: %d\n", rc); + ret |= rc; + + return rc; } \ No newline at end of file diff --git a/kernel/patch/patch.c b/kernel/patch/patch.c index 35119a87..2716a196 100644 --- a/kernel/patch/patch.c +++ b/kernel/patch/patch.c @@ -12,7 +12,7 @@ #include #include #include -#include +#include int linux_misc_symbol_init(); int linux_libs_symbol_init(); @@ -68,86 +68,89 @@ static void before_rest_init(hook_fargs4_t *args, void *udata) if ((rc = resolve_struct())) goto out; log_boot("resolve_struct done: %d\n", rc); - if ((rc = task_observer())) goto out; - log_boot("task_observer done: %d\n", rc); - if ((rc = selinux_hook_install())) goto out; log_boot("selinux_hook_install 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); - if ((rc = supercall_install())) goto out; + rc = supercall_install(); log_boot("supercall_install done: %d\n", rc); - if ((rc = resolve_pt_regs())) goto out; + rc = resolve_pt_regs(); + log_boot("resolve_pt_regs done: %d\n", rc); - if ((rc = su_compat_init())) goto out; + rc = su_compat_init(); log_boot("su_compat_init done: %d\n", rc); #ifdef ANDROID - - if ((rc = kpuserd_init())) goto out; + rc = kpuserd_init(); log_boot("kpuserd_init done: %d\n", rc); - #endif out: return; } +static int extra_load_kpm_callback(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(event, extra->event) || (!extra->event[0] && !strcmp(EXTRA_EVENT_KPM_DEFAULT, event))) { + int rc = load_module(data, extra->con_size, args, event, 0); + log_boot("%s loading extra kpm return: %d\n", event, rc); + } + } + return 0; +} + +static int extra_load_kpm(const char *event) +{ + on_each_extra_item(extra_load_kpm_callback, (void *)event); + return 0; +} + static void before_kernel_init(hook_fargs4_t *args, void *udata) { - log_boot("before kernel_init ...\n"); - int rc = extra_load_kpm(EXTRA_EVENT_PRE_KERNEL_INIT); - log_boot("extra_load_kpm done: %d\n", rc); + log_boot("event: %s\n", EXTRA_EVENT_PRE_KERNEL_INIT); + extra_load_kpm(EXTRA_EVENT_PRE_KERNEL_INIT); } static void after_kernel_init(hook_fargs4_t *args, void *udata) { - log_boot("after kernel_init ...\n"); - // int rc = extra_load_kpm(EXTRA_EVENT_POST_KERNEL_INIT); - // log_boot("extra_load_kpm done: %d\n", rc); + log_boot("event: %s\n", EXTRA_EVENT_POST_KERNEL_INIT); } int patch() { - int rc = 0; + hook_err_t ret = 0; unsigned long panic_addr = get_preset_patch_sym()->panic; if (panic_addr) { - hook_err_t err = hook_wrap12((void *)panic_addr, before_panic, 0, 0); - if (err) { - log_boot("hook panic: %llx, error: %d\n", panic_addr, rc); - rc = err; - goto out; - } + hook_err_t rc = hook_wrap12((void *)panic_addr, before_panic, 0, 0); + log_boot("hook rc: %d\n", rc); + ret |= 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 err = hook_wrap4((void *)init_addr, before_rest_init, 0, (void *)init_addr); - if (err) { - log_boot("hook for init: %llx, error: %d\n", init_addr, err); - rc = err; - goto out; - } + hook_err_t rc = hook_wrap4((void *)init_addr, before_rest_init, 0, (void *)init_addr); + log_boot("hook rc: %d\n", rc); + ret |= rc; } // kernel_init unsigned long kernel_init_addr = get_preset_patch_sym()->kernel_init; if (kernel_init_addr) { - hook_err_t err = hook_wrap4((void *)kernel_init_addr, before_kernel_init, after_kernel_init, 0); - if (err) { - log_boot("hook kernel_init: %llx, error: %d\n", kernel_init_addr, err); - rc = err; - goto out; - } + hook_err_t rc = hook_wrap4((void *)kernel_init_addr, before_kernel_init, after_kernel_init, 0); + log_boot("hook rc: %d\n", rc); + ret |= rc; } -out: - return rc; + return ret; } diff --git a/tools/symbol.c b/tools/symbol.c index 30851df1..5ab86fb6 100644 --- a/tools/symbol.c +++ b/tools/symbol.c @@ -119,12 +119,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_execve_file = try_get_symbol_offset_zero(kallsym, img_buf, "__do_execve_file"); - symbol->do_execveat_common = try_get_symbol_offset_zero(kallsym, img_buf, "do_execveat_common"); - symbol->do_execve_common = try_get_symbol_offset_zero(kallsym, img_buf, "do_execve_common"); - if (!symbol->__do_execve_file && !symbol->do_execveat_common && !symbol->do_execve_common) - tools_loge_exit("no symbol execve"); - // 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"); @@ -133,19 +127,6 @@ int fillin_patch_symbol(kallsym_t *kallsym, char *img_buf, int imglen, patch_sym symbol->input_handle_event = get_symbol_offset_zero(kallsym, img_buf, "input_handle_event"); - symbol->vfs_statx = try_get_symbol_offset_zero(kallsym, img_buf, "vfs_statx"); - symbol->do_statx = try_get_symbol_offset_zero(kallsym, img_buf, "do_statx"); - symbol->vfs_fstatat = try_get_symbol_offset_zero(kallsym, img_buf, "vfs_fstatat"); - if (!symbol->vfs_statx && !symbol->do_statx && !symbol->vfs_fstatat) tools_loge_exit("no symbol stat"); - - symbol->do_faccessat = try_get_symbol_offset_zero(kallsym, img_buf, "do_faccessat"); - if (!symbol->do_faccessat) { - symbol->sys_faccessat = get_symbol_offset_zero(kallsym, img_buf, "sys_faccessat"); - symbol->sys_faccessat2 = get_symbol_offset_zero(kallsym, img_buf, "sys_faccessat2"); - } - // if (!symbol->do_faccessat && (!symbol->sys_faccessat || !symbol->sys_faccessat2)) - // tools_loge_exit("no symbol accessat"); - if ((is_be() ^ target_is_be)) { for (int64_t *pos = (int64_t *)symbol; pos <= (int64_t *)symbol; pos++) { *pos = i64swp(*pos); diff --git a/user/android/android_user.c b/user/android/android_user.c index 1d829b30..fcc36319 100644 --- a/user/android/android_user.c +++ b/user/android/android_user.c @@ -200,7 +200,7 @@ static void post_fs_data_init() char *const cp_argv[] = { "/system/bin/cp", current_exe, KPATCH_DATA_PATH, NULL }; fork_for_result(cp_argv[0], cp_argv); - char *const rm_argv[] = { "/system/bin/unlink", current_exe, NULL }; + char *const rm_argv[] = { "/system/bin/rm", current_exe, NULL }; fork_for_result(rm_argv[0], rm_argv); } } @@ -229,7 +229,9 @@ int android_user(int argc, char **argv) if (!sc_ready(key)) return -EFAULT; char *scmd = argv[1]; - if (scmd == NULL) return -1; + if (scmd == NULL) return -EINVAL; + + log_kernel("cmd: %s\n", scmd); int optc; while ((optc = getopt_long(argc, argv, "k", longopts, NULL)) != -1) {