@@ -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,47 @@ 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+
281+ if (copy_from_user (buf , (const char __user * )arg3 , sizeof (buf ) - 1 )) {
282+ pr_err ("cmd_add_try_umount: failed to copy user string\n" );
283+ return 0 ;
284+ }
285+ buf [384 - 1 ] = '\0' ;
286+
287+ new_entry = kmalloc (sizeof (* new_entry ), GFP_KERNEL );
288+ if (!new_entry )
289+ return 0 ;
290+
291+ new_entry -> umountable = kstrdup (buf , GFP_KERNEL );
292+ if (!new_entry -> umountable ) {
293+ kfree (new_entry );
294+ return 0 ;
295+ }
296+
297+ // disallow dupes
298+ // if this gets too many, we can consider moving this whole task to a kthread
299+ list_for_each_entry (entry , & mount_list , list ) {
300+ if (!strcmp (entry -> umountable , buf )) {
301+ pr_info ("cmd_add_try_umount: %s is already here!\n" , buf );
302+ kfree (new_entry -> umountable );
303+ kfree (new_entry );
304+ return 0 ;
305+ }
306+ }
307+
308+ // debug
309+ // pr_info("cmd_add_try_umount: %s added!\n", buf);
310+ list_add (& new_entry -> list , & mount_list );
311+
312+ if (copy_to_user (result , & reply_ok , sizeof (reply_ok ))) {
313+ pr_err ("prctl reply error, cmd: %lu\n" , arg2 );
314+ }
315+ return 0 ;
316+ }
317+
271318 if (arg2 == CMD_BECOME_MANAGER ) {
272319 if (from_manager ) {
273320 if (copy_to_user (result , & reply_ok , sizeof (reply_ok ))) {
@@ -503,25 +550,6 @@ static bool is_non_appuid(kuid_t uid)
503550 return appid < FIRST_APPLICATION_UID ;
504551}
505552
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-
525553#if LINUX_VERSION_CODE >= KERNEL_VERSION (5 , 9 , 0 ) || defined(KSU_HAS_PATH_UMOUNT )
526554static void ksu_path_umount (const char * mnt , struct path * path , int flags )
527555{
@@ -545,7 +573,7 @@ static void ksu_sys_umount(const char *mnt, int flags)
545573}
546574#endif // KSU_HAS_PATH_UMOUNT
547575
548- static void try_umount (const char * mnt , bool check_mnt , int flags )
576+ static void try_umount (const char * mnt , int flags )
549577{
550578 struct path path ;
551579 int err = kern_path (mnt , 0 , & path );
@@ -559,12 +587,6 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
559587 return ;
560588 }
561589
562- // we are only interest in some specific mounts
563- if (check_mnt && !should_umount (& path )) {
564- path_put (& path );
565- return ;
566- }
567-
568590#if LINUX_VERSION_CODE >= KERNEL_VERSION (5 , 9 , 0 ) || defined(KSU_HAS_PATH_UMOUNT )
569591 ksu_path_umount (mnt , & path , flags );
570592 // dont call path_put here!!
@@ -579,6 +601,8 @@ static void try_umount(const char *mnt, bool check_mnt, int flags)
579601
580602int ksu_handle_setuid (struct cred * new , const struct cred * old )
581603{
604+ struct mount_entry * entry ;
605+
582606 // this hook is used for umounting overlayfs for some uid, if there isn't any module mounted, just ignore it!
583607 if (!ksu_module_mounted ) {
584608 return 0 ;
@@ -641,17 +665,10 @@ int ksu_handle_setuid(struct cred *new, const struct cred *old)
641665 current -> pid );
642666#endif
643667
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 );
668+ // don't free! keep on heap! this is used on subsequent setuid calls
669+ // if this is freed, we dont have anything to umount next
670+ list_for_each_entry (entry , & mount_list , list )
671+ try_umount (entry -> umountable , MNT_DETACH );
655672
656673 return 0 ;
657674}
@@ -662,6 +679,7 @@ static int ksu_task_prctl(int option, unsigned long arg2, unsigned long arg3,
662679 ksu_handle_prctl (option , arg2 , arg3 , arg4 , arg5 );
663680 return - ENOSYS ;
664681}
682+
665683// kernel 4.4 and 4.9
666684#if LINUX_VERSION_CODE < KERNEL_VERSION (4 , 10 , 0 ) || defined(CONFIG_KSU_ALLOWLIST_WORKAROUND )
667685static int ksu_key_permission (key_ref_t key_ref , const struct cred * cred ,
0 commit comments