Skip to content

Commit

Permalink
KernelSU: add susfs for kernelSU
Browse files Browse the repository at this point in the history
Signed-off-by: Edwiin Kusuma Jaya <[email protected]>
  • Loading branch information
kutemeikito committed Sep 26, 2024
1 parent 33b9ed3 commit eb21384
Show file tree
Hide file tree
Showing 9 changed files with 1,663 additions and 0 deletions.
450 changes: 450 additions & 0 deletions 10_enable_susfs_for_ksu.patch

Large diffs are not rendered by default.

83 changes: 83 additions & 0 deletions kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,87 @@ config KSU_DEBUG
help
Enable KernelSU debug mode.

menu "KernelSU - SUSFS"
config KSU_SUSFS
bool "KernelSU addon - SUSFS"
depends on KSU
default y
help
Patch and Enable SUSFS to kernel with KernelSU

config KSU_SUSFS_SUS_PATH
bool "Enable to hide suspicious path"
depends on KSU_SUSFS
default y
help
Allow hiding the existence of user-defined file/directory from various system calls

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]

config KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
bool "Enable to re-order mount id and parent mount id in mountinfo (experimental)"
depends on KSU_SUSFS_SUS_MOUNT
default n
help
- Enable this option will automatically and completely re-order the mount id and parent mount id in /proc/self/mountinfo
- The actual mnt_id/parent_mnt_id is not changed in kernel, only reflects on /proc/self/mountinfo
- You should not enable this if the mnt_id on your device is already not in order by default
- Moreover, be careful this feature may cause unknown system crashes / random reboot / bootloop on different kernels or devices, further testing is needed.
- Requires KSU_SUSFS_SUS_MOUNT to be ON

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

config KSU_SUSFS_SUS_MAPS
bool "Enable to spoof suspicious maps"
depends on KSU_SUSFS
default y
help
Allow spoofing the user-defined mappings in /proc/self/[maps|smaps|map_files]

config KSU_SUSFS_SUS_PROC_FD_LINK
bool "Enable to spoof suspicous symbolic links (experimental)"
depends on KSU_SUSFS
default n
help
Allow spoofing the user-defined symbolic link in /proc/self/fd/

config KSU_SUSFS_SUS_MEMFD
bool "Enable to hide or spoof suspicous memfd (experimental)"
depends on KSU_SUSFS
default n
help
Allow preventing the user-defined memfd name from being created

config KSU_SUSFS_TRY_UMOUNT
bool "Enable to use ksu's try_umount"
depends on KSU_SUSFS
default y
help
Allow using ksu's umount to umount other user-defined mount paths prior to ksu's default umount paths

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

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
endmenu

endmenu
39 changes: 39 additions & 0 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,43 @@ endif
ccflags-y += -Wno-implicit-function-declaration -Wno-strict-prototypes -Wno-int-conversion -Wno-gcc-compat
ccflags-y += -Wno-declaration-after-statement -Wno-unused-function

ifeq ($(shell test -e $(srctree)/fs/susfs.c; echo $$?),0)
ifdef KSU_SUSFS
ccflags-y += -DKSU_SUSFS
endif
ifdef KSU_SUSFS_SUS_PATH
ccflags-y += -DKSU_SUSFS_SUS_PATH
endif
ifdef KSU_SUSFS_SUS_MOUNT
ccflags-y += -DKSU_SUSFS_SUS_MOUNT
endif
ifdef KSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
ccflags-y += -DKSU_SUSFS_SUS_MOUNT_MNT_ID_REORDER
endif
ifdef KSU_SUSFS_SUS_KSTAT
ccflags-y += -DKSU_SUSFS_SUS_KSTAT
endif
ifdef KSU_SUSFS_SUS_MAPS
ccflags-y += -DKSU_SUSFS_SUS_MAPS
endif
ifdef KSU_SUSFS_SUS_PROC_FD_LINK
ccflags-y += -DKSU_SUSFS_SUS_PROC_FD_LINK
endif
ifdef KSU_SUSFS_SUS_MEMFD
ccflags-y += -DKSU_SUSFS_SUS_MEMFD
endif
ifdef KSU_SUSFS_TRY_UMOUNT
ccflags-y += -DKSU_SUSFS_TRY_UMOUNT
endif
ifdef KSU_SUSFS_SPOOF_UNAME
ccflags-y += -DKSU_SUSFS_SPOOF_UNAME
endif
ifdef KSU_SUSFS_ENABLE_LOG
ccflags-y += -DKSU_SUSFS_ENABLE_LOG
endif
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
210 changes: 210 additions & 0 deletions kernel/core_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@
#include "throne_tracker.h"
#include "kernel_compat.h"

#ifdef CONFIG_KSU_SUSFS
#include <linux/susfs.h>
#endif

static bool ksu_module_mounted = false;

extern int handle_sepolicy(unsigned long arg3, void __user *arg4);
Expand Down Expand Up @@ -376,6 +380,207 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
return 0;
}

#ifdef CONFIG_KSU_SUSFS
if (current_uid().val == 0) {
int error = 0;
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
if (arg2 == CMD_SUSFS_ADD_SUS_PATH) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_path))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_PATH -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_path((struct st_susfs_sus_path __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_PATH -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_PATH
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
if (arg2 == CMD_SUSFS_ADD_SUS_MOUNT) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_mount))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_mount((struct st_susfs_sus_mount __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_MOUNT -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
if (arg2 == CMD_SUSFS_UPDATE_SUS_KSTAT) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
pr_err("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> arg5 is not accessible\n");
return 0;
}
error = susfs_update_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_UPDATE_SUS_KSTAT -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_kstat))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_kstat((struct st_susfs_sus_kstat __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_KSTAT
#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
if (arg2 == CMD_SUSFS_ADD_SUS_MAPS) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_maps))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MAPS -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MAPS -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_maps((struct st_susfs_sus_maps __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_MAPS -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
if (arg2 == CMD_SUSFS_UPDATE_SUS_MAPS) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_maps))) {
pr_err("susfs: CMD_SUSFS_UPDATE_SUS_MAPS -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_UPDATE_SUS_MAPS -> arg5 is not accessible\n");
return 0;
}
error = susfs_update_sus_maps((struct st_susfs_sus_maps __user*)arg3);
pr_info("susfs: CMD_SUSFS_UPDATE_SUS_MAPS -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
if (arg2 == CMD_SUSFS_ADD_SUS_MAPS_STATICALLY) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_maps))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MAPS_STATICALLY -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MAPS_STATICALLY -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_maps((struct st_susfs_sus_maps __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_MAPS_STATICALLY -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MAPS
#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
if (arg2 == CMD_SUSFS_ADD_SUS_PROC_FD_LINK) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_proc_fd_link))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_PROC_FD_LINK -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_PROC_FD_LINK -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_proc_fd_link((struct st_susfs_sus_proc_fd_link __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_PROC_FD_LINK -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_PROC_FD_LINK
#ifdef CONFIG_KSU_SUSFS_SUS_MEMFD
if (arg2 == CMD_SUSFS_ADD_SUS_MEMFD) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_sus_memfd))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MEMFD -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_SUS_MEMFD -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_sus_memfd((struct st_susfs_sus_memfd __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_SUS_MEMFD -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_SUS_MEMFD
#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
if (arg2 == CMD_SUSFS_ADD_TRY_UMOUNT) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_try_umount))) {
pr_err("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> arg5 is not accessible\n");
return 0;
}
error = susfs_add_try_umount((struct st_susfs_try_umount __user*)arg3);
pr_info("susfs: CMD_SUSFS_ADD_TRY_UMOUNT -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
#ifdef CONFIG_KSU_SUSFS_SPOOF_UNAME
if (arg2 == CMD_SUSFS_SET_UNAME) {
if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_susfs_uname))) {
pr_err("susfs: CMD_SUSFS_SET_UNAME -> arg3 is not accessible\n");
return 0;
}
if (!ksu_access_ok((void __user*)arg5, sizeof(error))) {
pr_err("susfs: CMD_SUSFS_SET_UNAME -> arg5 is not accessible\n");
return 0;
}
error = susfs_set_uname((struct st_susfs_uname __user*)arg3);
pr_info("susfs: CMD_SUSFS_SET_UNAME -> ret: %d\n", error);
copy_to_user((void __user*)arg5, &error, sizeof(error));
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);
copy_to_user((void __user*)arg5, &error, sizeof(error));
return 0;
}
#endif //#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG
}
#endif //#ifdef CONFIG_KSU_SUSFS

// all other cmds are for 'root manager'
if (!from_manager) {
return 0;
Expand Down Expand Up @@ -536,6 +741,11 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
current->pid);
#endif

#ifdef CONFIG_KSU_SUSFS_TRY_UMOUNT
// susfs come first, and lastly umount by ksu, make sure umount in reversed order
susfs_try_umount(new_uid.val);
#endif

// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
// filter the mountpoint whose target is `/data/adb`
try_umount("/system", true, 0);
Expand Down
Loading

0 comments on commit eb21384

Please sign in to comment.