|  | 
| 44 | 44 | #include "throne_tracker.h" | 
| 45 | 45 | #include "throne_tracker.h" | 
| 46 | 46 | #include "kernel_compat.h" | 
|  | 47 | +#include "../../fs/mount.h" // mount and namespace struct definitions | 
| 47 | 48 | 
 | 
| 48 | 49 | static bool ksu_module_mounted = false; | 
| 49 | 50 | 
 | 
| @@ -498,52 +499,93 @@ static bool is_appuid(kuid_t uid) | 
| 498 | 499 | 	return appid >= FIRST_APPLICATION_UID && appid <= LAST_APPLICATION_UID; | 
| 499 | 500 | } | 
| 500 | 501 | 
 | 
| 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 | +}; | 
| 519 | 508 | 
 | 
| 520 |  | -static void ksu_umount_mnt(struct path *path, int flags) | 
|  | 509 | +static void ksu_path_umount(struct path *path, int flags) | 
| 521 | 510 | { | 
| 522 | 511 | 	int err = path_umount(path, flags); | 
| 523 | 512 | 	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); | 
| 525 | 516 | 	} | 
| 526 | 517 | } | 
| 527 | 518 | 
 | 
| 528 |  | -static void try_umount(const char *mnt, bool check_mnt, int flags) | 
|  | 519 | +static int collect_ksu_mounts(struct vfsmount *mnt, void *arg) | 
| 529 | 520 | { | 
| 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); | 
| 534 | 546 | 	} | 
| 535 | 547 | 
 | 
| 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 = ¤t->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)); | 
| 538 | 564 | 		return; | 
| 539 | 565 | 	} | 
| 540 | 566 | 
 | 
| 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); | 
| 544 | 580 | 	} | 
| 545 | 581 | 
 | 
| 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); | 
| 547 | 589 | } | 
| 548 | 590 | 
 | 
| 549 | 591 | 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) | 
| 598 | 640 | 		current->pid); | 
| 599 | 641 | #endif | 
| 600 | 642 | 
 | 
| 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(); | 
| 611 | 644 | 
 | 
| 612 | 645 | 	return 0; | 
| 613 | 646 | } | 
|  | 
0 commit comments