Skip to content

Commit

Permalink
Hook syscalls and stable symbols (#1657)
Browse files Browse the repository at this point in the history
1. Replace `do_execveat_common` with `sys_execve` and `sys_execveat`
2. Replace `input_handle_event` with `input_event` and
`input_inject_event`

Tested on android12-5.10-2024-04, android13-5.15-2024-04.
android14-6.1-2024-04
  • Loading branch information
anotherjin authored Apr 26, 2024
1 parent c8dd0b0 commit 2027ac3
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 6 deletions.
4 changes: 4 additions & 0 deletions kernel/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
#define SYS_READ_SYMBOL "__arm64_sys_read"
#define SYS_NEWFSTATAT_SYMBOL "__arm64_sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "__arm64_sys_faccessat"
#define SYS_EXECVE_SYMBOL "__arm64_sys_execve"
#else
#define PRCTL_SYMBOL "sys_prctl"
#define SYS_READ_SYMBOL "sys_read"
#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "sys_faccessat"
#define SYS_EXECVE_SYMBOL "sys_execve"
#endif

#elif defined(__x86_64__)
Expand All @@ -50,11 +52,13 @@
#define SYS_READ_SYMBOL "__x64_sys_read"
#define SYS_NEWFSTATAT_SYMBOL "__x64_sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "__x64_sys_faccessat"
#define SYS_EXECVE_SYMBOL "__x64_sys_execve"
#else
#define PRCTL_SYMBOL "sys_prctl"
#define SYS_READ_SYMBOL "sys_read"
#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "sys_faccessat"
#define SYS_EXECVE_SYMBOL "sys_execve"
#endif

#else
Expand Down
54 changes: 48 additions & 6 deletions kernel/ksud.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ int ksu_handle_execveat_ksud(int *fd, struct filename **filename_ptr,
return 0;
}

if (unlikely(!memcmp(filename->name, system_bin_init,
if (unlikely(!memcmp(filename->name, system_bin_init,
sizeof(system_bin_init) - 1) && argv)) {
// /system/bin/init executed
int argc = count(*argv, MAX_ARG_STRINGS);
Expand Down Expand Up @@ -472,6 +472,32 @@ static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_execveat_ksud(fd, filename_ptr, &argv, NULL, NULL);
}

static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1(regs);
#else
struct pt_regs *real_regs = regs;
#endif
const char __user **filename_user = (const char **)&PT_REGS_PARM1(real_regs);
const char __user *const __user *__argv =
(const char __user *const __user *)PT_REGS_PARM2(real_regs);
struct user_arg_ptr argv = { .ptr.native = __argv };
struct filename filename_in, *filename_p;
char path[32];

if (!filename_user)
return 0;

memset(path, 0, sizeof(path));
ksu_strncpy_from_user_nofault(path, *filename_user, 32);
filename_in.name = path;

filename_p = &filename_in;
return ksu_handle_execveat_ksud(AT_FDCWD, &filename_p, &argv, NULL,
NULL);
}

// remove this later!
__maybe_unused static int vfs_read_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
Expand Down Expand Up @@ -506,6 +532,12 @@ static int input_handle_event_handler_pre(struct kprobe *p,
return ksu_handle_input_handle_event(type, code, value);
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
static struct kprobe execve_kp = {
.symbol_name = SYS_EXECVE_SYMBOL,
.pre_handler = sys_execve_handler_pre,
};
#else
static struct kprobe execve_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
.symbol_name = "do_execveat_common",
Expand All @@ -516,6 +548,7 @@ static struct kprobe execve_kp = {
#endif
.pre_handler = execve_handler_pre,
};
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
static struct kprobe vfs_read_kp = {
Expand All @@ -529,11 +562,20 @@ static struct kprobe vfs_read_kp = {
};
#endif

static struct kprobe input_handle_event_kp = {
.symbol_name = "input_handle_event",
static struct kprobe input_event_kp = {
.symbol_name = "input_event",
.pre_handler = input_handle_event_handler_pre,
};

static struct kprobe input_inject_event_kp = {
.symbol_name = "input_inject_event",
.pre_handler = input_handle_event_handler_pre,
};

static struct kprobe *input_event_kps[] = {
&input_event_kp, &input_inject_event_kp
};

static void do_stop_vfs_read_hook(struct work_struct *work)
{
unregister_kprobe(&vfs_read_kp);
Expand All @@ -546,7 +588,7 @@ static void do_stop_execve_hook(struct work_struct *work)

static void do_stop_input_hook(struct work_struct *work)
{
unregister_kprobe(&input_handle_event_kp);
unregister_kprobes(input_event_kps, 2);
}
#endif

Expand Down Expand Up @@ -600,7 +642,7 @@ void ksu_ksud_init()
ret = register_kprobe(&vfs_read_kp);
pr_info("ksud: vfs_read_kp: %d\n", ret);

ret = register_kprobe(&input_handle_event_kp);
ret = register_kprobes(input_event_kps, 2);
pr_info("ksud: input_handle_event_kp: %d\n", ret);

INIT_WORK(&stop_vfs_read_work, do_stop_vfs_read_hook);
Expand All @@ -614,6 +656,6 @@ void ksu_ksud_exit() {
unregister_kprobe(&execve_kp);
// this should be done before unregister vfs_read_kp
// unregister_kprobe(&vfs_read_kp);
unregister_kprobe(&input_handle_event_kp);
unregister_kprobes(input_event_kps, 2);
#endif
}
52 changes: 52 additions & 0 deletions kernel/sucompat.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ static char __user *sh_user_path(void)
return userspace_stack_buffer(sh_path, sizeof(sh_path));
}

static char __user *ksud_user_path(void)
{
static const char ksud_path[] = KSUD_PATH;

return userspace_stack_buffer(ksud_path, sizeof(ksud_path));
}

int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
int * __unused_flags)
{
Expand Down Expand Up @@ -130,6 +137,32 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
return 0;
}

int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
void *__never_use_argv, void *__never_use_envp, int *__never_use_flags)
{
const char su[] = SU_PATH;
char path[sizeof(su) + 1];

if (unlikely(!filename_user))
return 0;

memset(path, 0, sizeof(path));
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));

if (likely(memcmp(path, su, sizeof(su))))
return 0;

if (!ksu_is_allow_uid(current_uid().val))
return 0;

pr_info("sys_execve su found\n");
*filename_user = ksud_user_path();

escape_to_root();

return 0;
}

#ifdef CONFIG_KPROBES

__maybe_unused static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
Expand Down Expand Up @@ -196,6 +229,18 @@ static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_execveat_sucompat(fd, filename_ptr, NULL, NULL, NULL);
}

static int sys_execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1(regs);
#else
struct pt_regs *real_regs = regs;
#endif
const char __user **filename_user = (const char **)&PT_REGS_PARM1(real_regs);

return ksu_handle_execve_sucompat(AT_FDCWD, filename_user, NULL, NULL, NULL);
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
static struct kprobe faccessat_kp = {
.symbol_name = SYS_FACCESSAT_SYMBOL,
Expand Down Expand Up @@ -228,6 +273,12 @@ static struct kprobe newfstatat_kp = {
};
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
static struct kprobe execve_kp = {
.symbol_name = SYS_EXECVE_SYMBOL,
.pre_handler = sys_execve_handler_pre,
};
#else
static struct kprobe execve_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
.symbol_name = "do_execveat_common",
Expand All @@ -238,6 +289,7 @@ static struct kprobe execve_kp = {
#endif
.pre_handler = execve_handler_pre,
};
#endif

#endif

Expand Down

0 comments on commit 2027ac3

Please sign in to comment.