kernel: Use iterate_dir for multi-user traversal instead of a fixed user ID range.

This commit is contained in:
ShirkNeko
2025-09-13 21:24:40 +08:00
parent eb87c1355b
commit 63d9bdd9d6

View File

@@ -21,8 +21,6 @@ uid_t ksu_manager_uid = KSU_INVALID_UID;
#define USER_DATA_BASE_PATH "/data/user_de" #define USER_DATA_BASE_PATH "/data/user_de"
#define MAX_SUPPORTED_USERS 32 // Supports up to 32 users #define MAX_SUPPORTED_USERS 32 // Supports up to 32 users
#define USER_DATA_PATH_LEN 384 // 384 is enough for /data/user_de/{userid}/<package> #define USER_DATA_PATH_LEN 384 // 384 is enough for /data/user_de/{userid}/<package>
#define MAX_ANDROID_USER_ID 999
#define MIN_ANDROID_USER_ID 0
struct uid_data { struct uid_data {
struct list_head list; struct list_head list;
@@ -162,14 +160,45 @@ struct user_data_context {
struct user_scan_context *scan_ctx; struct user_scan_context *scan_ctx;
}; };
struct user_de_context {
struct dir_context ctx;
uid_t *user_ids;
size_t count;
size_t max_users;
};
// Actor function to collect user IDs from /data/user_de
FILLDIR_RETURN_TYPE user_de_actor(struct dir_context *ctx, const char *name,
int namelen, loff_t off, u64 ino,
unsigned int d_type)
{
struct user_de_context *data = container_of(ctx, struct user_de_context, ctx);
if (d_type != DT_DIR)
return FILLDIR_ACTOR_CONTINUE;
if (strncmp(name, ".", namelen) == 0 || strncmp(name, "..", namelen) == 0)
return FILLDIR_ACTOR_CONTINUE;
uid_t uid = 0;
for (int i = 0; i < namelen; i++) {
if (name[i] < '0' || name[i] > '9')
return FILLDIR_ACTOR_CONTINUE;
uid = uid * 10 + (name[i] - '0');
}
if (data->count >= data->max_users)
return FILLDIR_ACTOR_STOP;
data->user_ids[data->count++] = uid;
return FILLDIR_ACTOR_CONTINUE;
}
// Retrieve a list of all active Android user IDs in the system // Retrieve a list of all active Android user IDs in the system
static int get_active_user_ids(uid_t *user_ids, size_t max_users, size_t *found_users) static int get_active_user_ids(uid_t *user_ids, size_t max_users, size_t *found_users)
{ {
struct file *dir_file; struct file *dir_file;
int ret = 0; int ret = 0;
size_t count = 0;
const char *opened_base = NULL;
*found_users = 0; *found_users = 0;
@@ -179,27 +208,26 @@ static int get_active_user_ids(uid_t *user_ids, size_t max_users, size_t *found_
USER_DATA_BASE_PATH, PTR_ERR(dir_file)); USER_DATA_BASE_PATH, PTR_ERR(dir_file));
return PTR_ERR(dir_file); return PTR_ERR(dir_file);
} }
opened_base = USER_DATA_BASE_PATH;
for (uid_t user_id = MIN_ANDROID_USER_ID; struct {
user_id <= MAX_ANDROID_USER_ID && count < max_users; struct dir_context ctx;
user_id++) { uid_t *user_ids;
size_t count;
char user_path[USER_DATA_PATH_LEN]; size_t max_users;
struct path path; } ctx = {
.ctx.actor = user_de_actor,
snprintf(user_path, sizeof(user_path), "%s/%u", opened_base, user_id); .user_ids = user_ids,
.count = 0,
if (!kern_path(user_path, 0, &path)) { .max_users = max_users
user_ids[count++] = user_id; };
path_put(&path);
}
}
ret = iterate_dir(dir_file, &ctx.ctx);
filp_close(dir_file, NULL); filp_close(dir_file, NULL);
*found_users = count;
if (count > 0) *found_users = ctx.count;
pr_info("UserDE UID: Found %zu active users\n", count);
if (ctx.count > 0)
pr_info("UserDE UID: Found %zu active users\n", ctx.count);
return ret; return ret;
} }