77#include <linux/version.h>
88#include <linux/stat.h>
99#include <linux/namei.h>
10+ #include <asm/atomic.h>
1011
1112#include "allowlist.h"
1213#include "klog.h" // IWYU pragma: keep
1920
2021uid_t ksu_manager_uid = KSU_INVALID_UID ;
2122
23+ static atomic_t pkg_lock = ATOMIC_INIT (0 );
24+ static atomic_t scan_lock = ATOMIC_INIT (0 );
25+
2226#define KSU_UID_LIST_PATH "/data/misc/user_uid/uid_list"
2327#define USER_DATA_PATH "/data/user_de/0"
2428#define USER_DATA_PATH_LEN 288
2529
30+ struct uid_scan_stats {
31+ size_t errors_encountered ;
32+ };
33+
34+ struct user_data_context {
35+ struct dir_context ctx ;
36+ struct list_head * uid_list ;
37+ struct uid_scan_stats * stats ;
38+ };
39+
2640struct uid_data {
2741 struct list_head list ;
2842 u32 uid ;
@@ -251,7 +265,7 @@ FILLDIR_RETURN_TYPE user_data_actor(struct dir_context *ctx, const char *name,
251265 }
252266
253267 char package_path [USER_DATA_PATH_LEN ];
254- if (snprintf (package_path , sizeof (package_path ), "%s/%.*s" ,
268+ if (snprintf (package_path , sizeof (package_path ), "%s/%.*s" ,
255269 USER_DATA_PATH , namelen , name ) >= sizeof (package_path )) {
256270 pr_err ("Path too long for package: %.*s\n" , namelen , name );
257271 if (my_ctx -> stats )
@@ -330,14 +344,15 @@ static int scan_user_data_for_uids(struct list_head *uid_list)
330344 struct file * dir_file ;
331345 struct uid_scan_stats stats = {0 };
332346 int ret = 0 ;
333-
347+
334348 if (!uid_list ) {
335349 return - EINVAL ;
336350 }
337351
338352 dir_file = ksu_filp_open_compat (USER_DATA_PATH , O_RDONLY , 0 );
339353 if (IS_ERR (dir_file )) {
340- pr_err ("UserDE UID: Failed to open %s, err: (%ld)\n" , USER_DATA_PATH , PTR_ERR (dir_file ));
354+
355+ pr_err ("Failed to open %s, err: (%ld)\n" , USER_DATA_PATH , PTR_ERR (dir_file ));
341356 return PTR_ERR (dir_file );
342357 }
343358
@@ -350,14 +365,11 @@ static int scan_user_data_for_uids(struct list_head *uid_list)
350365 ret = iterate_dir (dir_file , & ctx .ctx );
351366 filp_close (dir_file , NULL );
352367
368+ // if 0 errors, that means everything were fine.
353369 if (stats .errors_encountered > 0 ) {
354- pr_warn ( "Encountered %zu errors while scanning user data directory\n" ,
355- stats .errors_encountered );
370+ pr_info ( "Got %zu error(s) while scanning %s directory. \n" ,
371+ stats .errors_encountered , USER_DATA_PATH );
356372 }
357-
358- pr_info ("UserDE UID: Scanned %s directory with %zu errors\n" ,
359- USER_DATA_PATH , stats .errors_encountered );
360-
361373 return ret ;
362374}
363375
@@ -461,7 +473,14 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
461473 return FILLDIR_ACTOR_CONTINUE ;
462474}
463475
464- void search_manager (const char * path , int depth , struct list_head * uid_data )
476+ // compat: https://elixir.bootlin.com/linux/v3.9/source/include/linux/fs.h#L771
477+ #if LINUX_VERSION_CODE >= KERNEL_VERSION (3 ,9 ,0 )
478+ #define S_MAGIC_COMPAT (x ) ((x)->f_inode->i_sb->s_magic)
479+ #else
480+ #define S_MAGIC_COMPAT (x ) ((x)->f_path.dentry->d_inode->i_sb->s_magic)
481+ #endif
482+
483+ static void search_manager (const char * path , int depth , struct list_head * uid_data )
465484{
466485 int i , stop = 0 ;
467486 struct list_head data_path_list ;
@@ -498,7 +517,7 @@ void search_manager(const char *path, int depth, struct list_head *uid_data)
498517 pr_err ("Failed to open directory: %s, err: %ld\n" , pos -> dirpath , PTR_ERR (file ));
499518 goto skip_iterate ;
500519 }
501-
520+
502521 // grab magic on first folder, which is /data/app
503522 if (!data_app_magic ) {
504523 if (file -> f_inode -> i_sb -> s_magic ) {
@@ -557,26 +576,79 @@ extern bool ksu_uid_scanner_enabled;
557576void track_throne (void )
558577{
559578 struct list_head uid_list ;
560-
561- // init uid list head
579+ struct file * fp ;
580+ int ret = 0 ;
562581 INIT_LIST_HEAD (& uid_list );
563582
564- if (ksu_uid_scanner_enabled ) {
565- pr_info ("Scanning %s directory..\n" , KSU_UID_LIST_PATH );
566-
567- if (uid_from_um_list (& uid_list ) == 0 ) {
568- pr_info ("loaded uids from %s success\n" , KSU_UID_LIST_PATH );
569- } else {
570- pr_warn ("%s read failed, falling back to %s\n" , KSU_UID_LIST_PATH , USER_DATA_PATH );
571- if (scan_user_data_for_uids (& uid_list ) < 0 )
572- goto out ;
573- pr_info ("UserDE UID: Scanned %zu packages from user data directory\n" , list_count_nodes (& uid_list ));
574- }
583+ pr_info ("Scanning %s directory..\n" , USER_DATA_PATH );
584+ ret = scan_user_data_for_uids (& uid_list );
585+
586+ if (ret < 0 ) {
587+ pr_warn ("Failed to scan %s, falling back to %s\n" ,
588+ USER_DATA_PATH , SYSTEM_PACKAGES_LIST_PATH );
589+
590+ fp = ksu_filp_open_compat (SYSTEM_PACKAGES_LIST_PATH , O_RDONLY , 0 );
591+ if (IS_ERR (fp )) {
592+ pr_err ("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n" ,
593+ __func__ , PTR_ERR (fp ));
594+ return ;
595+ }
596+
597+ if (atomic_read (& pkg_lock ) != 1 ) {
598+ pr_info ("%s: locking to only read %s\n" , __func__ , SYSTEM_PACKAGES_LIST_PATH );
599+ atomic_set (& pkg_lock , 1 );
600+ }
601+
602+ char chr = 0 ;
603+ loff_t pos = 0 ;
604+ loff_t line_start = 0 ;
605+ char buf [KSU_MAX_PACKAGE_NAME ];
606+ for (;;) {
607+ ssize_t count = ksu_kernel_read_compat (fp , & chr , sizeof (chr ), & pos );
608+ if (count != sizeof (chr ))
609+ break ;
610+ if (chr != '\n' )
611+ continue ;
612+
613+ count = ksu_kernel_read_compat (fp , buf , sizeof (buf ), & line_start );
614+
615+ struct uid_data * data = kzalloc (sizeof (struct uid_data ), GFP_ATOMIC );
616+ if (!data ) {
617+ filp_close (fp , 0 );
618+ goto out ;
619+ }
620+
621+ char * tmp = buf ;
622+ const char * delim = " " ;
623+ char * package = strsep (& tmp , delim );
624+ char * uid = strsep (& tmp , delim );
625+ if (!uid || !package ) {
626+ pr_err ("update_uid: package or uid is NULL!\n" );
627+ break ;
628+ }
629+
630+ u32 res ;
631+ if (kstrtou32 (uid , 10 , & res )) {
632+ pr_err ("update_uid: uid parse err\n" );
633+ break ;
634+ }
635+ data -> uid = res ;
636+ strncpy (data -> package , package , KSU_MAX_PACKAGE_NAME );
637+ list_add_tail (& data -> list , & uid_list );
638+
639+ // reset line start
640+ line_start = pos ;
641+ }
642+ filp_close (fp , 0 );
575643 } else {
576- pr_info ("User mode scan status is %s, skipping scan %s\n" , ksu_uid_scanner_enabled ? "enabled" : "disabled" , KSU_UID_LIST_PATH );
577- if (scan_user_data_for_uids (& uid_list ) < 0 )
578- goto out ;
579- pr_info ("UserDE UID: Scanned %zu packages from user data directory\n" , list_count_nodes (& uid_list ));
644+ pr_info ("Scanned %zu package(s) from user data directory.\n" ,
645+ list_count_nodes (& uid_list ));
646+
647+ if (atomic_read (& scan_lock ) != 1 ) {
648+ pr_info ("%s: locking to only read %s directory.\n" ,
649+ __func__ , USER_DATA_PATH );
650+ atomic_set (& scan_lock , 1 );
651+ }
580652 }
581653
582654 // now update uid list
@@ -627,6 +699,7 @@ void track_throne(void)
627699prune :
628700 // then prune the allowlist
629701 ksu_prune_allowlist (is_uid_exist , & uid_list );
702+
630703out :
631704 // free uid_list
632705 list_for_each_entry_safe (np , n , & uid_list , list ) {
0 commit comments