diff --git a/kernel/arch.h b/kernel/arch.h index 4a7b93516ae5..1de7e7b7d03b 100644 --- a/kernel/arch.h +++ b/kernel/arch.h @@ -21,9 +21,13 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) #define PRCTL_SYMBOL "__arm64_sys_prctl" #define SYS_READ_SYMBOL "__arm64_sys_read" +#define SYS_NEWFSTATAT_SYMBOL "__arm64_sys_newfstatat" +#define SYS_FACCESSAT_SYMBOL "__arm64_sys_faccessat" #else #define PRCTL_SYMBOL "sys_prctl" #define SYS_READ_SYMBOL "sys_read" +#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat" +#define SYS_FACCESSAT_SYMBOL "sys_faccessat" #endif #elif defined(__x86_64__) @@ -44,9 +48,13 @@ #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0) #define PRCTL_SYMBOL "__x64_sys_prctl" #define SYS_READ_SYMBOL "__x64_sys_read" +#define SYS_NEWFSTATAT_SYMBOL "__x64_sys_newfstatat" +#define SYS_FACCESSAT_SYMBOL "__x64_sys_faccessat" #else #define PRCTL_SYMBOL "sys_prctl" #define SYS_READ_SYMBOL "sys_read" +#define SYS_NEWFSTATAT_SYMBOL "sys_newfstatat" +#define SYS_FACCESSAT_SYMBOL "sys_faccessat" #endif #else diff --git a/kernel/sucompat.c b/kernel/sucompat.c index f4430f8e27c9..983395eeb57a 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -1,4 +1,5 @@ #include "asm/current.h" +#include "linux/compiler_attributes.h" #include "linux/cred.h" #include "linux/err.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 *flags) + int * __unused_flags) { const char su[] = SU_PATH; @@ -131,7 +132,7 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr, #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); 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); } -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); 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); } +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 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); } +#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 = { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) .symbol_name = "do_faccessat", @@ -175,7 +210,14 @@ static struct kprobe faccessat_kp = { #endif .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 = { #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) .symbol_name = "vfs_statx", @@ -184,6 +226,7 @@ static struct kprobe newfstatat_kp = { #endif .pre_handler = newfstatat_handler_pre, }; +#endif static struct kprobe execve_kp = { #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)