diff --git a/kernel/Kconfig b/kernel/Kconfig index 67f177f4708a..ea19e8a3397d 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -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 (NOT recommended)" + depends on KSU_SUSFS + default y + help + - Allow hiding the user-defined path and all its sub-paths from various system calls. + - 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. + - The mnt_id, parent_mnt_id and mnt_group_id will be reordered as well in mountinfo while the actual values are remained unchanged in kernel, + and this reorder function will be effective on all processes spawned only by the zygote process. + +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 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. + - Effective on all NO-root-access-granted processes. + +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_SUS_SU + bool "Enable SUS-SU in runtime temporarily (experimental)" + depends on KSU_SUSFS && KPROBES + default y + help + - Allow user to enable or disable core ksu kprobes hooks temporarily in runtime. + - When enabling sus_su, kprobes of ksu will be disabled, and a fifo driver will be created in /dev/[random_string]. + (for first time only), then user needs to mount the 'sus_su' to /system/bin/su using overlayfs or whatever techniques, + and run 'su' to get root shell from the fifo driver. Or, refer to the method in service.sh from module template. + - When disabling sus_su, kprobes of ksu will be enabled again, and the fifo driver will be deleted. + - Only apps with root access granted by ksu manager are allowed to get root. + - Also overlayfs is required. + +endmenu + endmenu diff --git a/kernel/Makefile b/kernel/Makefile index 11daaa4c1363..d50362282490 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -57,14 +57,91 @@ $(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) +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_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_SPOOF_UNAME +ccflags-y += -DKSU_SUSFS_SPOOF_UNAME +endif +ifdef KSU_SUSFS_ENABLE_LOG +ccflags-y += -DKSU_SUSFS_ENABLE_LOG +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 diff --git a/kernel/core_hook.c b/kernel/core_hook.c index 009216efa454..8c97730207c3 100644 --- a/kernel/core_hook.c +++ b/kernel/core_hook.c @@ -33,6 +33,13 @@ #include #endif +#ifdef CONFIG_KSU_SUSFS +#include +#ifdef CONFIG_KSU_SUSFS_SUS_SU +#include "sucompat.h" +#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU +#endif // #ifdef CONFIG_KSU_SUSFS + #include "allowlist.h" #include "arch.h" #include "core_hook.h" @@ -45,6 +52,19 @@ #include "throne_tracker.h" #include "kernel_compat.h" +#ifdef CONFIG_KSU_SUSFS +bool susfs_is_allow_su(void) +{ + if (is_manager()) { + // we are manager, allow! + return true; + } + return ksu_is_allow_uid(current_uid().val); +} + +static u32 zygote_sid = 0; +#endif // #ifdef CONFIG_KSU_SUSFS + static bool ksu_module_mounted = false; extern int handle_sepolicy(unsigned long arg3, void __user *arg4); @@ -376,6 +396,164 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3, return 0; } +#ifdef CONFIG_KSU_SUSFS + if (current_uid_val == 0) { +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + if (arg2 == CMD_SUSFS_ADD_SUS_PATH) { + int error = 0; + 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); + if (copy_to_user((void __user*)arg5, &error, sizeof(error))) + 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) { + int error = 0; + 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); + if (copy_to_user((void __user*)arg5, &error, sizeof(error))) + 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) { + int error = 0; + 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); + if (copy_to_user((void __user*)arg5, &error, sizeof(error))) + pr_info("susfs: copy_to_user() failed\n"); + return 0; + } + if (arg2 == CMD_SUSFS_UPDATE_SUS_KSTAT) { + int error = 0; + 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); + if (copy_to_user((void __user*)arg5, &error, sizeof(error))) + pr_info("susfs: copy_to_user() failed\n"); + return 0; + } + if (arg2 == CMD_SUSFS_ADD_SUS_KSTAT_STATICALLY) { + int error = 0; + 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); + if (copy_to_user((void __user*)arg5, &error, sizeof(error))) + 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) { + int error = 0; + 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); + if (copy_to_user((void __user*)arg5, &error, sizeof(error))) + 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) { + int error = 0; + 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); + if (copy_to_user((void __user*)arg5, &error, sizeof(error))) + 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) { + int error = 0; + 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, &error, sizeof(error))) + pr_info("susfs: copy_to_user() failed\n"); + return 0; + } +#endif //#ifdef CONFIG_KSU_SUSFS_ENABLE_LOG +#ifdef CONFIG_KSU_SUSFS_SUS_SU + if (arg2 == CMD_SUSFS_SUS_SU) { + int error = 0; + if (!ksu_access_ok((void __user*)arg3, sizeof(struct st_sus_su))) { + pr_err("susfs: CMD_SUSFS_SUS_SU -> arg3 is not accessible\n"); + return 0; + } + if (!ksu_access_ok((void __user*)arg5, sizeof(error))) { + pr_err("susfs: CMD_SUSFS_SUS_SU -> arg5 is not accessible\n"); + return 0; + } + error = susfs_sus_su((struct st_sus_su __user*)arg3); + pr_info("susfs: CMD_SUSFS_SUS_SU -> ret: %d\n", error); + if (copy_to_user((void __user*)arg5, &error, sizeof(error))) + pr_info("susfs: copy_to_user() failed\n"); + return 0; + } +#endif //#ifdef CONFIG_KSU_SUSFS_SUS_SU + } +#endif //#ifdef CONFIG_KSU_SUSFS + // all other cmds are for 'root manager' if (!from_manager) { return 0; @@ -460,7 +638,11 @@ static int ksu_umount_mnt(struct path *path, int flags) #endif } +#ifdef CONFIG_KSU_SUSFS +void try_umount(const char *mnt, bool check_mnt, int flags) +#else static void try_umount(const char *mnt, bool check_mnt, int flags) +#endif { struct path path; int err = kern_path(mnt, 0, &path); @@ -503,6 +685,27 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) return 0; } +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT + // check if spawned process is zygote + if (unlikely(new_uid.val == 0 && is_zygote(new->security))) { + zygote_sid = ksu_get_zygote_sid(); + } + + // check if current process is zygote + bool is_zygote_child = zygote_sid == ksu_get_current_sid(); + if (likely(is_zygote_child)) { + // set flag TASK_STRUCT_KABI1_IS_ZYGOTE to current->android_kabi_reserved1 + if (unlikely(!(current->android_kabi_reserved1 & TASK_STRUCT_KABI1_IS_ZYGOTE))) { + current->android_kabi_reserved1 |= TASK_STRUCT_KABI1_IS_ZYGOTE; + pr_info("susfs: Found newly created zygote process\n"); + } + // if spawned process is non user app process, run try_umount() + if (unlikely(new_uid.val < 10000 && new_uid.val >= 1000)) { + goto out_try_umount; + } + } +#endif + if (!is_appuid(new_uid) || is_unsupported_uid(new_uid.val)) { // pr_info("handle setuid ignore non application or isolated uid: %d\n", new_uid.val); return 0; @@ -512,6 +715,12 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) // pr_info("handle setuid ignore allowed application: %d\n", new_uid.val); return 0; } +#ifdef CONFIG_KSU_SUSFS_SUS_PATH + else { + // if new uid is not root granted, then drop a payload to inidicate that sus_path will be effective on this uid + new->user->android_kabi_reserved1 |= USER_STRUCT_KABI1_NON_ROOT_USER_APP_PROFILE; + } +#endif if (!ksu_uid_should_umount(new_uid.val)) { return 0; @@ -521,21 +730,32 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old) #endif } +#ifndef CONFIG_KSU_SUSFS_SUS_MOUNT // check old process's selinux context, if it is not zygote, ignore it! // because some su apps may setuid to untrusted_app but they are in global mount namespace // when we umount for such process, that is a disaster! bool is_zygote_child = is_zygote(old->security); +#endif if (!is_zygote_child) { pr_info("handle umount ignore non zygote child: %d\n", current->pid); return 0; } + #ifdef CONFIG_KSU_DEBUG // umount the target mnt pr_info("handle umount for uid: %d, pid: %d\n", new_uid.val, current->pid); #endif +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT +out_try_umount: +#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); diff --git a/kernel/core_hook.h b/kernel/core_hook.h index 616951e8db35..e80ce4a958e5 100644 --- a/kernel/core_hook.h +++ b/kernel/core_hook.h @@ -6,4 +6,10 @@ void __init ksu_core_init(void); void ksu_core_exit(void); +#ifdef CONFIG_KSU_SUSFS +bool susfs_is_allow_su(void); +void escape_to_root(void); +void try_umount(const char *mnt, bool check_mnt, int flags); +#endif + #endif diff --git a/kernel/kernel_compat.c b/kernel/kernel_compat.c index b242bc637398..0ec3df624f94 100644 --- a/kernel/kernel_compat.c +++ b/kernel/kernel_compat.c @@ -77,6 +77,16 @@ void ksu_android_ns_fs_check() task_unlock(current); } +int ksu_access_ok(const void *addr, unsigned long size) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(5,0,0) + /* For kernels before 5.0.0, pass the type argument to access_ok. */ + return access_ok(VERIFY_READ, addr, size); +#else + /* For kernels 5.0.0 and later, ignore the type argument. */ + return access_ok(addr, size); +#endif +} + struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode) { #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_IS_HW_HISI) diff --git a/kernel/kernel_compat.h b/kernel/kernel_compat.h index ba9981857fd1..34050e73d790 100644 --- a/kernel/kernel_compat.h +++ b/kernel/kernel_compat.h @@ -29,6 +29,7 @@ extern struct key *init_session_keyring; #endif extern void ksu_android_ns_fs_check(); +extern int ksu_access_ok(const void *addr, unsigned long size); extern struct file *ksu_filp_open_compat(const char *filename, int flags, umode_t mode); extern ssize_t ksu_kernel_read_compat(struct file *p, void *buf, size_t count, diff --git a/kernel/ksu.c b/kernel/ksu.c index 55331049dac9..6cc6ed1009c0 100644 --- a/kernel/ksu.c +++ b/kernel/ksu.c @@ -11,6 +11,10 @@ #include "ksu.h" #include "throne_tracker.h" +#ifdef CONFIG_KSU_SUSFS +#include +#endif + static struct workqueue_struct *ksu_workqueue; bool ksu_queue_work(struct work_struct *work) @@ -53,6 +57,10 @@ int __init kernelsu_init(void) pr_alert("*************************************************************"); #endif +#ifdef CONFIG_KSU_SUSFS + susfs_init(); +#endif + ksu_core_init(); ksu_workqueue = alloc_ordered_workqueue("kernelsu_work_queue", 0); diff --git a/kernel/ksud.c b/kernel/ksud.c index 68e473524284..45b43928d0d2 100644 --- a/kernel/ksud.c +++ b/kernel/ksud.c @@ -64,6 +64,10 @@ bool ksu_execveat_hook __read_mostly = true; bool ksu_input_hook __read_mostly = true; #endif +#ifdef CONFIG_KSU_SUSFS_SUS_SU +bool ksu_devpts_hook = false; +#endif + u32 ksu_devpts_sid; void on_post_fs_data(void) diff --git a/kernel/selinux/rules.c b/kernel/selinux/rules.c index 1ba6d853f2a9..7b24203ce0ad 100644 --- a/kernel/selinux/rules.c +++ b/kernel/selinux/rules.c @@ -134,6 +134,11 @@ void apply_kernelsu_rules() ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "getpgid"); ksu_allow(db, "system_server", KERNEL_SU_DOMAIN, "process", "sigkill"); +#ifdef CONFIG_KSU_SUSFS + // Allow umount in zygote process without installing zygisk + ksu_allow(db, "zygote", "labeledfs", "filesystem", "unmount"); +#endif + rcu_read_unlock(); } diff --git a/kernel/selinux/selinux.c b/kernel/selinux/selinux.c index da6cc058a922..dbead9ba203f 100644 --- a/kernel/selinux/selinux.c +++ b/kernel/selinux/selinux.c @@ -129,6 +129,23 @@ bool is_zygote(void *sec) return result; } +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT +u32 ksu_get_zygote_sid(void) +{ + u32 zygote_sid = 0; + int err = security_secctx_to_secid("u:r:zygote:s0", strlen("u:r:zygote:s0"), + &zygote_sid); + if (err) { + pr_info("get zygote sid err %d\n", err); + } + return zygote_sid; +} + +u32 ksu_get_current_sid(void) { + return current_sid(); +} +#endif + #define DEVPTS_DOMAIN "u:object_r:ksu_file:s0" u32 ksu_get_devpts_sid() diff --git a/kernel/selinux/selinux.h b/kernel/selinux/selinux.h index 4c0358b55624..5da8a62a1097 100644 --- a/kernel/selinux/selinux.h +++ b/kernel/selinux/selinux.h @@ -23,6 +23,12 @@ bool is_zygote(void *cred); void apply_kernelsu_rules(); +#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT +u32 ksu_get_zygote_sid(void); + +u32 ksu_get_current_sid(void); +#endif + u32 ksu_get_devpts_sid(); #endif diff --git a/kernel/sucompat.c b/kernel/sucompat.c index 9b45cd0d9490..c33fdc165fab 100644 --- a/kernel/sucompat.c +++ b/kernel/sucompat.c @@ -365,3 +365,25 @@ void ksu_sucompat_exit() unregister_kprobe(&pts_unix98_lookup_kp); #endif } + + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +extern bool ksu_devpts_hook; + +void ksu_susfs_disable_sus_su(void) { + enable_kprobe(&execve_kp); + enable_kprobe(&newfstatat_kp); + enable_kprobe(&faccessat_kp); + enable_kprobe(&pts_unix98_lookup_kp); + ksu_devpts_hook = false; +} + +void ksu_susfs_enable_sus_su(void) { + disable_kprobe(&execve_kp); + disable_kprobe(&newfstatat_kp); + disable_kprobe(&faccessat_kp); + disable_kprobe(&pts_unix98_lookup_kp); + ksu_devpts_hook = true; +} +#endif + diff --git a/kernel/sucompat.h b/kernel/sucompat.h new file mode 100644 index 000000000000..95305d61485a --- /dev/null +++ b/kernel/sucompat.h @@ -0,0 +1,9 @@ +#ifndef __KSU_H_SUCOMPAT +#define __KSU_H_SUCOMPAT + +#ifdef CONFIG_KSU_SUSFS_SUS_SU +void ksu_susfs_disable_sus_su(void); +void ksu_susfs_enable_sus_su(void); +#endif + +#endif