Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hook syscalls and stable symbols #1657

Merged
merged 7 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions kernel/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,19 @@
#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"
#define SYS_EXECVEAT_SYMBOL "__arm64_sys_execveat"
#define COMPAT_SYS_EXECVE_SYMBOL "__arm64_compat_sys_execve"
#define COMPAT_SYS_EXECVEAT_SYMBOL "__arm64_compat_sys_execveat"
#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"
#define SYS_EXECVEAT_SYMBOL "sys_execveat"
#define COMPAT_SYS_EXECVE_SYMBOL "compat_sys_execve"
#define COMPAT_SYS_EXECVEAT_SYMBOL "compat_sys_execveat"
#endif

#elif defined(__x86_64__)
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
Loading