kernel: hook newfstatat/faccessat syscall instead of unstable symbol

This commit is contained in:
weishu
2024-03-20 15:15:26 +08:00
parent 2a64784a33
commit 815f4d0428
2 changed files with 54 additions and 3 deletions

View File

@@ -21,9 +21,13 @@
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PRCTL_SYMBOL "__arm64_sys_prctl" #define PRCTL_SYMBOL "__arm64_sys_prctl"
#define SYS_READ_SYMBOL "__arm64_sys_read" #define SYS_READ_SYMBOL "__arm64_sys_read"
#define SYS_NEWFSTATAT_SYMBOL "__arm64_sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "__arm64_sys_faccessat"
#else #else
#define PRCTL_SYMBOL "sys_prctl" #define PRCTL_SYMBOL "sys_prctl"
#define SYS_READ_SYMBOL "sys_read" #define SYS_READ_SYMBOL "sys_read"
#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "sys_faccessat"
#endif #endif
#elif defined(__x86_64__) #elif defined(__x86_64__)
@@ -44,9 +48,13 @@
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#define PRCTL_SYMBOL "__x64_sys_prctl" #define PRCTL_SYMBOL "__x64_sys_prctl"
#define SYS_READ_SYMBOL "__x64_sys_read" #define SYS_READ_SYMBOL "__x64_sys_read"
#define SYS_NEWFSTATAT_SYMBOL "__x64_sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "__x64_sys_faccessat"
#else #else
#define PRCTL_SYMBOL "sys_prctl" #define PRCTL_SYMBOL "sys_prctl"
#define SYS_READ_SYMBOL "sys_read" #define SYS_READ_SYMBOL "sys_read"
#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat"
#define SYS_FACCESSAT_SYMBOL "sys_faccessat"
#endif #endif
#else #else

View File

@@ -1,4 +1,5 @@
#include "asm/current.h" #include "asm/current.h"
#include "linux/compiler_attributes.h"
#include "linux/cred.h" #include "linux/cred.h"
#include "linux/err.h" #include "linux/err.h"
#include "linux/fs.h" #include "linux/fs.h"
@@ -40,7 +41,7 @@ static char __user *sh_user_path(void)
} }
int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode, int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
int *flags) int * __unused_flags)
{ {
const char su[] = SU_PATH; const char su[] = SU_PATH;
@@ -131,7 +132,7 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
#ifdef CONFIG_KPROBES #ifdef CONFIG_KPROBES
static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs) __maybe_unused static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{ {
int *dfd = (int *)PT_REGS_PARM1(regs); int *dfd = (int *)PT_REGS_PARM1(regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs); const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs);
@@ -142,7 +143,21 @@ static int faccessat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_faccessat(dfd, filename_user, mode, flags); return ksu_handle_faccessat(dfd, filename_user, mode, flags);
} }
static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs) static int sys_faccessat_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
int *dfd = (int *)PT_REGS_PARM1(real_regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(real_regs);
int *mode = (int *)&PT_REGS_PARM3(real_regs);
return ksu_handle_faccessat(dfd, filename_user, mode, NULL);
}
__maybe_unused static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
{ {
int *dfd = (int *)&PT_REGS_PARM1(regs); int *dfd = (int *)&PT_REGS_PARM1(regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs); const char __user **filename_user = (const char **)&PT_REGS_PARM2(regs);
@@ -157,6 +172,20 @@ static int newfstatat_handler_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_stat(dfd, filename_user, flags); return ksu_handle_stat(dfd, filename_user, flags);
} }
static int sys_newfstatat_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
int *dfd = (int *)&PT_REGS_PARM1(real_regs);
const char __user **filename_user = (const char **)&PT_REGS_PARM2(real_regs);
int *flags = (int *)&PT_REGS_SYSCALL_PARM4(real_regs);
return ksu_handle_stat(dfd, filename_user, flags);
}
// https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864 // https://elixir.bootlin.com/linux/v5.10.158/source/fs/exec.c#L1864
static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs) static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
{ {
@@ -167,6 +196,12 @@ static int execve_handler_pre(struct kprobe *p, struct pt_regs *regs)
return ksu_handle_execveat_sucompat(fd, filename_ptr, NULL, NULL, NULL); return ksu_handle_execveat_sucompat(fd, filename_ptr, NULL, NULL, NULL);
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
static struct kprobe faccessat_kp = {
.symbol_name = SYS_FACCESSAT_SYMBOL,
.pre_handler = sys_faccessat_handler_pre,
};
#else
static struct kprobe faccessat_kp = { static struct kprobe faccessat_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
.symbol_name = "do_faccessat", .symbol_name = "do_faccessat",
@@ -175,7 +210,14 @@ static struct kprobe faccessat_kp = {
#endif #endif
.pre_handler = faccessat_handler_pre, .pre_handler = faccessat_handler_pre,
}; };
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0)
static struct kprobe newfstatat_kp = {
.symbol_name = SYS_NEWFSTATAT_SYMBOL,
.pre_handler = sys_newfstatat_handler_pre,
};
#else
static struct kprobe newfstatat_kp = { static struct kprobe newfstatat_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
.symbol_name = "vfs_statx", .symbol_name = "vfs_statx",
@@ -184,6 +226,7 @@ static struct kprobe newfstatat_kp = {
#endif #endif
.pre_handler = newfstatat_handler_pre, .pre_handler = newfstatat_handler_pre,
}; };
#endif
static struct kprobe execve_kp = { static struct kprobe execve_kp = {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)