kernel: Remove susfs patch

This commit is contained in:
ShirkNeko
2025-11-09 12:48:51 +08:00
parent c400952b47
commit a525048d1f
11 changed files with 35 additions and 962 deletions

View File

@@ -48,142 +48,4 @@ config KSU_MANUAL_HOOK
help help
If enabled, Hook required KernelSU syscalls with manually-patched function. If enabled, Hook required KernelSU syscalls with manually-patched function.
menu "KernelSU - SUSFS"
config KSU_SUSFS
bool "KernelSU addon - SUSFS"
depends on KSU
depends on THREAD_INFO_IN_TASK
default y
help
Patch and Enable SUSFS to kernel with KernelSU.
config KSU_SUSFS_SUS_PATH
bool "Enable to hide suspicious path (NOT recommended)"
depends on KSU_SUSFS
default y
help
- Allow hiding the user-defined path and all its sub-paths from various system calls.
- tmpfs filesystem is not allowed to be added.
- Effective only on zygote spawned user app process.
- Use with cautious as it may cause performance loss and will be vulnerable to side channel attacks,
just disable this feature if it doesn't work for you or you don't need it at all.
config KSU_SUSFS_SUS_MOUNT
bool "Enable to hide suspicious mounts"
depends on KSU_SUSFS
default y
help
- Allow hiding the user-defined mount paths from /proc/self/[mounts|mountinfo|mountstat].
- Effective on all processes for hiding mount entries.
- Mounts mounted by process with ksu domain will be forced to be assigned the dev name "KSU".
- mnt_id and mnt_group_id of the sus mount will be assigned to a much bigger number to solve the issue of id not being contiguous.
config KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
bool "Enable to hide KSU's default mounts automatically (experimental)"
depends on KSU_SUSFS_SUS_MOUNT
default y
help
- Automatically add KSU's default mounts to sus_mount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
bool "Enable to hide suspicious bind mounts automatically (experimental)"
depends on KSU_SUSFS_SUS_MOUNT
default y
help
- Automatically add binded mounts to sus_mount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_SUS_KSTAT
bool "Enable to spoof suspicious kstat"
depends on KSU_SUSFS
default y
help
- Allow spoofing the kstat of user-defined file/directory.
- Effective only on zygote spawned user app process.
config KSU_SUSFS_TRY_UMOUNT
bool "Enable to use ksu's try_umount"
depends on KSU_SUSFS
default y
help
- Allow using try_umount to umount other user-defined mount paths prior to ksu's default umount paths.
- Effective on all NO-root-access-granted processes.
config KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
bool "Enable to add bind mounts to ksu's try_umount automatically (experimental)"
depends on KSU_SUSFS_TRY_UMOUNT
default y
help
- Automatically add binded mounts to ksu's try_umount.
- No susfs command is needed in userspace.
- Only mount operation from process with ksu domain will be checked.
config KSU_SUSFS_SPOOF_UNAME
bool "Enable to spoof uname"
depends on KSU_SUSFS
default y
help
- Allow spoofing the string returned by uname syscall to user-defined string.
- Effective on all processes.
config KSU_SUSFS_ENABLE_LOG
bool "Enable logging susfs log to kernel"
depends on KSU_SUSFS
default y
help
- Allow logging susfs log to kernel, uncheck it to completely disable all susfs log.
config KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
bool "Enable to automatically hide ksu and susfs symbols from /proc/kallsyms"
depends on KSU_SUSFS
default y
help
- Automatically hide ksu and susfs symbols from '/proc/kallsyms'.
- Effective on all processes.
config KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
bool "Enable to spoof /proc/bootconfig (gki) or /proc/cmdline (non-gki)"
depends on KSU_SUSFS
default y
help
- Spoof the output of /proc/bootconfig (gki) or /proc/cmdline (non-gki) with a user-defined file.
- Effective on all processes.
config KSU_SUSFS_OPEN_REDIRECT
bool "Enable to redirect a path to be opened with another path (experimental)"
depends on KSU_SUSFS
default y
help
- Allow redirecting a target path to be opened with another user-defined path.
- Effective only on processes with uid < 2000.
- Please be reminded that process with open access to the target and redirected path can be detected.
config KSU_SUSFS_SUS_SU
bool "Enable SUS-SU in runtime temporarily"
depends on KSU_SUSFS && KPROBES && HAVE_KPROBES && KPROBE_EVENTS
default y
help
- Allow user to enable or disable core ksu kprobes hooks temporarily in runtime. There are 2 working modes for sus_su.
- Mode 0 (default): Disable sus_su, and enable ksu kprobe hooks for su instead.
- Mode 1 (deprecated):
- Mode 2: Enable sus_su, and disable ksu kprobe hooks for su, which means the kernel inline hooks are enabled,
the same as the su implementaion of non-gki kernel without kprobe supported.
- Only apps with root access granted by ksu manager are allowed to get root.
config KSU_SUSFS_SUS_MAP
bool "Enable to hide some mmapped real file from different proc maps interfaces"
depends on KSU_SUSFS
default y
help
- Allow hiding mmapped real file from /proc/<pid>/[maps|smaps|smaps_rollup|map_files|mem|pagemap]
- It does NOT support hiding for anon memory.
- It does NOT hide any inline hooks or plt hooks cause by the injected library itself.
- It may not be able to evade detections by apps that implement a good injection detection.
- Effective only on zygote spawned umounted user app process.
endmenu
endmenu endmenu

View File

@@ -184,14 +184,4 @@ $(info -- Supported Unofficial Manager: 5ec1cff (GKI) rsuntk (Non-GKI) ShirkNeko
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function -Wno-unused-variable ccflags-y += -Wno-declaration-after-statement -Wno-unused-function -Wno-unused-variable
## For susfs stuff ##
ifeq ($(shell test -e $(srctree)/fs/susfs.c; echo $$?),0)
$(eval SUSFS_VERSION=$(shell cat $(srctree)/include/linux/susfs.h | grep -E '^#define SUSFS_VERSION' | cut -d' ' -f3 | sed 's/"//g'))
$(info )
$(info -- SUSFS_VERSION: $(SUSFS_VERSION))
else
$(info -- You have not integrate susfs in your kernel.)
$(info -- Read: https://gitlab.com/simonpunk/susfs4ksu)
endif
# Keep a new line here!! Because someone may append config # Keep a new line here!! Because someone may append config

View File

@@ -11,11 +11,6 @@
#include <linux/printk.h> #include <linux/printk.h>
#include <linux/types.h> #include <linux/types.h>
#ifdef CONFIG_KSU_SUSFS
#include <linux/susfs.h>
#include <linux/susfs_def.h>
#endif // #ifdef CONFIG_KSU_SUSFS
#include "manager.h" #include "manager.h"
#include "kernel_umount.h" #include "kernel_umount.h"
#include "klog.h" // IWYU pragma: keep #include "klog.h" // IWYU pragma: keep
@@ -26,79 +21,6 @@
#include "sulog.h" #include "sulog.h"
#ifdef CONFIG_KSU_SUSFS
extern u32 susfs_zygote_sid;
extern bool susfs_is_mnt_devname_ksu(struct path *path);
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
extern void susfs_run_sus_path_loop(uid_t uid);
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
extern bool susfs_is_log_enabled __read_mostly;
#endif // #ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
static bool susfs_is_umount_for_zygote_system_process_enabled = false;
static bool susfs_is_umount_for_zygote_iso_service_enabled = false;
extern void susfs_reorder_mnt_id(void);
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
extern bool susfs_is_auto_add_sus_bind_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
extern bool susfs_is_auto_add_sus_ksu_default_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
extern bool susfs_is_auto_add_try_umount_for_bind_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
static inline void susfs_on_post_fs_data(void) {
struct path path;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (!kern_path(DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS, 0, &path)) {
susfs_is_umount_for_zygote_system_process_enabled = true;
path_put(&path);
}
pr_info("susfs_is_umount_for_zygote_system_process_enabled: %d\n", susfs_is_umount_for_zygote_system_process_enabled);
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
if (!kern_path(DATA_ADB_NO_AUTO_ADD_SUS_BIND_MOUNT, 0, &path)) {
susfs_is_auto_add_sus_bind_mount_enabled = false;
path_put(&path);
}
pr_info("susfs_is_auto_add_sus_bind_mount_enabled: %d\n", susfs_is_auto_add_sus_bind_mount_enabled);
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
if (!kern_path(DATA_ADB_NO_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT, 0, &path)) {
susfs_is_auto_add_sus_ksu_default_mount_enabled = false;
path_put(&path);
}
pr_info("susfs_is_auto_add_sus_ksu_default_mount_enabled: %d\n", susfs_is_auto_add_sus_ksu_default_mount_enabled);
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
if (!kern_path(DATA_ADB_NO_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT, 0, &path)) {
susfs_is_auto_add_try_umount_for_bind_mount_enabled = false;
path_put(&path);
}
pr_info("susfs_is_auto_add_try_umount_for_bind_mount_enabled: %d\n", susfs_is_auto_add_try_umount_for_bind_mount_enabled);
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
}
static inline bool is_some_system_uid(uid_t uid)
{
return (uid >= 1000 && uid < 10000);
}
static inline bool is_zygote_isolated_service_uid(uid_t uid)
{
return ((uid >= 90000 && uid < 100000) || (uid >= 1090000 && uid < 1100000));
}
static inline bool is_zygote_normal_app_uid(uid_t uid)
{
return ((uid >= 10000 && uid < 19999) || (uid >= 1010000 && uid < 1019999));
}
#endif // #ifdef CONFIG_KSU_SUSFS
static bool ksu_kernel_umount_enabled = true; static bool ksu_kernel_umount_enabled = true;
static int kernel_umount_feature_get(u64 *value) static int kernel_umount_feature_get(u64 *value)
@@ -132,15 +54,12 @@ static bool should_umount(struct path *path)
pr_info("ignore global mnt namespace process: %d\n", current_uid().val); pr_info("ignore global mnt namespace process: %d\n", current_uid().val);
return false; return false;
} }
#ifdef CONFIG_KSU_SUSFS
return susfs_is_mnt_devname_ksu(path);
#else
if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) { if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) {
const char *fstype = path->mnt->mnt_sb->s_type->name; const char *fstype = path->mnt->mnt_sb->s_type->name;
return strcmp(fstype, "overlay") == 0; return strcmp(fstype, "overlay") == 0;
} }
return false; return false;
#endif
} }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_HAS_PATH_UMOUNT) #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0) || defined(KSU_HAS_PATH_UMOUNT)
@@ -178,12 +97,7 @@ static int ksu_sys_umount(const char *mnt, int flags)
}) })
#endif #endif
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
void try_umount(const char *mnt, bool check_mnt, int flags, uid_t uid)
#else
void try_umount(const char *mnt, bool check_mnt, int flags) void try_umount(const char *mnt, bool check_mnt, int flags)
#endif
{ {
struct path path; struct path path;
int ret; int ret;
@@ -204,12 +118,6 @@ void try_umount(const char *mnt, bool check_mnt, int flags)
return; return;
} }
#if defined(CONFIG_KSU_SUSFS_TRY_UMOUNT) && defined(CONFIG_KSU_SUSFS_ENABLE_LOG)
if (susfs_is_log_enabled) {
pr_info("susfs: umounting '%s' for uid: %d\n", mnt, uid);
}
#endif
ret = ksu_umount_mnt(mnt, &path, flags); ret = ksu_umount_mnt(mnt, &path, flags);
if (ret) { if (ret) {
#ifdef CONFIG_KSU_DEBUG #ifdef CONFIG_KSU_DEBUG
@@ -218,78 +126,11 @@ void try_umount(const char *mnt, bool check_mnt, int flags)
} }
} }
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
void susfs_try_umount_all(uid_t uid) {
susfs_try_umount(uid);
/* For Legacy KSU only */
try_umount("/odm", true, 0, uid);
try_umount("/system", true, 0, uid);
try_umount("/vendor", true, 0, uid);
try_umount("/product", true, 0, uid);
try_umount("/system_ext", true, 0, uid);
// - For '/data/adb/modules' we pass 'false' here because it is a loop device that we can't determine whether
// its dev_name is KSU or not, and it is safe to just umount it if it is really a mountpoint
try_umount("/data/adb/modules", false, MNT_DETACH, uid);
try_umount("/data/adb/kpm", false, MNT_DETACH, uid);
/* For both Legacy KSU and Magic Mount KSU */
try_umount("/debug_ramdisk", true, MNT_DETACH, uid);
try_umount("/sbin", false, MNT_DETACH, uid);
// try umount hosts file
try_umount("/system/etc/hosts", false, MNT_DETACH, uid);
// try umount lsposed dex2oat bins
try_umount("/apex/com.android.art/bin/dex2oat64", false, MNT_DETACH, uid);
try_umount("/apex/com.android.art/bin/dex2oat32", false, MNT_DETACH, uid);
}
#endif
struct umount_tw { struct umount_tw {
struct callback_head cb; struct callback_head cb;
const struct cred *old_cred; const struct cred *old_cred;
}; };
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
static void umount_tw_func(struct callback_head *cb)
{
struct umount_tw *tw = container_of(cb, struct umount_tw, cb);
const struct cred *saved = NULL;
if (tw->old_cred) {
saved = override_creds(tw->old_cred);
}
uid_t uid = current_uid().val;
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
// filter the mountpoint whose target is `/data/adb`
try_umount("/odm", true, 0, uid);
try_umount("/system", true, 0, uid);
try_umount("/vendor", true, 0, uid);
try_umount("/product", true, 0, uid);
try_umount("/system_ext", true, 0, uid);
try_umount("/data/adb/modules", false, MNT_DETACH, uid);
try_umount("/data/adb/kpm", false, MNT_DETACH, uid);
// try umount ksu temp path
try_umount("/debug_ramdisk", false, MNT_DETACH, uid);
try_umount("/sbin", false, MNT_DETACH, uid);
// try umount lsposed dex2oat bins
try_umount("/system/etc/hosts", false, MNT_DETACH, uid);
// try umount lsposed dex2oat bins
try_umount("/apex/com.android.art/bin/dex2oat64", false, MNT_DETACH, uid);
try_umount("/apex/com.android.art/bin/dex2oat32", false, MNT_DETACH, uid);
if (saved)
revert_creds(saved);
if (tw->old_cred)
put_cred(tw->old_cred);
kfree(tw);
}
#else
static void umount_tw_func(struct callback_head *cb) static void umount_tw_func(struct callback_head *cb)
{ {
struct umount_tw *tw = container_of(cb, struct umount_tw, cb); struct umount_tw *tw = container_of(cb, struct umount_tw, cb);
@@ -324,7 +165,6 @@ static void umount_tw_func(struct callback_head *cb)
kfree(tw); kfree(tw);
} }
#endif
static inline bool is_appuid(uid_t uid) static inline bool is_appuid(uid_t uid)
{ {
@@ -343,109 +183,6 @@ static inline bool is_unsupported_uid(uid_t uid)
return appid > LAST_APPLICATION_UID; return appid > LAST_APPLICATION_UID;
} }
#ifdef CONFIG_KSU_SUSFS
int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
{
struct umount_tw *tw;
// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
if (!ksu_module_mounted) {
return 0;
}
if (!ksu_kernel_umount_enabled) {
return 0;
}
if (!is_appuid(new_uid) || is_unsupported_uid(new_uid)) {
pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid);
return 0;
}
if (!ksu_uid_should_umount(new_uid)) {
return 0;
} else {
pr_info("uid: %d should not umount!\n", current_uid().val);
}
// We only interest in process spwaned by zygote
if (!susfs_is_sid_equal(current->cred->security, susfs_zygote_sid)) {
return 0;
}
// Check if spawned process is isolated service first, and force to do umount if so
if (is_zygote_isolated_service_uid(new_uid) && susfs_is_umount_for_zygote_iso_service_enabled) {
goto do_umount;
}
// - Since ksu maanger app uid is excluded in allow_list_arr, so ksu_uid_should_umount(manager_uid)
// will always return true, that's why we need to explicitly check if new_uid.val belongs to
// ksu manager
if (ksu_is_manager_uid_valid() &&
(new_uid % 1000000 == ksu_get_manager_uid())) // % 1000000 in case it is private space uid
{
return 0;
}
// Check if spawned process is normal user app and needs to be umounted
if (likely(is_zygote_normal_app_uid(new_uid) && ksu_uid_should_umount(new_uid))) {
goto do_umount;
}
// Lastly, Check if spawned process is some system process and needs to be umounted
if (unlikely(is_some_system_uid(new_uid) && susfs_is_umount_for_zygote_system_process_enabled)) {
goto do_umount;
}
#if __SULOG_GATE
ksu_sulog_report_syscall(new_uid, NULL, "setuid", NULL);
#endif
return 0;
do_umount:
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
// susfs come first, and lastly umount by ksu, make sure umount in reversed order
susfs_try_umount_all(new_uid);
#else
tw = kmalloc(sizeof(*tw), GFP_ATOMIC);
if (!tw)
return 0;
tw->old_cred = get_current_cred();
tw->cb.func = umount_tw_func;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0)
int err = task_work_add(current, &tw->cb, TWA_RESUME);
#else
int err = task_work_add(current, &tw->cb, true);
#endif
if (err) {
if (tw->old_cred) {
put_cred(tw->old_cred);
}
kfree(tw);
pr_warn("unmount add task_work failed\n");
}
#endif // #ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
get_task_struct(current);
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
// We can reorder the mnt_id now after all sus mounts are umounted
susfs_reorder_mnt_id();
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
susfs_set_current_proc_umounted();
put_task_struct(current);
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
susfs_run_sus_path_loop(new_uid);
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
return 0;
}
#else
int ksu_handle_umount(uid_t old_uid, uid_t new_uid) int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
{ {
struct umount_tw *tw; struct umount_tw *tw;
@@ -506,7 +243,6 @@ int ksu_handle_umount(uid_t old_uid, uid_t new_uid)
return 0; return 0;
} }
#endif
void ksu_kernel_umount_init(void) void ksu_kernel_umount_init(void)
{ {

View File

@@ -6,10 +6,6 @@
void ksu_kernel_umount_init(void); void ksu_kernel_umount_init(void);
void ksu_kernel_umount_exit(void); void ksu_kernel_umount_exit(void);
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
void susfs_try_umount_all(uid_t uid);
#endif
// Handler function to be called from setresuid hook // Handler function to be called from setresuid hook
int ksu_handle_umount(uid_t old_uid, uid_t new_uid); int ksu_handle_umount(uid_t old_uid, uid_t new_uid);

View File

@@ -17,10 +17,6 @@
#include "throne_comm.h" #include "throne_comm.h"
#include "dynamic_manager.h" #include "dynamic_manager.h"
#ifdef CONFIG_KSU_SUSFS
#include <linux/susfs.h>
#endif
static struct workqueue_struct *ksu_workqueue; static struct workqueue_struct *ksu_workqueue;
bool ksu_queue_work(struct work_struct *work) bool ksu_queue_work(struct work_struct *work)
@@ -54,10 +50,6 @@ int __init kernelsu_init(void)
pr_alert("*************************************************************"); pr_alert("*************************************************************");
#endif #endif
#ifdef CONFIG_KSU_SUSFS
susfs_init();
#endif
ksu_feature_init(); ksu_feature_init();
ksu_supercalls_init(); ksu_supercalls_init();

View File

@@ -75,10 +75,6 @@ bool ksu_input_hook __read_mostly = true;
#endif #endif
bool ksu_execveat_hook __read_mostly = true; bool ksu_execveat_hook __read_mostly = true;
#ifdef CONFIG_KSU_SUSFS_SUS_SU
bool susfs_is_sus_su_ready = false;
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
u32 ksu_file_sid; u32 ksu_file_sid;
// Detect whether it is on or not // Detect whether it is on or not
@@ -752,10 +748,6 @@ static void stop_execve_hook(void)
pr_info("stop execve_hook\n"); pr_info("stop execve_hook\n");
ksu_execveat_hook = false; ksu_execveat_hook = false;
#endif #endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
susfs_is_sus_su_ready = true;
pr_info("susfs: sus_su is ready\n");
#endif
} }
static void stop_input_hook(void) static void stop_input_hook(void)

View File

@@ -142,15 +142,6 @@ void apply_kernelsu_rules(void)
// https://android-review.googlesource.com/c/platform/system/logging/+/3725346 // https://android-review.googlesource.com/c/platform/system/logging/+/3725346
ksu_dontaudit(db, "untrusted_app", KERNEL_SU_DOMAIN, "dir", "getattr"); ksu_dontaudit(db, "untrusted_app", KERNEL_SU_DOMAIN, "dir", "getattr");
#ifdef CONFIG_KSU_SUSFS
// Allow umount in zygote process without installing zygisk
ksu_allow(db, "zygote", "labeledfs", "filesystem", "unmount");
susfs_set_kernel_sid();
susfs_set_init_sid();
susfs_set_ksu_sid();
susfs_set_zygote_sid();
#endif
mutex_unlock(&ksu_rules); mutex_unlock(&ksu_rules);
} }

View File

@@ -6,16 +6,6 @@
#define KERNEL_SU_DOMAIN "u:r:su:s0" #define KERNEL_SU_DOMAIN "u:r:su:s0"
#ifdef CONFIG_KSU_SUSFS
#define KERNEL_INIT_DOMAIN "u:r:init:s0"
#define KERNEL_ZYGOTE_DOMAIN "u:r:zygote:s0"
#define KERNEL_KERNEL_DOMAIN "u:r:kernel:s0"
u32 susfs_ksu_sid = 0;
u32 susfs_init_sid = 0;
u32 susfs_zygote_sid = 0;
u32 susfs_kernel_sid = 0;
#endif
static int transive_to_domain(const char *domain) static int transive_to_domain(const char *domain)
{ {
struct cred *cred; struct cred *cred;
@@ -155,88 +145,6 @@ bool is_zygote(const struct cred* cred)
return result; return result;
} }
#ifdef CONFIG_KSU_SUSFS
static inline void susfs_set_sid(const char *secctx_name, u32 *out_sid)
{
int err;
if (!secctx_name || !out_sid) {
pr_err("secctx_name || out_sid is NULL\n");
return;
}
err = security_secctx_to_secid(secctx_name, strlen(secctx_name),
out_sid);
if (err) {
pr_err("failed setting sid for '%s', err: %d\n", secctx_name, err);
return;
}
pr_info("sid '%u' is set for secctx_name '%s'\n", *out_sid, secctx_name);
}
bool susfs_is_sid_equal(void *sec, u32 sid2) {
struct task_security_struct *tsec = (struct task_security_struct *)sec;
if (!tsec) {
return false;
}
return tsec->sid == sid2;
}
u32 susfs_get_sid_from_name(const char *secctx_name)
{
u32 out_sid = 0;
int err;
if (!secctx_name) {
pr_err("secctx_name is NULL\n");
return 0;
}
err = security_secctx_to_secid(secctx_name, strlen(secctx_name),
&out_sid);
if (err) {
pr_err("failed getting sid from secctx_name: %s, err: %d\n", secctx_name, err);
return 0;
}
return out_sid;
}
u32 susfs_get_current_sid(void) {
return current_sid();
}
void susfs_set_zygote_sid(void)
{
susfs_set_sid(KERNEL_ZYGOTE_DOMAIN, &susfs_zygote_sid);
}
bool susfs_is_current_zygote_domain(void) {
return unlikely(current_sid() == susfs_zygote_sid);
}
void susfs_set_ksu_sid(void)
{
susfs_set_sid(KERNEL_SU_DOMAIN, &susfs_ksu_sid);
}
bool susfs_is_current_ksu_domain(void) {
return unlikely(current_sid() == susfs_ksu_sid);
}
void susfs_set_init_sid(void)
{
susfs_set_sid(KERNEL_INIT_DOMAIN, &susfs_init_sid);
}
bool susfs_is_current_init_domain(void) {
return unlikely(current_sid() == susfs_init_sid);
}
void susfs_set_kernel_sid(void)
{
susfs_set_sid(KERNEL_KERNEL_DOMAIN, &susfs_kernel_sid);
}
#endif
#define KSU_FILE_DOMAIN "u:object_r:ksu_file:s0" #define KSU_FILE_DOMAIN "u:object_r:ksu_file:s0"
u32 ksu_get_ksu_file_sid() u32 ksu_get_ksu_file_sid()

View File

@@ -23,18 +23,6 @@ bool is_zygote(const struct cred* cred);
void apply_kernelsu_rules(void); void apply_kernelsu_rules(void);
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
bool susfs_is_sid_equal(void *sec, u32 sid2);
u32 susfs_get_sid_from_name(const char *secctx_name);
u32 susfs_get_current_sid(void);
void susfs_set_zygote_sid(void);
bool susfs_is_current_zygote_domain(void);
void susfs_set_ksu_sid(void);
bool susfs_is_current_ksu_domain(void);
void susfs_set_init_sid(void);
bool susfs_is_current_init_domain(void);
#endif
u32 ksu_get_ksu_file_sid(void); u32 ksu_get_ksu_file_sid(void);
int handle_sepolicy(unsigned long arg3, void __user *arg4); int handle_sepolicy(unsigned long arg3, void __user *arg4);

View File

@@ -45,11 +45,6 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#endif #endif
#ifdef CONFIG_KSU_SUSFS
#include <linux/susfs.h>
#include <linux/susfs_def.h>
#endif // #ifdef CONFIG_KSU_SUSFS
#include "allowlist.h" #include "allowlist.h"
#include "setuid_hook.h" #include "setuid_hook.h"
#include "feature.h" #include "feature.h"
@@ -87,28 +82,6 @@ static const struct ksu_feature_handler enhanced_security_handler = {
.set_handler = enhanced_security_feature_set, .set_handler = enhanced_security_feature_set,
}; };
#ifdef CONFIG_KSU_SUSFS
bool susfs_is_boot_completed_triggered = false;
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
static bool susfs_is_umount_for_zygote_system_process_enabled = false;
static bool susfs_is_umount_for_zygote_iso_service_enabled = false;
extern bool susfs_hide_sus_mnts_for_all_procs;
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
extern bool susfs_is_auto_add_sus_bind_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
extern bool susfs_is_auto_add_sus_ksu_default_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
#ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
extern bool susfs_is_auto_add_try_umount_for_bind_mount_enabled;
#endif // #ifdef CONFIG_KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
#ifdef CONFIG_KSU_SUSFS_SUS_SU
extern bool susfs_is_sus_su_ready;
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
#endif // #ifdef CONFIG_KSU_SUSFS
static inline bool is_allow_su(void) static inline bool is_allow_su(void)
{ {
if (is_manager()) { if (is_manager()) {
@@ -135,300 +108,6 @@ static bool is_appuid(uid_t uid)
return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID; return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID;
} }
#if __SULOG_GATE
static void sulog_prctl_cmd(uid_t uid, unsigned long cmd)
{
const char *name = NULL;
switch (cmd) {
#ifdef CONFIG_KSU_SUSFS
case CMD_SUSFS_ADD_SUS_PATH: name = "prctl_susfs_add_sus_path"; break;
case CMD_SUSFS_ADD_SUS_PATH_LOOP: name = "prctl_susfs_add_sus_path_loop"; break;
case CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH: name = "prctl_susfs_set_android_data_root_path"; break;
case CMD_SUSFS_SET_SDCARD_ROOT_PATH: name = "prctl_susfs_set_sdcard_root_path"; break;
case CMD_SUSFS_ADD_SUS_MOUNT: name = "prctl_susfs_add_sus_mount"; break;
case CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS: name = "prctl_susfs_hide_sus_mnts_for_all_procs"; break;
case CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE: name = "prctl_susfs_umount_for_zygote_iso_service"; break;
case CMD_SUSFS_ADD_SUS_KSTAT: name = "prctl_susfs_add_sus_kstat"; break;
case CMD_SUSFS_UPDATE_SUS_KSTAT: name = "prctl_susfs_update_sus_kstat"; break;
case CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY: name = "prctl_susfs_add_sus_kstat_statically"; break;
case CMD_SUSFS_ADD_TRY_UMOUNT: name = "prctl_susfs_add_try_umount"; break;
case CMD_SUSFS_SET_UNAME: name = "prctl_susfs_set_uname"; break;
case CMD_SUSFS_ENABLE_LOG: name = "prctl_susfs_enable_log"; break;
case CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG: name = "prctl_susfs_set_cmdline_or_bootconfig"; break;
case CMD_SUSFS_ADD_OPEN_REDIRECT: name = "prctl_susfs_add_open_redirect"; break;
case CMD_SUSFS_SHOW_VERSION: name = "prctl_susfs_show_version"; break;
case CMD_SUSFS_SHOW_ENABLED_FEATURES: name = "prctl_susfs_show_enabled_features"; break;
case CMD_SUSFS_SHOW_VARIANT: name = "prctl_susfs_show_variant"; break;
#ifdef CONFIG_KSU_SUSFS_SUS_SU
case CMD_SUSFS_SUS_SU: name = "prctl_susfs_sus_su"; break;
case CMD_SUSFS_IS_SUS_SU_READY: name = "prctl_susfs_is_sus_su_ready"; break;
case CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE: name = "prctl_susfs_show_sus_su_working_mode"; break;
#endif
case CMD_SUSFS_ADD_SUS_MAP: name = "prctl_susfs_add_sus_map"; break;
case CMD_SUSFS_ENABLE_AVC_LOG_SPOOFING: name = "prctl_susfs_enable_avc_log_spoofing"; break;
#endif
default: name = "prctl_unknown"; break;
}
ksu_sulog_report_syscall(uid, NULL, name, NULL);
}
#endif
int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5)
{
#ifdef CONFIG_KSU_SUSFS
// - We straight up check if process is supposed to be umounted, return 0 if so
// - This is to prevent side channel attack as much as possible
if (likely(susfs_is_current_proc_umounted()))
return 0;
#endif
// if success, we modify the arg5 as result!
u32 *result = (u32 *)arg5;
u32 reply_ok = KERNEL_SU_OPTION;
if (KERNEL_SU_OPTION != option) {
return 0;
}
bool from_root = 0 == current_uid().val;
bool from_manager = is_manager();
#if __SULOG_GATE
sulog_prctl_cmd(current_uid().val, arg2);
#endif
if (!from_root && !from_manager && !is_allow_su()) {
// only root or manager can access this interface
return 0;
}
#ifdef CONFIG_KSU_DEBUG
pr_info("option: 0x%x, cmd: %ld\n", option, arg2);
#endif
#ifdef CONFIG_KSU_SUSFS
int susfs_cmd_err = 0;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (arg2 == CMD_SUSFS_ADD_SUS_PATH) {
susfs_cmd_err = susfs_add_sus_path((struct st_susfs_sus_path __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_PATH -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_ADD_SUS_PATH_LOOP) {
susfs_cmd_err = susfs_add_sus_path_loop((struct st_susfs_sus_path __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_PATH_LOOP -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH) {
susfs_cmd_err = susfs_set_i_state_on_external_dir((char __user*)arg3, CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH);
pr_info("susfs: CMD_SUSFS_SET_ANDROID_DATA_ROOT_PATH -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SET_SDCARD_ROOT_PATH) {
susfs_cmd_err = susfs_set_i_state_on_external_dir((char __user*)arg3, CMD_SUSFS_SET_SDCARD_ROOT_PATH);
pr_info("susfs: CMD_SUSFS_SET_SDCARD_ROOT_PATH -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_PATH
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (arg2 == CMD_SUSFS_ADD_SUS_MOUNT) {
susfs_cmd_err = susfs_add_sus_mount((struct st_susfs_sus_mount __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS) {
if (arg3 != 0 && arg3 != 1) {
pr_err("susfs: CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS -> arg3 can only be 0 or 1\n");
return 0;
}
susfs_hide_sus_mnts_for_all_procs = arg3;
pr_info("susfs: CMD_SUSFS_HIDE_SUS_MNTS_FOR_ALL_PROCS -> susfs_hide_sus_mnts_for_all_procs: %lu\n", arg3);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE) {
if (arg3 != 0 && arg3 != 1) {
pr_err("susfs: CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE -> arg3 can only be 0 or 1\n");
return 0;
}
susfs_is_umount_for_zygote_iso_service_enabled = arg3;
pr_info("susfs: CMD_SUSFS_UMOUNT_FOR_ZYGOTE_ISO_SERVICE -> susfs_is_umount_for_zygote_iso_service_enabled: %lu\n", arg3);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT) {
susfs_cmd_err = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_UPDATE_SUS_KSTAT) {
susfs_cmd_err = susfs_update_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY) {
susfs_cmd_err = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
if (arg2 == CMD_SUSFS_ADD_TRY_UMOUNT) {
susfs_cmd_err = susfs_add_try_umount((struct st_susfs_try_umount __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
if (arg2 == CMD_SUSFS_SET_UNAME) {
susfs_cmd_err = susfs_set_uname((struct st_susfs_uname __user*)arg3);
pr_info("susfs: CMD_SUSFS_SET_UNAME -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
if (arg2 == CMD_SUSFS_ENABLE_LOG) {
if (arg3 != 0 && arg3 != 1) {
pr_err("susfs: CMD_SUSFS_ENABLE_LOG -> arg3 can only be 0 or 1\n");
return 0;
}
susfs_set_log(arg3);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
if (arg2 == CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG) {
susfs_cmd_err = susfs_set_cmdline_or_bootconfig((char __user*)arg3);
pr_info("susfs: CMD_SUSFS_SET_CMDLINE_OR_BOOTCONFIG -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SPOOF_CMDLINE_OR_BOOTCONFIG
#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
if (arg2 == CMD_SUSFS_ADD_OPEN_REDIRECT) {
susfs_cmd_err = susfs_add_open_redirect((struct st_susfs_open_redirect __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_OPEN_REDIRECT -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_OPEN_REDIRECT
#ifdef CONFIG_KSU_SUSFS_SUS_SU
if (arg2 == CMD_SUSFS_SUS_SU) {
susfs_cmd_err = susfs_sus_su((struct st_sus_su __user*)arg3);
pr_info("susfs: CMD_SUSFS_SUS_SU -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_SU
if (arg2 == CMD_SUSFS_SHOW_VERSION) {
int len_of_susfs_version = strlen(SUSFS_VERSION);
char *susfs_version = SUSFS_VERSION;
susfs_cmd_err = copy_to_user((void __user*)arg3, (void*)susfs_version, len_of_susfs_version+1);
pr_info("susfs: CMD_SUSFS_SHOW_VERSION -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SHOW_ENABLED_FEATURES) {
if (arg4 <= 0) {
pr_err("susfs: CMD_SUSFS_SHOW_ENABLED_FEATURES -> arg4 cannot be <= 0\n");
return 0;
}
susfs_cmd_err = susfs_get_enabled_features((char __user*)arg3, arg4);
pr_info("susfs: CMD_SUSFS_SHOW_ENABLED_FEATURES -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SHOW_VARIANT) {
int len_of_variant = strlen(SUSFS_VARIANT);
char *susfs_variant = SUSFS_VARIANT;
susfs_cmd_err = copy_to_user((void __user*)arg3, (void*)susfs_variant, len_of_variant+1);
pr_info("susfs: CMD_SUSFS_SHOW_VARIANT -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#ifdef CONFIG_KSU_SUSFS_SUS_SU
if (arg2 == CMD_SUSFS_IS_SUS_SU_READY) {
susfs_cmd_err = copy_to_user((void __user*)arg3, (void*)&susfs_is_sus_su_ready, sizeof(susfs_is_sus_su_ready));
pr_info("susfs: CMD_SUSFS_IS_SUS_SU_READY -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
if (arg2 == CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE) {
int working_mode = susfs_get_sus_su_working_mode();
susfs_cmd_err = copy_to_user((void __user*)arg3, (void*)&working_mode, sizeof(working_mode));
pr_info("susfs: CMD_SUSFS_SHOW_SUS_SU_WORKING_MODE -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
#ifdef CONFIG_KSU_SUSFS_SUS_MAP
if (arg2 == CMD_SUSFS_ADD_SUS_MAP) {
susfs_cmd_err = susfs_add_sus_map((struct st_susfs_sus_map __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_MAP -> ret: %d\n", susfs_cmd_err);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MAP
if (arg2 == CMD_SUSFS_ENABLE_AVC_LOG_SPOOFING) {
if (arg3 != 0 && arg3 != 1) {
pr_err("susfs: CMD_SUSFS_ENABLE_AVC_LOG_SPOOFING -> arg3 can only be 0 or 1\n");
return 0;
}
susfs_set_avc_log_spoofing(arg3);
if (copy_to_user((void __user*)arg5, &susfs_cmd_err, sizeof(susfs_cmd_err)))
pr_info("susfs: copy_to_user() failed\n");
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS
return 0;
}
int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid) int ksu_handle_setresuid(uid_t ruid, uid_t euid, uid_t suid)
{ {
uid_t new_uid = ruid; uid_t new_uid = ruid;

View File

@@ -12,9 +12,6 @@
#else #else
#include <linux/sched.h> #include <linux/sched.h>
#endif #endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
#include <linux/susfs_def.h>
#endif
#include "allowlist.h" #include "allowlist.h"
#include "feature.h" #include "feature.h"
@@ -25,7 +22,6 @@
#include "syscall_hook_manager.h" #include "syscall_hook_manager.h"
#include "sulog.h" #include "sulog.h"
#include "kernel_compat.h"
#define SU_PATH "/system/bin/su" #define SU_PATH "/system/bin/su"
#define SH_PATH "/system/bin/sh" #define SH_PATH "/system/bin/sh"
@@ -41,10 +37,8 @@ static int su_compat_feature_get(u64 *value)
static int su_compat_feature_set(u64 value) static int su_compat_feature_set(u64 value)
{ {
bool enable = value != 0; bool enable = value != 0;
ksu_su_compat_enabled = enable; ksu_su_compat_enabled = enable;
pr_info("su_compat: set to %d\n", enable); pr_info("su_compat: set to %d\n", enable);
return 0; return 0;
} }
@@ -55,13 +49,7 @@ static const struct ksu_feature_handler su_compat_handler = {
.set_handler = su_compat_feature_set, .set_handler = su_compat_feature_set,
}; };
static const char sh_path[] = "/system/bin/sh"; static void __user *userspace_stack_buffer(const void *d, size_t len)
static const char ksud_path[] = KSUD_PATH;
static const char su[] = SU_PATH;
bool ksu_sucompat_hook_state __read_mostly = true;
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 /* To avoid having to mmap a page in userspace, just write below the stack
* pointer. */ * pointer. */
@@ -70,19 +58,24 @@ static inline void __user *userspace_stack_buffer(const void *d, size_t len)
return copy_to_user(p, d, len) ? NULL : p; return copy_to_user(p, d, len) ? NULL : p;
} }
static inline char __user *sh_user_path(void) static char __user *sh_user_path(void)
{ {
static const char sh_path[] = "/system/bin/sh";
return userspace_stack_buffer(sh_path, sizeof(sh_path)); return userspace_stack_buffer(sh_path, sizeof(sh_path));
} }
static inline char __user *ksud_user_path(void) static char __user *ksud_user_path(void)
{ {
static const char ksud_path[] = KSUD_PATH;
return userspace_stack_buffer(ksud_path, sizeof(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 ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
int *__unused_flags) int *__unused_flags)
{ {
const char su[] = SU_PATH;
#ifndef KSU_HAVE_SYSCALL_TRACEPOINTS_HOOK #ifndef KSU_HAVE_SYSCALL_TRACEPOINTS_HOOK
if (!ksu_su_compat_enabled) { if (!ksu_su_compat_enabled) {
@@ -90,19 +83,13 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
} }
#endif #endif
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid_for_current(current_uid().val)) { if (!ksu_is_allow_uid_for_current(current_uid().val)) {
return 0; return 0;
} }
#endif
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su) + 1] = {0};
#else
char path[sizeof(su) + 1]; char path[sizeof(su) + 1];
memset(path, 0, sizeof(path)); memset(path, 0, sizeof(path));
#endif strncpy_from_user_nofault(path, *filename_user, sizeof(path));
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path));
if (unlikely(!memcmp(path, su, sizeof(su)))) { if (unlikely(!memcmp(path, su, sizeof(su)))) {
#if __SULOG_GATE #if __SULOG_GATE
@@ -115,53 +102,26 @@ int ksu_handle_faccessat(int *dfd, const char __user **filename_user, int *mode,
return 0; 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;
#if __SULOG_GATE
ksu_sulog_report_syscall(current_uid().val, NULL, "vfs_fstatat", sh);
#endif
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) int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
{ {
// const char sh[] = SH_PATH;
const char su[] = SU_PATH;
#ifndef KSU_HAVE_SYSCALL_TRACEPOINTS_HOOK #ifndef KSU_HAVE_SYSCALL_TRACEPOINTS_HOOK
if (!ksu_su_compat_enabled) { if (!ksu_su_compat_enabled) {
return 0; return 0;
} }
#endif #endif
#ifndef CONFIG_KSU_SUSFS_SUS_SU
if (!ksu_is_allow_uid_for_current(current_uid().val)) { if (!ksu_is_allow_uid_for_current(current_uid().val)) {
return 0; return 0;
} }
#endif
if (unlikely(!filename_user)) { if (unlikely(!filename_user)) {
return 0; return 0;
} }
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su) + 1] = {0};
#else
char path[sizeof(su) + 1]; char path[sizeof(su) + 1];
memset(path, 0, sizeof(path)); memset(path, 0, sizeof(path));
#endif
// Remove this later!! we use syscall hook, so this will never happen!!!!! // Remove this later!! we use syscall hook, so this will never happen!!!!!
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) && 0 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0) && 0
// it becomes a `struct filename *` after 5.18 // it becomes a `struct filename *` after 5.18
@@ -176,7 +136,7 @@ int ksu_handle_stat(int *dfd, const char __user **filename_user, int *flags)
pr_info("vfs_statx su->sh!\n"); pr_info("vfs_statx su->sh!\n");
memcpy((void *)filename->name, sh, sizeof(sh)); memcpy((void *)filename->name, sh, sizeof(sh));
#else #else
ksu_strncpy_from_user_nofault(path, *filename_user, sizeof(path)); strncpy_from_user_nofault(path, *filename_user, sizeof(path));
if (unlikely(!memcmp(path, su, sizeof(su)))) { if (unlikely(!memcmp(path, su, sizeof(su)))) {
#if __SULOG_GATE #if __SULOG_GATE
@@ -196,13 +156,14 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
int *__never_use_flags) int *__never_use_flags)
{ {
struct filename *filename; struct filename *filename;
const char sh[] = KSUD_PATH;
const char su[] = SU_PATH;
#ifndef KSU_HAVE_SYSCALL_TRACEPOINTS_HOOK #ifndef KSU_HAVE_SYSCALL_TRACEPOINTS_HOOK
if (!ksu_su_compat_enabled) { if (!ksu_su_compat_enabled) {
return 0; return 0;
} }
#endif #endif
if (unlikely(!filename_ptr)) if (unlikely(!filename_ptr))
return 0; return 0;
@@ -215,28 +176,22 @@ int ksu_handle_execveat_sucompat(int *fd, struct filename **filename_ptr,
return 0; return 0;
#if __SULOG_GATE #if __SULOG_GATE
ksu_sulog_report_syscall(current_uid().val, NULL, "execve", filename->name);
#ifndef CONFIG_KSU_SUSFS_SUS_SU
bool is_allowed = ksu_is_allow_uid_for_current(current_uid().val); bool is_allowed = ksu_is_allow_uid_for_current(current_uid().val);
#endif ksu_sulog_report_syscall(current_uid().val, NULL, "execve", filename->name);
#endif
#ifndef CONFIG_KSU_SUSFS_SUS_SU if (!is_allowed) {
#if __SULOG_GATE
if (!is_allowed)
return 0; return 0;
}
ksu_sulog_report_su_attempt(current_uid().val, NULL, filename->name, is_allowed); ksu_sulog_report_su_attempt(current_uid().val, NULL, filename->name, is_allowed);
#else #else
if (!ksu_is_allow_uid_for_current(current_uid().val)) { if (!ksu_is_allow_uid_for_current(current_uid().val)) {
return 0; return 0;
} }
#endif
#endif #endif
pr_info("do_execveat_common su found\n"); pr_info("do_execveat_common su found\n");
memcpy((void *)filename->name, ksud_path, sizeof(ksud_path)); memcpy((void *)filename->name, sh, sizeof(sh));
escape_with_root_profile(); escape_with_root_profile();
@@ -253,43 +208,27 @@ int ksu_handle_execve_sucompat(int *fd, const char __user **filename_user,
void *__never_use_argv, void *__never_use_envp, void *__never_use_argv, void *__never_use_envp,
int *__never_use_flags) int *__never_use_flags)
{ {
//const char su[] = SU_PATH; const char su[] = SU_PATH;
#ifdef CONFIG_KSU_SUSFS_SUS_SU
char path[sizeof(su) + 1] = {0};
#else
char path[sizeof(su) + 1]; char path[sizeof(su) + 1];
#endif
#ifndef KSU_HAVE_SYSCALL_TRACEPOINTS_HOOK #ifndef KSU_HAVE_SYSCALL_TRACEPOINTS_HOOK
if (!ksu_su_compat_enabled) { if (!ksu_su_compat_enabled){
return 0; return 0;
} }
#endif #endif
if (unlikely(!filename_user)) if (unlikely(!filename_user))
return 0; return 0;
/* memset(path, 0, sizeof(path));
* nofault variant fails silently due to pagefault_disable strncpy_from_user_nofault(path, *filename_user, sizeof(path));
* some cpus dont really have that good speculative execution
* access_ok to substitute set_fs, we check if pointer is accessible
*/
if (!ksu_access_ok(*filename_user, sizeof(path)))
return 0;
// success = returns number of bytes and should be less than path
long len = strncpy_from_user(path, *filename_user, sizeof(path));
if (len <= 0 || len > sizeof(path))
return 0;
// strncpy_from_user_nofault does this too
path[sizeof(path) - 1] = '\0';
if (likely(memcmp(path, su, sizeof(su)))) if (likely(memcmp(path, su, sizeof(su))))
return 0; return 0;
#if __SULOG_GATE #if __SULOG_GATE
ksu_sulog_report_syscall(current_uid().val, NULL, "execve", path);
bool is_allowed = ksu_is_allow_uid_for_current(current_uid().val); bool is_allowed = ksu_is_allow_uid_for_current(current_uid().val);
ksu_sulog_report_syscall(current_uid().val, NULL, "execve", path);
if (!is_allowed) if (!is_allowed)
return 0; return 0;