@@ -237,6 +237,12 @@ static void nuke_ext4_sysfs() {
237237	path_put (& path );
238238}
239239
240+ struct  mount_entry  {
241+     char  * umountable ;
242+     struct  list_head  list ;
243+ };
244+ LIST_HEAD (mount_list );
245+ 
240246int  ksu_handle_prctl (int  option , unsigned long  arg2 , unsigned long  arg3 ,
241247		     unsigned long  arg4 , unsigned long  arg5 )
242248{
@@ -268,6 +274,46 @@ int ksu_handle_prctl(int option, unsigned long arg2, unsigned long arg3,
268274	pr_info ("option: 0x%x, cmd: %ld\n" , option , arg2 );
269275#endif 
270276
277+ 	if  (arg2  ==  CMD_ADD_TRY_UMOUNT ) {
278+ 		struct  mount_entry  * new_entry , * entry ;
279+ 		char  buf [384 ];
280+ 		memzero_explicit (buf , 384 ); // overkill, init as empty is ok 
281+ 
282+ 		if  (copy_from_user (buf , (const  char  __user  * )arg3 , sizeof (buf ) -  1 )) {
283+ 			pr_err ("cmd_add_try_umount: failed to copy user string\n" );
284+ 			return  0 ;
285+ 		}
286+ 		buf [384  -  1 ] =  '\0' ;
287+ 
288+ 		new_entry  =  kmalloc (sizeof (* new_entry ), GFP_KERNEL );
289+ 		if  (!new_entry )
290+ 			return  0 ;
291+ 
292+ 		new_entry -> umountable  =  kstrdup (buf , GFP_KERNEL );
293+ 		if  (!new_entry -> umountable ) {
294+ 			kfree (new_entry );
295+ 			return  0 ;
296+ 		}
297+ 
298+ 		// disallow dupes 
299+ 		// if this gets too many, we can consider moving this whole task to a kthread 
300+ 		list_for_each_entry (entry , & mount_list , list ) {
301+ 			if  (!strcmp (entry -> umountable , buf )) {
302+ 				pr_info ("cmd_add_try_umount: %s is already here!\n" , buf );
303+ 				return  0 ;
304+ 			}	
305+ 		}	
306+ 
307+ 		// debug 
308+ 		// pr_info("cmd_add_try_umount: %s added!\n", buf); 
309+ 		list_add (& new_entry -> list , & mount_list );
310+ 
311+ 		if  (copy_to_user (result , & reply_ok , sizeof (reply_ok ))) {
312+ 			pr_err ("prctl reply error, cmd: %lu\n" , arg2 );
313+ 		}
314+ 		return  0 ;
315+ 	}
316+ 
271317	if  (arg2  ==  CMD_BECOME_MANAGER ) {
272318		if  (from_manager ) {
273319			if  (copy_to_user (result , & reply_ok , sizeof (reply_ok ))) {
@@ -503,25 +549,6 @@ static bool is_non_appuid(kuid_t uid)
503549	return  appid  <  FIRST_APPLICATION_UID ;
504550}
505551
506- static  bool  should_umount (struct  path  * path )
507- {
508- 	if  (!path ) {
509- 		return  false;
510- 	}
511- 
512- 	if  (current -> nsproxy -> mnt_ns  ==  init_nsproxy .mnt_ns ) {
513- 		pr_info ("ignore global mnt namespace process: %d\n" ,
514- 			current_uid ().val );
515- 		return  false;
516- 	}
517- 
518- 	if  (path -> mnt  &&  path -> mnt -> mnt_sb  &&  path -> mnt -> mnt_sb -> s_type ) {
519- 		const  char  * fstype  =  path -> mnt -> mnt_sb -> s_type -> name ;
520- 		return  strcmp (fstype , "overlay" ) ==  0 ;
521- 	}
522- 	return  false;
523- }
524- 
525552#if  LINUX_VERSION_CODE  >= KERNEL_VERSION (5 , 9 , 0 ) ||  defined(KSU_HAS_PATH_UMOUNT )
526553static  void  ksu_path_umount (const  char  * mnt , struct  path  * path , int  flags )
527554{
@@ -545,7 +572,7 @@ static void ksu_sys_umount(const char *mnt, int flags)
545572}
546573#endif  // KSU_HAS_PATH_UMOUNT 
547574
548- static  void  try_umount (const  char  * mnt , bool   check_mnt ,  int  flags )
575+ static  void  try_umount (const  char  * mnt , int  flags )
549576{
550577	struct  path  path ;
551578	int  err  =  kern_path (mnt , 0 , & path );
@@ -559,12 +586,6 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
559586		return ;
560587	}
561588
562- 	// we are only interest in some specific mounts 
563- 	if  (check_mnt  &&  !should_umount (& path )) {
564- 		path_put (& path );
565- 		return ;
566- 	}
567- 
568589#if  LINUX_VERSION_CODE  >= KERNEL_VERSION (5 , 9 , 0 ) ||  defined(KSU_HAS_PATH_UMOUNT )
569590	ksu_path_umount (mnt , & path , flags );
570591	// dont call path_put here!! 
@@ -579,6 +600,8 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
579600
580601int  ksu_handle_setuid (struct  cred  * new , const  struct  cred  * old )
581602{
603+ 	struct  mount_entry  * entry , * tmp ;
604+ 
582605	// this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it! 
583606	if  (!ksu_module_mounted ) {
584607		return  0 ;
@@ -641,17 +664,10 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
641664		current -> pid );
642665#endif 
643666
644- 	// fixme: use `collect_mounts` and `iterate_mount` to iterate all mountpoint and 
645- 	// filter the mountpoint whose target is `/data/adb` 
646- 	try_umount ("/odm" , true, 0 );
647- 	try_umount ("/system" , true, 0 );
648- 	try_umount ("/vendor" , true, 0 );
649- 	try_umount ("/product" , true, 0 );
650- 	try_umount ("/system_ext" , true, 0 );
651- 	try_umount ("/data/adb/modules" , false, MNT_DETACH );
652- 
653- 	// try umount ksu temp path 
654- 	try_umount ("/debug_ramdisk" , false, MNT_DETACH );
667+ 	// don't free! keep on heap! this is used on subsequent setuid calls 
668+ 	// if this is freed, we dont have anything to umount next 
669+ 	list_for_each_entry_safe (entry , tmp , & mount_list , list )
670+ 		try_umount (entry -> umountable , MNT_DETACH );
655671
656672	return  0 ;
657673}
@@ -662,6 +678,7 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
662678	ksu_handle_prctl (option , arg2 , arg3 , arg4 , arg5 );
663679	return  - ENOSYS ;
664680}
681+ 
665682// kernel 4.4 and 4.9 
666683#if  LINUX_VERSION_CODE  <  KERNEL_VERSION (4 , 10 , 0 ) ||  defined(CONFIG_KSU_ALLOWLIST_WORKAROUND )
667684static  int  ksu_key_permission (key_ref_t  key_ref , const  struct  cred  * cred ,
0 commit comments