Skip to content

Commit 425ae46

Browse files
committed
kernel: core_hook: automate and refactor umount (tiann#2531)
monitors and lists all incoming mounts by hooking security_sb_mount this requires ksud to go back and use sys_mount instead of fsopen + move_mount this also fixes that MNT_DETACH issue. tiann#2386 (comment) Modules also can create an overlay with KSU devname and it will be added to the list. Context: aviraxp@c7facef#commitcomment-153941502 Stale: tiann#2531 Signed-off-by: backslashxx <[email protected]>
1 parent ce7dce5 commit 425ae46

File tree

1 file changed

+72
-35
lines changed

1 file changed

+72
-35
lines changed

kernel/core_hook.c

Lines changed: 72 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -504,25 +504,6 @@ static bool is_appuid(kuid_t uid)
504504
return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID;
505505
}
506506

507-
static bool should_umount(struct path *path)
508-
{
509-
if (!path) {
510-
return false;
511-
}
512-
513-
if (current->nsproxy->mnt_ns == init_nsproxy.mnt_ns) {
514-
pr_info("ignore global mnt namespace process: %d\n",
515-
current_uid().val);
516-
return false;
517-
}
518-
519-
if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) {
520-
const char *fstype = path->mnt->mnt_sb->s_type->name;
521-
return strcmp(fstype, "overlay") == 0;
522-
}
523-
return false;
524-
}
525-
526507
#ifdef KSU_HAS_PATH_UMOUNT
527508
static void ksu_umount_mnt(struct path *path, int flags)
528509
{
@@ -544,7 +525,7 @@ static void ksu_sys_umount(const char *mnt, int flags)
544525
}
545526
#endif
546527

547-
static void try_umount(const char *mnt, bool check_mnt, int flags)
528+
static void try_umount(const char *mnt, int flags)
548529
{
549530
struct path path;
550531
int err = kern_path(mnt, 0, &path);
@@ -557,20 +538,23 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
557538
return;
558539
}
559540

560-
// we are only interest in some specific mounts
561-
if (check_mnt && !should_umount(&path)) {
562-
return;
563-
}
564-
565541
#ifdef KSU_HAS_PATH_UMOUNT
566542
ksu_umount_mnt(&path, flags);
567543
#else
568544
ksu_sys_umount(mnt, flags);
569545
#endif
570546
}
571547

548+
struct mount_entry {
549+
char *umountable;
550+
struct list_head list;
551+
};
552+
LIST_HEAD(mount_list);
553+
572554
LSM_HANDLER_TYPE ksu_handle_setuid(struct cred *new, const struct cred *old)
573555
{
556+
struct mount_entry *entry, *tmp;
557+
574558
// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
575559
if (!ksu_module_mounted) {
576560
return 0;
@@ -621,21 +605,73 @@ LSM_HANDLER_TYPE ksu_handle_setuid(struct cred *new, const struct cred *old)
621605
current->pid);
622606
#endif
623607

624-
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
625-
// filter the mountpoint whose target is `/data/adb`
626-
try_umount("/odm", true, 0);
627-
try_umount("/system", true, 0);
628-
try_umount("/vendor", true, 0);
629-
try_umount("/product", true, 0);
630-
try_umount("/system_ext", true, 0);
631-
try_umount("/data/adb/modules", false, MNT_DETACH);
608+
list_for_each_entry_safe(entry, tmp, &mount_list, list) {
609+
try_umount(entry->umountable, MNT_DETACH);
610+
// don't free! keep on heap! this is used on subsequent setuid calls
611+
// if this is freed, we dont have anything to umount next
612+
// FIXME: might leak, refresh the list?
613+
}
632614

633-
// try umount ksu temp path
634-
try_umount("/debug_ramdisk", false, MNT_DETACH);
615+
return 0;
616+
}
617+
618+
static int ksu_mount_monitor(const char *dev_name, const char *dirname, const char *type)
619+
{
635620

621+
char *device_name_copy = kstrdup(dev_name, GFP_KERNEL);
622+
char *fstype_copy = kstrdup(type, GFP_KERNEL);
623+
char *dirname_copy = kstrdup(dirname, GFP_KERNEL);
624+
struct mount_entry *new_entry;
625+
626+
if (!device_name_copy || !dirname_copy) {
627+
// allow null fstype_copy for bind mounts/loopbacks
628+
goto out;
629+
}
630+
631+
/*
632+
* feel free to add your own patterns
633+
* default one is just KSU devname or it starts with /data/adb/modules
634+
*/
635+
if ((!strcmp(device_name_copy, "KSU"))
636+
|| strstarts(dirname_copy, "/data/adb/modules")
637+
|| !strcmp(dirname_copy, "/system/etc/hosts") ) {
638+
new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
639+
if (new_entry) {
640+
new_entry->umountable = kstrdup(dirname, GFP_KERNEL);
641+
list_add(&new_entry->list, &mount_list);
642+
pr_info("%s: devicename %s fstype: %s path: %s\n", __func__, device_name_copy, fstype_copy, new_entry->umountable);
643+
}
644+
}
645+
out:
646+
kfree(device_name_copy);
647+
kfree(fstype_copy);
648+
kfree(dirname_copy);
636649
return 0;
637650
}
638651

652+
// for UL, hook on security.c ksu_sb_mount(dev_name, path, type, flags, data);
653+
LSM_HANDLER_TYPE ksu_sb_mount(const char *dev_name, const struct path *path,
654+
const char *type, unsigned long flags, void *data)
655+
{
656+
/*
657+
* 384 is what throne_tracker uses, something sensible even for /data/app
658+
* we can pattern match revanced mounts even.
659+
* we are not really interested on mountpoints that are longer than that
660+
* this is now up to the modder for tweaking
661+
*/
662+
char buf[384];
663+
char *dir_name = d_path(path, buf, sizeof(buf));
664+
665+
if (dir_name && dir_name != buf) {
666+
#ifdef CONFIG_KSU_DEBUG
667+
pr_info("security_sb_mount: devname: %s path: %s type: %s \n", dev_name, dir_name, type);
668+
#endif
669+
return ksu_mount_monitor(dev_name, dir_name, type);
670+
} else {
671+
return 0;
672+
}
673+
}
674+
639675
// kernel 4.9 and older
640676
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
641677
LSM_HANDLER_TYPE ksu_key_permission(key_ref_t key_ref, const struct cred *cred,
@@ -678,6 +714,7 @@ static struct security_hook_list ksu_hooks[] = {
678714
LSM_HOOK_INIT(task_prctl, ksu_task_prctl),
679715
LSM_HOOK_INIT(inode_rename, ksu_inode_rename),
680716
LSM_HOOK_INIT(task_fix_setuid, ksu_task_fix_setuid),
717+
LSM_HOOK_INIT(sb_mount, ksu_sb_mount),
681718
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND)
682719
LSM_HOOK_INIT(key_permission, ksu_key_permission)
683720
#endif

0 commit comments

Comments
 (0)