Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
1e921f2
kernel: Add the real UID by parsing the UID from the /data/user_de/0/…
ShirkNeko Sep 11, 2025
e53d9f0
Apply suggestions from code review
ShirkNeko Sep 12, 2025
8d323e1
Update Function Complete Documentation
ShirkNeko Sep 12, 2025
5b3bbfa
Remove redundant unused assignments
ShirkNeko Sep 12, 2025
e47775a
kernel: Remove fallback scan for packages.list
ShirkNeko Sep 12, 2025
853ff27
Merge branch 'main' into main
ShirkNeko Sep 13, 2025
7b52170
Revert packages.list Rename Search
ShirkNeko Sep 13, 2025
e3c9e77
kernel: Use iterate_dir for multi-user traversal instead of a fixed u…
ShirkNeko Sep 13, 2025
e7e161c
kernel: Simplify and improve readability
ShirkNeko Sep 15, 2025
0abbc2a
kernel: Add optional scanning of all user applications
ShirkNeko Sep 16, 2025
cf80204
kernel: Remove duplicate `#include <linux/list.h>`
ShirkNeko Sep 16, 2025
2254d31
kernel: Optimizing thread scheduling during user scans
ShirkNeko Sep 16, 2025
d131d66
kernel: Separate and modularize the user data scanner scan function
ShirkNeko Sep 16, 2025
8f0ed16
kernel: Enhanced user data scanning
ShirkNeko Sep 16, 2025
1cd3574
kernel: Add support for concurrent scanning of user data apps
ShirkNeko Sep 16, 2025
6815232
Revert "kernel: Add support for concurrent scanning of user data apps"
ShirkNeko Sep 17, 2025
2bb49c9
Revert "kernel: Enhanced user data scanning"
ShirkNeko Sep 17, 2025
2c58d77
Revert "kernel: Separate and modularize the user data scanner scan fu…
ShirkNeko Sep 17, 2025
4c8bbd6
Revert "kernel: Optimizing thread scheduling during user scans"
ShirkNeko Sep 17, 2025
34b3c85
Revert "kernel: Remove duplicate `#include <linux/list.h>`"
ShirkNeko Sep 17, 2025
1ad5437
Revert "kernel: Add optional scanning of all user applications"
ShirkNeko Sep 17, 2025
3e36132
Revert "kernel: Simplify and improve readability"
ShirkNeko Sep 17, 2025
b9d0fd0
Revert "kernel: Use iterate_dir for multi-user traversal instead of a…
ShirkNeko Sep 17, 2025
f3b8413
Revert "Revert packages.list Rename Search"
ShirkNeko Sep 17, 2025
6803986
Revert "Tweak shizuku template description (#2746)"
ShirkNeko Sep 17, 2025
34f00a9
Revert "kernel: Remove fallback scan for packages.list"
ShirkNeko Sep 17, 2025
8dea917
Revert "Remove redundant unused assignments"
ShirkNeko Sep 17, 2025
d1093a6
Revert "Update Function Complete Documentation"
ShirkNeko Sep 17, 2025
be95637
Reapply "Tweak shizuku template description (#2746)"
ShirkNeko Sep 17, 2025
4c9c634
Merge branch 'main' into user_de
ShirkNeko Sep 26, 2025
73a6cd5
fmt
ShirkNeko Sep 26, 2025
dbac9d4
kernel: No longer revert to `package.list`
ShirkNeko Sep 26, 2025
1c78b61
kernel: Supplementing the omitted exit
ShirkNeko Sep 26, 2025
7b8dc41
kernel: simplification, use static, reduce log spam by not printing u…
ShirkNeko Sep 27, 2025
f91f592
Merge branch 'main' into user_de
ShirkNeko Sep 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions kernel/kernel_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@
#include <linux/version.h>
#include "ss/policydb.h"
#include "linux/key.h"
#include <linux/list.h>

/**
* list_count_nodes - count the number of nodes in a list
* the head of the list
*
* Returns the number of nodes in the list
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)
static inline __maybe_unused size_t list_count_nodes(const struct list_head *head)
{
const struct list_head *pos;
size_t count = 0;

if (!head)
return 0;

list_for_each(pos, head)
count++;

return count;
}
#endif

/*
* Adapt to Huawei HISI kernel without affecting other kernels ,
Expand Down
198 changes: 147 additions & 51 deletions kernel/throne_tracker.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/version.h>
#include <linux/stat.h>
#include <linux/namei.h>

#include "allowlist.h"
#include "klog.h" // IWYU pragma: keep
Expand All @@ -15,7 +17,8 @@

uid_t ksu_manager_uid = KSU_INVALID_UID;

#define SYSTEM_PACKAGES_LIST_PATH "/data/system/packages.list.tmp"
#define USER_DATA_PATH "/data/user_de/0"
#define USER_DATA_PATH_LEN 288

struct uid_data {
struct list_head list;
Expand Down Expand Up @@ -128,6 +131,138 @@ struct my_dir_context {
#define FILLDIR_ACTOR_STOP -EINVAL
#endif

struct uid_scan_stats {
size_t total_found;
size_t errors_encountered;
};

struct user_data_context {
struct dir_context ctx;
struct list_head *uid_list;
struct uid_scan_stats *stats;
};

FILLDIR_RETURN_TYPE user_data_actor(struct dir_context *ctx, const char *name,
int namelen, loff_t off, u64 ino,
unsigned int d_type)
{
struct user_data_context *my_ctx =
container_of(ctx, struct user_data_context, ctx);

if (!my_ctx || !my_ctx->uid_list) {
return FILLDIR_ACTOR_STOP;
}

if (!strncmp(name, "..", namelen) || !strncmp(name, ".", namelen))
return FILLDIR_ACTOR_CONTINUE;

if (d_type != DT_DIR)
return FILLDIR_ACTOR_CONTINUE;

if (namelen >= KSU_MAX_PACKAGE_NAME) {
pr_warn("Package name too long: %.*s\n", namelen, name);
if (my_ctx->stats)
my_ctx->stats->errors_encountered++;
return FILLDIR_ACTOR_CONTINUE;
}

char package_path[USER_DATA_PATH_LEN];
if (snprintf(package_path, sizeof(package_path), "%s/%.*s",
USER_DATA_PATH, namelen, name) >= sizeof(package_path)) {
pr_err("Path too long for package: %.*s\n", namelen, name);
if (my_ctx->stats)
my_ctx->stats->errors_encountered++;
return FILLDIR_ACTOR_CONTINUE;
}

struct path path;
int err = kern_path(package_path, LOOKUP_FOLLOW, &path);
if (err) {
pr_debug("Package path lookup failed: %s (err: %d)\n", package_path, err);
if (my_ctx->stats)
my_ctx->stats->errors_encountered++;
return FILLDIR_ACTOR_CONTINUE;
}

struct kstat stat;
err = vfs_getattr(&path, &stat, STATX_UID, AT_STATX_SYNC_AS_STAT);
path_put(&path);

if (err) {
pr_debug("Failed to get attributes for: %s (err: %d)\n", package_path, err);
if (my_ctx->stats)
my_ctx->stats->errors_encountered++;
return FILLDIR_ACTOR_CONTINUE;
}

uid_t uid = from_kuid(&init_user_ns, stat.uid);
if (uid == (uid_t)-1) {
pr_warn("Invalid UID for package: %.*s\n", namelen, name);
if (my_ctx->stats)
my_ctx->stats->errors_encountered++;
return FILLDIR_ACTOR_CONTINUE;
}

struct uid_data *data = kzalloc(sizeof(struct uid_data), GFP_ATOMIC);
if (!data) {
pr_err("Failed to allocate memory for package: %.*s\n", namelen, name);
if (my_ctx->stats)
my_ctx->stats->errors_encountered++;
return FILLDIR_ACTOR_CONTINUE;
}

data->uid = uid;
size_t copy_len = min(namelen, KSU_MAX_PACKAGE_NAME - 1);
strncpy(data->package, name, copy_len);
data->package[copy_len] = '\0';

list_add_tail(&data->list, my_ctx->uid_list);

if (my_ctx->stats)
my_ctx->stats->total_found++;
#ifdef CONFIG_KSU_DEBUG
pr_info("UserDE UID: Found package: %s, uid: %u\n", data->package, data->uid);
#endif

return FILLDIR_ACTOR_CONTINUE;
}

static int scan_user_data_for_uids(struct list_head *uid_list)
{
struct file *dir_file;
struct uid_scan_stats stats = {0};
int ret = 0;

if (!uid_list) {
return -EINVAL;
}

dir_file = ksu_filp_open_compat(USER_DATA_PATH, O_RDONLY, 0);
if (IS_ERR(dir_file)) {
pr_err("UserDE UID: Failed to open %s, err: (%ld)\n", USER_DATA_PATH, PTR_ERR(dir_file));
return PTR_ERR(dir_file);
}

struct user_data_context ctx = {
.ctx.actor = user_data_actor,
.uid_list = uid_list,
.stats = &stats
};

ret = iterate_dir(dir_file, &ctx.ctx);
filp_close(dir_file, NULL);

if (stats.errors_encountered > 0) {
pr_warn("Encountered %zu errors while scanning user data directory\n",
stats.errors_encountered);
}

pr_info("UserDE UID: Scanned %s directory with %zu errors\n",
USER_DATA_PATH, stats.errors_encountered);

return ret;
}

FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name,
int namelen, loff_t off, u64 ino,
unsigned int d_type)
Expand Down Expand Up @@ -301,60 +436,21 @@ static bool is_uid_exist(uid_t uid, char *package, void *data)

void track_throne()
{
struct file *fp =
ksu_filp_open_compat(SYSTEM_PACKAGES_LIST_PATH, O_RDONLY, 0);
if (IS_ERR(fp)) {
pr_err("%s: open " SYSTEM_PACKAGES_LIST_PATH " failed: %ld\n",
__func__, PTR_ERR(fp));
return;
}

struct list_head uid_list;
int ret;

// init uid list head
INIT_LIST_HEAD(&uid_list);

char chr = 0;
loff_t pos = 0;
loff_t line_start = 0;
char buf[KSU_MAX_PACKAGE_NAME];
for (;;) {
ssize_t count =
ksu_kernel_read_compat(fp, &chr, sizeof(chr), &pos);
if (count != sizeof(chr))
break;
if (chr != '\n')
continue;

count = ksu_kernel_read_compat(fp, buf, sizeof(buf),
&line_start);

struct uid_data *data =
kzalloc(sizeof(struct uid_data), GFP_ATOMIC);
if (!data) {
filp_close(fp, 0);
goto out;
}

char *tmp = buf;
const char *delim = " ";
char *package = strsep(&tmp, delim);
char *uid = strsep(&tmp, delim);
if (!uid || !package) {
pr_err("update_uid: package or uid is NULL!\n");
break;
}

u32 res;
if (kstrtou32(uid, 10, &res)) {
pr_err("update_uid: uid parse err\n");
break;
}
data->uid = res;
strncpy(data->package, package, KSU_MAX_PACKAGE_NAME);
list_add_tail(&data->list, &uid_list);
// reset line start
line_start = pos;
pr_info("Scanning %s directory..\n", USER_DATA_PATH);
ret = scan_user_data_for_uids(&uid_list);

if (ret < 0) {
pr_err("Failed to scan %s directory, err: %d\n", USER_DATA_PATH, ret);
goto out;
} else {
pr_info("Scanned %zu packages from user data directory\n", list_count_nodes(&uid_list));
}
filp_close(fp, 0);

// now update uid list
struct uid_data *np;
Expand Down
Loading