Skip to content

Commit

Permalink
kernel: Implement SUSFS 1.5.3
Browse files Browse the repository at this point in the history
  • Loading branch information
changhuapeng committed Dec 22, 2024
1 parent 5d73952 commit 29db0b2
Show file tree
Hide file tree
Showing 17 changed files with 840 additions and 58 deletions.
135 changes: 135 additions & 0 deletions kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,139 @@ 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 (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 on process with uid > 2000 only.
- 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 on all processes.

config KSU_SUSFS_SUS_OVERLAYFS
bool "Enable to automatically spoof kstat and kstatfs for overlayed files/directories"
depends on KSU_SUSFS
default y
help
- Automatically spoof the kstat and kstatfs for overlayed files/directories.
- No susfs command is needed in userspace.
- Effective on all processes.

config KSU_SUSFS_TRY_UMOUNT
bool "Enable to use ksu's ksu_try_umount"
depends on KSU_SUSFS
default y
help
- Allow using ksu_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 ksu_try_umount automatically (experimental)"
depends on KSU_SUSFS_TRY_UMOUNT
default y
help
- Automatically add binded mounts to ksu's ksu_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_PROC_CMDLINE
bool "Enable to spoof /proc/cmdline"
depends on KSU_SUSFS
default y
help
- Spoof the output of /proc/cmdline 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.

endmenu

endmenu
106 changes: 102 additions & 4 deletions kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,112 @@ $(info -- KernelSU Manager signature hash: $(KSU_EXPECTED_HASH))
ccflags-y += -DEXPECTED_SIZE=$(KSU_EXPECTED_SIZE)
ccflags-y += -DEXPECTED_HASH=\"$(KSU_EXPECTED_HASH)\"

ifeq ($(shell grep -q "int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
#ifeq ($(shell grep -q "int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
#ccflags-y += -DKSU_UMOUNT
#else
#$(info -- Did you know you can backport path_umount to fs/namespace.c from 5.9?)
#$(info -- Read: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#how-to-backport-path-umount)
#endif

ccflags-y += -DKSU_UMOUNT
else
$(info -- Did you know you can backport path_umount to fs/namespace.c from 5.9?)
$(info -- Read: https://kernelsu.org/guide/how-to-integrate-for-non-gki.html#how-to-backport-path-umount)

ifneq ($(shell grep -Eq "^static int can_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(info -- KSU_SUSFS: adding function 'static int can_umount(const struct path *path, int flags);' to $(srctree)/fs/namespace.c)
CAN_UMOUNT = static int can_umount(const struct path *path, int flags)\n\
{\n\t\
struct mount *mnt = real_mount(path->mnt);\n\t\
if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))\n\t\t\
return -EINVAL;\n\t\
if (!may_mount())\n\t\t\
return -EPERM;\n\t\
if (path->dentry != path->mnt->mnt_root)\n\t\t\
return -EINVAL;\n\t\
if (!check_mnt(mnt))\n\t\t\
return -EINVAL;\n\t\
if (mnt->mnt.mnt_flags & MNT_LOCKED)\n\t\t\
return -EINVAL;\n\t\
if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))\n\t\t\
return -EPERM;\n\t\
return 0;\n\
}\n
$(shell sed -i '/^static bool is_mnt_ns_file/i $(CAN_UMOUNT)' $(srctree)/fs/namespace.c;)
endif

ifneq ($(shell grep -Eq "^int path_umount" $(srctree)/fs/namespace.c; echo $$?),0)
$(info -- KSU_SUSFS: adding function 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/namespace.c)
PATH_UMOUNT = int path_umount(struct path *path, int flags)\n\
{\n\t\
struct mount *mnt = real_mount(path->mnt);\n\t\
int ret;\n\t\
ret = can_umount(path, flags);\n\t\
if (!ret)\n\t\t\
ret = do_umount(mnt, flags);\n\t\
dput(path->dentry);\n\t\
mntput_no_expire(mnt);\n\t\
return ret;\n\
}\n
$(shell sed -i '/^static bool is_mnt_ns_file/i $(PATH_UMOUNT)' $(srctree)/fs/namespace.c;)
endif

ifneq ($(shell grep -Eq "^int path_umount" $(srctree)/fs/internal.h; echo $$?),0)
$(shell sed -i '/^extern void __init mnt_init/a int path_umount(struct path *path, int flags);' $(srctree)/fs/internal.h;)
$(info -- KSU_SUSFS: adding 'int path_umount(struct path *path, int flags);' to $(srctree)/fs/internal.h)
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)
$(eval SUSFS_VERSION=$(shell cat $(srctree)/include/linux/susfs.h | grep -E '^#define SUSFS_VERSION' | cut -d' ' -f3 | sed 's/"//g'))
$(info -- SUSFS_VERSION: $(SUSFS_VERSION))
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_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
ccflags-y += -DKSU_SUSFS_AUTO_ADD_SUS_KSU_DEFAULT_MOUNT
endif
ifdef KSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
ccflags-y += -DKSU_SUSFS_AUTO_ADD_SUS_BIND_MOUNT
endif
ifdef KSU_SUSFS_SUS_KSTAT
ccflags-y += -DKSU_SUSFS_SUS_KSTAT
endif
ifdef KSU_SUSFS_SUS_OVERLAYFS
ccflags-y += -DKSU_SUSFS_SUS_OVERLAYFS
endif
ifdef KSU_SUSFS_TRY_UMOUNT
ccflags-y += -DKSU_SUSFS_TRY_UMOUNT
endif
ifdef KSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
ccflags-y += -DKSU_SUSFS_AUTO_ADD_TRY_UMOUNT_FOR_BIND_MOUNT
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
ifdef KSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
ccflags-y += -DKSU_SUSFS_HIDE_KSU_SUSFS_SYMBOLS
endif
ifdef KSU_SUSFS_SPOOF_PROC_CMDLINE
ccflags-y += -DKSU_SUSFS_SPOOF_PROC_CMDLINE
endif
ifdef KSU_SUSFS_OPEN_REDIRECT
ccflags-y += -DKSU_SUSFS_OPEN_REDIRECT
endif
ifdef KSU_SUSFS_SUS_SU
ccflags-y += -DKSU_SUSFS_SUS_SU
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
10 changes: 5 additions & 5 deletions kernel/allowlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static uint8_t allow_list_bitmap[PAGE_SIZE] __read_mostly __aligned(PAGE_SIZE);
static struct work_struct ksu_save_work;
static struct work_struct ksu_load_work;

bool persistent_allow_list(void);
static bool persistent_allow_list(void);

void ksu_show_allow_list(void)
{
Expand Down Expand Up @@ -267,7 +267,7 @@ bool __ksu_is_allow_uid(uid_t uid)

if (unlikely(uid == 0)) {
// already root, but only allow our domain.
return is_ksu_domain();
return ksu_is_ksu_domain();
}

if (forbid_system_uid(uid)) {
Expand Down Expand Up @@ -352,7 +352,7 @@ bool ksu_get_allow_list(int *array, int *length, bool allow)
return true;
}

void do_save_allow_list(struct work_struct *work)
static void do_save_allow_list(struct work_struct *work)
{
u32 magic = FILE_MAGIC;
u32 version = FILE_FORMAT_VERSION;
Expand Down Expand Up @@ -394,7 +394,7 @@ void do_save_allow_list(struct work_struct *work)
filp_close(fp, 0);
}

void do_load_allow_list(struct work_struct *work)
static void do_load_allow_list(struct work_struct *work)
{
loff_t off = 0;
ssize_t ret = 0;
Expand Down Expand Up @@ -484,7 +484,7 @@ void ksu_prune_allowlist(bool (*is_uid_valid)(uid_t, char *, void *), void *data
}

// make sure allow list works cross boot
bool persistent_allow_list(void)
static bool persistent_allow_list(void)
{
return ksu_queue_work(&ksu_save_work);
}
Expand Down
2 changes: 1 addition & 1 deletion kernel/apk_sign.c
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ module_param_cb(ksu_debug_manager_uid, &expected_size_ops,

#endif

bool is_manager_apk(char *path)
bool ksu_is_manager_apk(char *path)
{
return check_v2_signature(path, EXPECTED_SIZE, EXPECTED_HASH);
}
2 changes: 1 addition & 1 deletion kernel/apk_sign.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@

#include <linux/types.h>

bool is_manager_apk(char *path);
bool ksu_is_manager_apk(char *path);

#endif
Loading

0 comments on commit 29db0b2

Please sign in to comment.