Skip to content

Commit c7facef

Browse files
committed
[wip] Refactor umount logic
1 parent f33b12c commit c7facef

File tree

1 file changed

+74
-41
lines changed

1 file changed

+74
-41
lines changed

kernel/core_hook.c

Lines changed: 74 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
#include "throne_tracker.h"
4545
#include "throne_tracker.h"
4646
#include "kernel_compat.h"
47+
#include "../../fs/mount.h" // mount and namespace struct definitions
4748

4849
static bool ksu_module_mounted = false;
4950

@@ -498,52 +499,93 @@ static bool is_appuid(kuid_t uid)
498499
return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID;
499500
}
500501

501-
static bool should_umount(struct path *path)
502-
{
503-
if (!path) {
504-
return false;
505-
}
506-
507-
if (current->nsproxy->mnt_ns == init_nsproxy.mnt_ns) {
508-
pr_info("ignore global mnt namespace process: %d\n",
509-
current_uid().val);
510-
return false;
511-
}
512-
513-
if (path->mnt && path->mnt->mnt_sb && path->mnt->mnt_sb->s_type) {
514-
const char *fstype = path->mnt->mnt_sb->s_type->name;
515-
return strcmp(fstype, "overlay") == 0;
516-
}
517-
return false;
518-
}
502+
// linked list to reversed umount
503+
struct ksu_mount_entry {
504+
struct list_head list;
505+
struct vfsmount *mnt;
506+
struct dentry *mountpoint;
507+
};
519508

520-
static void ksu_umount_mnt(struct path *path, int flags)
509+
static void ksu_path_umount(struct path *path, int flags)
521510
{
522511
int err = path_umount(path, flags);
523512
if (err) {
524-
pr_info("umount %s failed: %d\n", path->dentry->d_iname, err);
513+
pr_err("umount %s failed: %d\n", path->dentry->d_iname, err);
514+
} else {
515+
pr_info("umounted %s successfully\n", path->dentry->d_iname);
525516
}
526517
}
527518

528-
static void try_umount(const char *mnt, bool check_mnt, int flags)
519+
static int collect_ksu_mounts(struct vfsmount *mnt, void *arg)
529520
{
530-
struct path path;
531-
int err = kern_path(mnt, 0, &path);
532-
if (err) {
533-
return;
521+
struct list_head *head = (struct list_head *)arg;
522+
struct ksu_mount_entry *entry;
523+
struct mount *mnt_real;
524+
const char *devname;
525+
526+
if (!mnt)
527+
return 0;
528+
529+
mnt_real = real_mount(mnt);
530+
devname = mnt_real->mnt_devname;
531+
532+
// use devname to match mountpoints
533+
if (devname && strcmp(devname, "KSU") == 0) {
534+
entry = kmalloc(sizeof(struct ksu_mount_entry), GFP_KERNEL);
535+
if (!entry) {
536+
pr_err("failed to allocate memory for mount entry\n");
537+
return -ENOMEM;
538+
}
539+
entry->mnt = mnt;
540+
entry->mountpoint = mnt_real->mnt_mountpoint;
541+
pr_info("mount details - devname: %s, root: %s, mountpoint: %s\n",
542+
mnt_real->mnt_devname ? mnt_real->mnt_devname : "null",
543+
mnt->mnt_root ? mnt->mnt_root->d_name.name : (const unsigned char *)"null",
544+
mnt_real->mnt_mountpoint ? mnt_real->mnt_mountpoint->d_name.name : (const unsigned char *)"null");
545+
list_add(&entry->list, head);
534546
}
535547

536-
if (path.dentry != path.mnt->mnt_root) {
537-
// it is not root mountpoint, maybe umounted by others already.
548+
return 0;
549+
}
550+
551+
static void ksu_umount(void)
552+
{
553+
struct path root = {
554+
.mnt = &current->nsproxy->mnt_ns->root->mnt,
555+
.dentry = current->nsproxy->mnt_ns->root->mnt.mnt_root
556+
};
557+
struct vfsmount *collected;
558+
struct ksu_mount_entry *entry, *tmp;
559+
LIST_HEAD(ksu_mounts);
560+
561+
collected = collect_mounts(&root);
562+
if (IS_ERR(collected)) {
563+
pr_err("%s: collect mounts failed: %ld\n", __func__, PTR_ERR(collected));
538564
return;
539565
}
540566

541-
// we are only interest in some specific mounts
542-
if (check_mnt && !should_umount(&path)) {
543-
return;
567+
iterate_mounts(collect_ksu_mounts, &ksu_mounts, collected);
568+
569+
drop_collected_mounts(collected);
570+
571+
// iterate the list in reversed order and umount
572+
list_for_each_entry_safe_reverse(entry, tmp, &ksu_mounts, list) {
573+
struct path path = {
574+
.mnt = entry->mnt,
575+
.dentry = entry->mountpoint
576+
};
577+
ksu_path_umount(&path, 0); //FIXME: why was it 0?
578+
list_del(&entry->list);
579+
kfree(entry);
544580
}
545581

546-
ksu_umount_mnt(&path, flags);
582+
// module image must get umounted last
583+
struct path image;
584+
int err;
585+
586+
err = kern_path("/data/adb/modules", LOOKUP_FOLLOW, &image);
587+
if (!err)
588+
ksu_path_umount(&image, MNT_DETACH);
547589
}
548590

549591
int ksu_handle_setuid(struct cred *new, const struct cred *old)
@@ -598,16 +640,7 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
598640
current->pid);
599641
#endif
600642

601-
// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and
602-
// filter the mountpoint whose target is `/data/adb`
603-
try_umount("/system", true, 0);
604-
try_umount("/vendor", true, 0);
605-
try_umount("/product", true, 0);
606-
try_umount("/system_ext", true, 0);
607-
try_umount("/data/adb/modules", false, MNT_DETACH);
608-
609-
// try umount ksu temp path
610-
try_umount("/debug_ramdisk", false, MNT_DETACH);
643+
ksu_umount();
611644

612645
return 0;
613646
}

0 commit comments

Comments
 (0)