kernel: susfs 1.5.9 a13-5.15 patch

This commit is contained in:
Rifat Azad
2025-07-15 22:23:43 +06:00
parent 52112a7ee3
commit 6fe4fcbce0
19 changed files with 1037 additions and 95 deletions
+92 -22
View File
@@ -13,6 +13,9 @@
#else
#include <linux/sched.h>
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
#include <linux/susfs_def.h>
#endif
#include "objsec.h"
#include "allowlist.h"
@@ -28,9 +31,13 @@
static bool ksu_sucompat_non_kp __read_mostly = true;
#endif
extern void escape_to_root();
extern void ksu_escape_to_root();
static void __user *userspace_stack_buffer(const void *d, size_t len)
static const char sh_path[] = "/system/bin/sh";
static const char ksud_path[] = KSUD_PATH;
static const char su[] = SU_PATH;
static inline void __user *userspace_stack_buffer(const void *d, size_t len)
{
/* To avoid having to mmap a page in userspace, just write below the stack
* pointer. */
@@ -39,37 +46,37 @@ static void __user *userspace_stack_buffer(const void *d, size_t len)
return copy_to_user(p, d, len) ? NULL : p;
}
static char __user *sh_user_path(void)
static inline char __user *sh_user_path(void)
{
static const char sh_path[] = "/system/bin/sh";
return userspace_stack_buffer(sh_path, sizeof(sh_path));
}
static char __user *ksud_user_path(void)
static inline 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)
{
const char su[] = SU_PATH;
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
return 0;
}
#endif
if (!ksu_is_allow_uid(current_uid().val)) {
return 0;
}
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val)) {
return 0;
}
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su)] = {0};
#else
char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
#endif
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
if (unlikely(!memcmp(path, su, sizeof(su)))) {
@@ -80,27 +87,49 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 1, 0) && defined(CONFIG_KSU_SUSFS_SUS_SU)
struct filename* susfs_ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags) {
struct filename *name = getname_flags(*filename_user, getname_statx_lookup_flags(*flags), NULL);
if (unlikely(IS_ERR(name) || name->name == NULL)) {
return name;
}
if (likely(memcmp(name->name, su, sizeof(su)))) {
return name;
}
const char sh[] = SH_PATH;
pr_info("vfs_fstatat su->sh!\n");
memcpy((void *)name->name, sh, sizeof(sh));
return name;
}
#endif
int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
{
// const char sh[] = SH_PATH;
const char su[] = SU_PATH;
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp){
return 0;
}
#endif
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val)) {
return 0;
}
#endif
if (unlikely(!filename_user)) {
return 0;
}
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su)] = {0};
#else
char path[sizeof(su) + 1];
memset(path, 0, sizeof(path));
#endif
// Remove this later!! we use syscall hook, so this will never happen!!!!!
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) && 0
// it becomes a `struct filename *` after 5.18
@@ -132,8 +161,6 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
int *__never_use_flags)
{
struct filename *filename;
const char sh[] = KSUD_PATH;
const char su[] = SU_PATH;
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
@@ -152,13 +179,15 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
if (likely(memcmp(filename->name, su, sizeof(su))))
return 0;
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid(current_uid().val))
return 0;
#endif
pr_info("do_execveat_common su found\n");
memcpy((void *)filename->name, sh, sizeof(sh));
memcpy((void *)filename->name, ksud_path, sizeof(ksud_path));
escape_to_root();
ksu_escape_to_root();
return 0;
}
@@ -167,8 +196,11 @@ 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;
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su)] = {0};
#else
char path[sizeof(su) + 1];
#endif
#ifndef CONFIG_KSU_KPROBES_HOOK
if (!ksu_sucompat_non_kp) {
@@ -206,7 +238,7 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
pr_info("sys_execve su found\n");
*filename_user = ksud_user_path();
escape_to_root();
ksu_escape_to_root();
return 0;
}
@@ -352,3 +384,41 @@ void ksu_sucompat_exit()
pr_info("ksu_sucompat_exit: hooks disabled: execve/execveat_su, faccessat, stat, devpts\n");
#endif
}
#ifdef CONFIG_KSU_SUSFS_SUS_SU
extern bool ksu_su_compat_enabled;
bool ksu_devpts_hook = false;
bool susfs_is_sus_su_hooks_enabled __read_mostly = false;
int susfs_sus_su_working_mode = 0;
static bool ksu_is_su_kps_enabled(void) {
for (int i = 0; i < ARRAY_SIZE(su_kps); i++) {
if (su_kps[i]) {
return true;
}
}
return false;
}
void ksu_susfs_disable_sus_su(void) {
susfs_is_sus_su_hooks_enabled = false;
ksu_devpts_hook = false;
susfs_sus_su_working_mode = SUS_SU_DISABLED;
// Re-enable the su_kps for user, users need to toggle off the kprobe hooks again in ksu manager if they want it disabled.
if (!ksu_is_su_kps_enabled()) {
ksu_sucompat_init();
ksu_su_compat_enabled = true;
}
}
void ksu_susfs_enable_sus_su(void) {
if (ksu_is_su_kps_enabled()) {
ksu_sucompat_exit();
ksu_su_compat_enabled = false;
}
susfs_is_sus_su_hooks_enabled = true;
ksu_devpts_hook = true;
susfs_sus_su_working_mode = SUS_SU_WITH_HOOKS;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU