kernel & KernelSU: Another attempt to optimize SUS_MOUNT and SUS_SU
Changes: 1. Simplified the flow of mnt_id reorder, now it happens only after all sus mounts are umounted in ksu_handle_setuid() 2. All mounts mounted by ksu process will be flagged as sus mount and allocated with a fake mnt_id/mnt_group_id during ONLY the post-fs-data and service stage, which means other ksu mounts during/after boot-completed stage will not be handled by susfs. 3. Renaming: - susfs_mnt_id_ida => susfs_ksu_mnt_id_ida - susfs_mnt_group_ida => susfs_ksu_mnt_group_ida - DEFAULT_SUS_MNT_ID => DEFAULT_KSU_MNT_ID - DEFAULT_SUS_MNT_GROUP_ID => DEFAULT_KSU_MNT_GROUP_ID 4. Increased the default fake mnt_id to 300000, and default fake mnt_group_id to 3000. 5. Unify susfs_is_current_non_root_user_app_proc() and susfs_is_current_proc_su_not_allowed() as susfs_is_current_proc_umounted() Unify susfs_set_current_non_root_user_app_proc() and susfs_set_current_proc_su_not_allowed() as susfs_set_current_proc_umounted() Unify TIF_NON_ROOT_USER_APP_PROC and TIF_PROC_SU_NOT_ALLOWED as TIF_PROC_UMOUNTED 6. Removed unused susfs_is_allow_su() 7. Reworked a custom ksu_handle_setuid() which will be used if CONFIG_KSU_SUSFS is defined Co-authored-by: simonpunk <simonpunk2016@gmail.com>
This commit is contained in:
@@ -65,15 +65,7 @@
|
||||
bool ksu_uid_scanner_enabled = false;
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
bool susfs_is_boot_completed_triggered = false;
|
||||
extern u32 susfs_zygote_sid;
|
||||
extern bool susfs_is_mnt_devname_ksu(struct path *path);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
@@ -86,6 +78,7 @@ extern bool susfs_is_log_enabled __read_mostly;
|
||||
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;
|
||||
//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;
|
||||
@@ -134,6 +127,22 @@ static inline void susfs_on_post_fs_data(void) {
|
||||
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_module_mounted = false;
|
||||
@@ -645,12 +654,12 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
switch (arg3) {
|
||||
case EVENT_POST_FS_DATA: {
|
||||
static bool post_fs_data_lock = false;
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
susfs_on_post_fs_data();
|
||||
#endif
|
||||
if (!post_fs_data_lock) {
|
||||
post_fs_data_lock = true;
|
||||
pr_info("post-fs-data triggered\n");
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
susfs_on_post_fs_data();
|
||||
#endif
|
||||
on_post_fs_data();
|
||||
// Initialize UID scanner if enabled
|
||||
init_uid_scanner();
|
||||
@@ -665,6 +674,10 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
if (!boot_complete_lock) {
|
||||
boot_complete_lock = true;
|
||||
pr_info("boot_complete triggered\n");
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
susfs_is_boot_completed_triggered = true;
|
||||
#endif
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1423,11 +1436,11 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
|
||||
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("/system_ext", true, 0, uid);
|
||||
try_umount("/vendor", true, 0, uid);
|
||||
try_umount("/product", true, 0, uid);
|
||||
try_umount("/odm", 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);
|
||||
@@ -1445,6 +1458,7 @@ void susfs_try_umount_all(uid_t uid) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
{
|
||||
// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
|
||||
@@ -1464,54 +1478,92 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
// check if current process is zygote
|
||||
bool is_zygote_child = susfs_is_sid_equal(old->security, susfs_zygote_sid);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||
if (likely(is_zygote_child)) {
|
||||
// if spawned process is non user app process
|
||||
if (unlikely(new_uid.val < 10000 && new_uid.val >= 1000)) {
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
// set flag if zygote spawned system process is allowed for root access
|
||||
if (!ksu_is_allow_uid(new_uid.val)) {
|
||||
task_lock(current);
|
||||
susfs_set_current_proc_su_not_allowed();
|
||||
task_unlock(current);
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
// umount for the system process if path DATA_ADB_UMOUNT_FOR_ZYGOTE_SYSTEM_PROCESS exists
|
||||
if (susfs_is_umount_for_zygote_system_process_enabled) {
|
||||
goto out_try_umount;
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
}
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
// - here we check if uid is a isolated service spawned by zygote directly
|
||||
// - Apps that do not use "useAppZyogte" to start a isolated service will be directly
|
||||
// spawned by zygote which KSU will ignore it by default, the only fix for now is to
|
||||
// force a umount for those uid
|
||||
// - Therefore make sure your root app doesn't use isolated service for root access
|
||||
// - Kudos to ThePedroo, the author and maintainer of Rezygisk for finding and reporting
|
||||
// the detection, really big helps here!
|
||||
else if (new_uid.val >= 90000 && new_uid.val < 1000000) {
|
||||
task_lock(current);
|
||||
susfs_set_current_non_root_user_app_proc();
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
susfs_set_current_proc_su_not_allowed();
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
task_unlock(current);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
susfs_run_sus_path_loop(new_uid.val);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
if (susfs_is_umount_for_zygote_iso_service_enabled) {
|
||||
goto out_susfs_try_umount_all;
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
}
|
||||
// We only interest in process spwaned by zygote
|
||||
if (!susfs_is_sid_equal(old->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.val) && susfs_is_umount_for_zygote_iso_service_enabled) {
|
||||
goto do_umount;
|
||||
}
|
||||
|
||||
// Check if spawned process is normal user app and needs to be umounted
|
||||
if (likely(is_zygote_normal_app_uid(new_uid.val) && ksu_uid_should_umount(new_uid.val))) {
|
||||
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.val) && susfs_is_umount_for_zygote_system_process_enabled)) {
|
||||
goto do_umount;
|
||||
}
|
||||
|
||||
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.val);
|
||||
#else
|
||||
// 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);
|
||||
try_umount("/system", true, 0);
|
||||
try_umount("/vendor", true, 0);
|
||||
try_umount("/product", true, 0);
|
||||
try_umount("/system_ext", true, 0);
|
||||
try_umount("/data/adb/modules", false, MNT_DETACH);
|
||||
|
||||
// try umount ksu temp path
|
||||
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
||||
|
||||
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 // #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.val);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
{
|
||||
// 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 (!new || !old) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
kuid_t new_uid = new->uid;
|
||||
kuid_t old_uid = old->uid;
|
||||
|
||||
if (0 != old_uid.val) {
|
||||
// old process is not root, ignore it.
|
||||
return 0;
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||
|
||||
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);
|
||||
@@ -1523,29 +1575,6 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ksu_is_allow_uid(new_uid.val)) {
|
||||
#ifdef CONFIG_KSU_DEBUG
|
||||
pr_info("handle setuid ignore allowed application: %d\n", new_uid.val);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_KSU_SUSFS
|
||||
else {
|
||||
task_lock(current);
|
||||
susfs_set_current_non_root_user_app_proc();
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
susfs_set_current_proc_su_not_allowed();
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_SU
|
||||
task_unlock(current);
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
susfs_run_sus_path_loop(new_uid.val);
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS_SUS_PATH
|
||||
}
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||
|
||||
#ifdef CONFIG_KSU_SUSFS_SUS_MOUNT
|
||||
out_try_umount:
|
||||
#endif
|
||||
if (!ksu_uid_should_umount(new_uid.val)) {
|
||||
return 0;
|
||||
} else {
|
||||
@@ -1553,53 +1582,42 @@ out_try_umount:
|
||||
pr_info("uid: %d should not umount!\n", current_uid().val);
|
||||
#endif
|
||||
}
|
||||
#ifndef CONFIG_KSU_SUSFS
|
||||
// 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 = ksu_is_zygote(old->security);
|
||||
#endif
|
||||
|
||||
// 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);
|
||||
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_TRY_UMOUNT
|
||||
out_susfs_try_umount_all:
|
||||
// susfs come first, and lastly umount by ksu, make sure umount in reversed order
|
||||
susfs_try_umount_all(new_uid.val);
|
||||
#else
|
||||
// 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);
|
||||
try_umount("/system", true, 0);
|
||||
try_umount("/vendor", true, 0);
|
||||
try_umount("/product", true, 0);
|
||||
try_umount("/system_ext", true, 0);
|
||||
|
||||
// try umount modules path
|
||||
try_umount("/data/adb/modules", false, MNT_DETACH);
|
||||
|
||||
// try umount kpm path
|
||||
try_umount("/data/adb/kpm", false, MNT_DETACH);
|
||||
|
||||
// try umount ksu temp path
|
||||
try_umount("/debug_ramdisk", false, MNT_DETACH);
|
||||
|
||||
// try umount ksu su path
|
||||
try_umount("/sbin", false, MNT_DETACH);
|
||||
|
||||
// try umount hosts file
|
||||
try_umount("/system/etc/hosts", false, MNT_DETACH);
|
||||
|
||||
// try umount lsposed dex2oat bins
|
||||
try_umount("/apex/com.android.art/bin/dex2oat64", false, MNT_DETACH);
|
||||
try_umount("/apex/com.android.art/bin/dex2oat32", false, MNT_DETACH);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // #ifdef CONFIG_KSU_SUSFS
|
||||
|
||||
static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|
||||
unsigned long arg4, unsigned long arg5)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user