Skip to content

Commit ee2a8f9

Browse files
rsuntkShirkNeko
authored andcommitted
kernel: scan /data/user_de/0 for actual UID (tiann#155) +
* Based on tiann#2759 - This may not perfect (such as lock), but tests were fine on ASUS Zenfone Max Pro M2 (X01BD), Android 16 (AOSP) - Any suggestion or bug reports is highly appreciated! Tested-by: rsuntk <[email protected]> Signed-off-by: rsuntk <[email protected]> Co-authored-by: ShirkNeko <[email protected]>
1 parent 33d673b commit ee2a8f9

File tree

2 files changed

+125
-28
lines changed

2 files changed

+125
-28
lines changed

kernel/kernel_compat.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,30 @@
66
#include <linux/cred.h>
77
#include "ss/policydb.h"
88
#include "linux/key.h"
9+
#include <linux/list.h>
10+
11+
/**
12+
* list_count_nodes - count the number of nodes in a list
13+
* the head of the list
14+
*
15+
* Returns the number of nodes in the list
16+
*/
17+
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
18+
static inline size_t list_count_nodes(const struct list_head *head)
19+
{
20+
const struct list_head *pos;
21+
size_t count = 0;
22+
23+
if (!head)
24+
return 0;
25+
26+
list_for_each(pos, head) {
27+
count++;
28+
}
29+
30+
return count;
31+
}
32+
#endif
933

1034
/**
1135
* list_count_nodes - count the number of nodes in a list

kernel/throne_tracker.c

Lines changed: 101 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
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
@@ -19,10 +20,23 @@
1920

2021
uid_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+
2640
struct 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;
557576
void 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)
627699
prune:
628700
// then prune the allowlist
629701
ksu_prune_allowlist(is_uid_exist, &uid_list);
702+
630703
out:
631704
// free uid_list
632705
list_for_each_entry_safe (np, n, &uid_list, list) {

0 commit comments

Comments
 (0)