From d58ec6952c79e5f9ddf3b36f310fed3e5db11d7a Mon Sep 17 00:00:00 2001 From: 5ec1cff Date: Mon, 2 Jun 2025 23:11:36 +0800 Subject: [PATCH] throne_tracker: avoid cross fs access --- kernel/throne_tracker.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/kernel/throne_tracker.c b/kernel/throne_tracker.c index adadbd9b..72ebbf6b 100644 --- a/kernel/throne_tracker.c +++ b/kernel/throne_tracker.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "allowlist.h" #include "klog.h" // IWYU pragma: keep @@ -115,6 +116,7 @@ struct my_dir_context { void *private_data; int depth; int *stop; + struct super_block* root_sb; }; // https://docs.kernel.org/filesystems/porting.html // filldir_t (readdir callbacks) calling conventions have changed. Instead of returning 0 or -E... it returns bool now. false means "no more" (as -E... used to) and true - "keep going" (as 0 in old calling conventions). Rationale: callers never looked at specific -E... values anyway. -> iterate_shared() instances require no changes at all, all filldir_t ones in the tree converted. @@ -135,6 +137,8 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name, struct my_dir_context *my_ctx = container_of(ctx, struct my_dir_context, ctx); char dirpath[DATA_PATH_LEN]; + int err; + struct path path; if (!my_ctx) { pr_err("Invalid context\n"); @@ -162,6 +166,18 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name, return FILLDIR_ACTOR_CONTINUE; } + err = kern_path(dirpath, 0, &path); + + if (err) { + pr_err("get dirpath %s err: %d\n", dirpath, err); + return FILLDIR_ACTOR_CONTINUE; + } + + if (my_ctx->root_sb != path.dentry->d_inode->i_sb) { + pr_info("skip cross fs: %s", dirpath); + return FILLDIR_ACTOR_CONTINUE; + } + if (d_type == DT_DIR && my_ctx->depth > 0 && (my_ctx->stop && !*my_ctx->stop)) { struct data_path *data = kmalloc(sizeof(struct data_path), GFP_ATOMIC); @@ -211,10 +227,19 @@ FILLDIR_RETURN_TYPE my_actor(struct dir_context *ctx, const char *name, void search_manager(const char *path, int depth, struct list_head *uid_data) { - int i, stop = 0; + int i, stop = 0, err; struct list_head data_path_list; + struct path kpath; + struct super_block* root_sb; INIT_LIST_HEAD(&data_path_list); + err = kern_path(path, 0, &kpath); + + if (err) { + pr_err("get search root %s err: %d\n", path, err); + return; + } + // Initialize APK cache list struct apk_path_hash *pos, *n; list_for_each_entry(pos, &apk_path_hash_list, list) { @@ -227,6 +252,8 @@ void search_manager(const char *path, int depth, struct list_head *uid_data) data.depth = depth; list_add_tail(&data.list, &data_path_list); + root_sb = kpath.dentry->d_inode->i_sb; + for (i = depth; i >= 0; i--) { struct data_path *pos, *n; @@ -236,7 +263,8 @@ void search_manager(const char *path, int depth, struct list_head *uid_data) .parent_dir = pos->dirpath, .private_data = uid_data, .depth = pos->depth, - .stop = &stop }; + .stop = &stop, + .root_sb = root_sb }; struct file *file; if (!stop) {