From a9b8f23c1455de6149e4ec5af09d2b4f928f59e9 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Sun, 12 Apr 2026 12:48:30 +0800 Subject: [PATCH 01/15] support manager verify --- kernel/.gitignore | 7 +- kernel/linux/include/linux/fs.h | 18 + kernel/patch/android/userd.c | 633 +++++++++++++++++++++++++++++-- kernel/patch/common/supercall.c | 13 +- kernel/patch/common/supercmd.c | 9 +- kernel/patch/common/user_event.c | 10 +- kernel/patch/include/userd.h | 12 +- kernel/patch/ksyms/misc.c | 4 +- tools/patch.c | 2 +- 9 files changed, 669 insertions(+), 39 deletions(-) diff --git a/kernel/.gitignore b/kernel/.gitignore index 33132a55..91ab46aa 100644 --- a/kernel/.gitignore +++ b/kernel/.gitignore @@ -19,4 +19,9 @@ # kernel patch module *.kpm -kpimg \ No newline at end of file +kpimg + +*.img +kernel +kernel-b +*.bat \ No newline at end of file diff --git a/kernel/linux/include/linux/fs.h b/kernel/linux/include/linux/fs.h index 896915fb..d566df3d 100644 --- a/kernel/linux/include/linux/fs.h +++ b/kernel/linux/include/linux/fs.h @@ -357,6 +357,24 @@ static inline loff_t vfs_llseek(struct file *file, loff_t offset, int whence) kfunc_direct_call(vfs_llseek, file, offset, whence); } +/* Directory iteration context (kernel 3.11+). + * Actor signature: int return (4.x) or bool return (5.0+) — both are ABI-compatible + * on arm64 for 0/1 values, so we use the 5.0+ bool form to satisfy the compiler. + */ +struct dir_context { + bool (*actor)(struct dir_context *, const char *, int, loff_t, u64, unsigned int); + loff_t pos; +}; + +extern int kfunc_def(iterate_dir)(struct file *, struct dir_context *); + +static inline int iterate_dir(struct file *file, struct dir_context *ctx) +{ + kfunc_call(iterate_dir, file, ctx); + kfunc_not_found(); + return 0; /* symbol not resolved; caller checks result via its context */ +} + static inline void putname(struct filename *name) { kfunc_direct_call_void(putname, name); diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 5a27538a..ca567de9 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -29,12 +29,17 @@ #include #include #include -#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include #define REPLACE_RC_FILE "/dev/user_init.rc" @@ -48,6 +53,26 @@ #define APD_PATH "/data/adb/apd" #define MAGISK_POLICY_PATH "/data/adb/ap/bin/magiskpolicy" #define AP_PACKAGE_CONFIG_PATH "/data/adb/ap/package_config" +#define ANDROID_PACKAGES_LIST_PATH "/data/system/packages.list" +#define TRUSTED_MANAGER_PACKAGE "me.bmax.apatch" +#define APK_SIG_BLOCK_MAGIC "APK Sig Block 42" +#define APK_SIG_BLOCK_MAGIC_LEN 16 +#define APK_SIG_SCHEME_V2_BLOCK_ID 0x7109871au +#define APK_SIG_SCHEME_V3_BLOCK_ID 0xf05368c0u +#define APK_SIG_SCHEME_V31_BLOCK_ID 0x1b93ad61u +#define APK_CERT_MAX_LENGTH 4096 + +#define TRUSTED_MANAGER_DIGEST_LEN SHA256_BLOCK_SIZE +#define TRUSTED_MANAGER_UID_INVALID ((uid_t)-1) + +static const uint8_t trusted_manager_signature_digest[TRUSTED_MANAGER_DIGEST_LEN] = { + 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, + 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, + 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, + 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 +}; + +static uid_t trusted_manager_uid = TRUSTED_MANAGER_UID_INVALID; @@ -93,9 +118,14 @@ static const void *kernel_read_file(const char *path, loff_t *len) } *len = vfs_llseek(filp, 0, SEEK_END); vfs_llseek(filp, 0, SEEK_SET); - data = vmalloc(*len); + data = vmalloc(*len + 1); + if (!data) { + filp_close(filp, 0); + goto out; + } loff_t pos = 0; kernel_read(filp, data, *len, &pos); + ((char *)data)[*len] = '\0'; filp_close(filp, 0); out: @@ -103,30 +133,571 @@ static const void *kernel_read_file(const char *path, loff_t *len) return data; } -static loff_t kernel_write_file(const char *path, const void *data, loff_t len, umode_t mode) +static int path_has_suffix(const char *path, const char *suffix) { - loff_t off = 0; - set_priv_sel_allow(current, true); + size_t path_len; + size_t suffix_len; + if (!path || !suffix) return 0; + path_len = strlen(path); + suffix_len = strlen(suffix); + if (path_len < suffix_len) return 0; + return strcmp(path + path_len - suffix_len, suffix) == 0; +} + +static int path_is_exact(const char *path, const char *target) +{ + return path && target && strcmp(path, target) == 0; +} + +static int read_le32(struct file *fp, loff_t *pos, uint32_t *out) +{ + return kernel_read(fp, out, sizeof(*out), pos) == sizeof(*out) ? 0 : -EIO; +} + +static int read_le64(struct file *fp, loff_t *pos, uint64_t *out) +{ + return kernel_read(fp, out, sizeof(*out), pos) == sizeof(*out) ? 0 : -EIO; +} + +static int skip_bytes(loff_t *pos, uint64_t len) +{ + *pos += (loff_t)len; + return 0; +} + +static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_len) +{ + log_boot("[TM] ENTER cert match func\n"); + uint8_t digest[SHA256_BLOCK_SIZE]; + SHA256_CTX ctx; + + sha256_init(&ctx); + sha256_update(&ctx, cert_der, cert_len); + sha256_final(&ctx, digest); + + int i; + + log_boot("[TM] calc digest: "); + for (i = 0; i < TRUSTED_MANAGER_DIGEST_LEN; i++) { + log_boot("%02x", digest[i]); + } + log_boot("\n"); + + log_boot("[TM] expect digest: "); + for (i = 0; i < TRUSTED_MANAGER_DIGEST_LEN; i++) { + log_boot("%02x", trusted_manager_signature_digest[i]); + } + log_boot("\n"); + + return lib_memcmp(digest, trusted_manager_signature_digest, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; +} + +struct zip_entry_header +{ + uint32_t signature; + uint16_t version; + uint16_t flags; + uint16_t compression; + uint16_t mod_time; + uint16_t mod_date; + uint32_t crc32; + uint32_t compressed_size; + uint32_t uncompressed_size; + uint16_t file_name_length; + uint16_t extra_field_length; +} __attribute__((packed)); + +static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4, loff_t *pos, uint32_t *offset) +{ + uint8_t *cert_buf; + + if (read_le32(fp, pos, size4)) return 0; // signer-sequence length + if (read_le32(fp, pos, size4)) return 0; // signer length + if (read_le32(fp, pos, size4)) return 0; // signed data length + *offset += sizeof(*size4) * 3; + + if (read_le32(fp, pos, size4)) return 0; // digests-sequence length + if (skip_bytes(pos, *size4)) return 0; + *offset += sizeof(*size4) + *size4; + + if (read_le32(fp, pos, size4)) return 0; // certificates length + if (read_le32(fp, pos, size4)) return 0; // certificate length + *offset += sizeof(*size4) * 2; + + if (*size4 == 0 || *size4 > APK_CERT_MAX_LENGTH) { + log_boot("trusted manager apk cert length invalid: %u\n", *size4); + return 0; + } + + *offset += *size4; + cert_buf = vmalloc(*size4); + if (!cert_buf) { + return 0; + } + + if (kernel_read(fp, cert_buf, *size4, pos) != *size4) { + kvfree(cert_buf); + return 0; + } + + if (!cert_der_matches_trusted_digest(cert_buf, *size4)) { + kvfree(cert_buf); + return 2; + } + + kvfree(cert_buf); + return 1; +} + +static int apk_has_v1_signature_file(struct file *fp) +{ + static const char manifest[] = "META-INF/MANIFEST.MF"; + struct zip_entry_header header; + loff_t pos = 0; + + while (kernel_read(fp, &header, sizeof(header), &pos) == sizeof(header)) { + if (header.signature != 0x04034b50u) { + return 0; + } + + if (header.file_name_length == sizeof(manifest) - 1) { + char file_name[sizeof(manifest)]; + if (kernel_read(fp, file_name, header.file_name_length, &pos) != header.file_name_length) { + return 0; + } + file_name[header.file_name_length] = '\0'; + if (strncmp(file_name, manifest, sizeof(manifest) - 1) == 0) { + return 1; + } + } else if (skip_bytes(&pos, header.file_name_length)) { + return 0; + } - struct file *fp = filp_open(path, O_WRONLY | O_CREAT | O_TRUNC, mode); + if (skip_bytes(&pos, (uint64_t)header.extra_field_length + header.compressed_size)) { + return 0; + } + } + + return 0; +} + +static int apk_matches_trusted_signature(const char *path) +{ + int i; + int rc = 0; + int v2_blocks = 0; + int v2_valid = 0; + int v3_present = 0; + int v31_present = 0; + uint8_t magic[APK_SIG_BLOCK_MAGIC_LEN + 1] = { 0 }; + uint32_t size4; + uint64_t size8; + uint64_t size_of_block; + loff_t pos; + struct file *fp; + + if (!path || !path[0]) return 0; + + set_priv_sel_allow(current, true); + fp = filp_open(path, O_RDONLY, 0); if (!fp || IS_ERR(fp)) { - log_boot("create file %s error: %d\n", path, PTR_ERR(fp)); + log_boot("trusted manager apk open failed: %s rc=%ld\n", path, PTR_ERR(fp)); + set_priv_sel_allow(current, false); + return 0; + } + + for (i = 0; i <= 0xffff; i++) { + unsigned short n = 0; + pos = vfs_llseek(fp, -i - 2, SEEK_END); + if (pos < 0) { + continue; + } + if (kernel_read(fp, &n, sizeof(n), &pos) != sizeof(n)) { + continue; + } + if (n == i) { + pos -= 22; + if (!read_le32(fp, &pos, &size4) && size4 == 0x06054b50u) { + break; + } + } + } + + if (i > 0xffff) { goto out; } - kernel_write(fp, data, len, &off); - if (off != len) { - log_boot("write file %s error: %x\n", path, off); - goto free; + + pos += 12; + if (read_le32(fp, &pos, &size4)) { + goto out; } + pos = (loff_t)size4 - 0x18; -free: - filp_close(fp, 0); + if (read_le64(fp, &pos, &size8)) { + goto out; + } + if (kernel_read(fp, magic, APK_SIG_BLOCK_MAGIC_LEN, &pos) != APK_SIG_BLOCK_MAGIC_LEN) { + goto out; + } + if (strncmp((char *)magic, APK_SIG_BLOCK_MAGIC, APK_SIG_BLOCK_MAGIC_LEN) != 0) { + goto out; + } + + pos = (loff_t)size4 - (loff_t)(size8 + 0x8); + if (read_le64(fp, &pos, &size_of_block)) { + goto out; + } + if (size_of_block != size8) { + goto out; + } + + for (i = 0; i < 16; i++) { + uint32_t id; + uint32_t offset = sizeof(id); + if (read_le64(fp, &pos, &size8)) { + goto out; + } + if (size8 == size_of_block) { + break; + } + if (read_le32(fp, &pos, &id)) { + goto out; + } + + if (id == APK_SIG_SCHEME_V2_BLOCK_ID) { + int match; + v2_blocks++; + match = apk_sig_block_matches_trusted_digest(fp, &size4, &pos, &offset); + if (match == 2) { + v2_valid = 1; + } + } else if (id == APK_SIG_SCHEME_V3_BLOCK_ID) { + v3_present = 1; + } else if (id == APK_SIG_SCHEME_V31_BLOCK_ID) { + v31_present = 1; + } + + if (size8 < offset) { + log_boot("trusted manager apk sig block size invalid: %llu offset: %u\n", size8, offset); + goto out; + } + if (skip_bytes(&pos, size8 - offset)) { + log_boot("trusted manager apk sig block skip failed\n"); + goto out; + } + } + + if (!v2_valid) { + log_boot("trusted manager apk sig block invalid: v2_blocks=%d v2_valid=%d v3_present=%d v31_present=%d\n", + v2_blocks, v2_valid, v3_present, v31_present); + goto out; + } + + // if (apk_has_v1_signature_file(fp)) { + // log_boot("trusted manager apk has v1 signature file, which is not allowed\n"); + // goto out; + // } + + rc = 1; out: + filp_close(fp, 0); set_priv_sel_allow(current, false); - return off; + return rc; } +static int lookup_package_list_uid(const char *package_name, uid_t *trusted_uid_out) +{ + loff_t len = 0; + char *content = (char *)kernel_read_file(ANDROID_PACKAGES_LIST_PATH, &len); + char *cursor; + char *end; + + if (!trusted_uid_out) return -EINVAL; + if (!content || len <= 0) { + log_boot("trusted manager: failed to read %s\n", ANDROID_PACKAGES_LIST_PATH); + return -ENOENT; + } + + cursor = content; + end = content + len; + while (cursor < end) { + char *line = cursor; + char *line_end = cursor; + char *pkg; + char *uid_str; + unsigned long long uid_raw = 0; + + while (line_end < end && *line_end != '\n' && *line_end != '\r') { + line_end++; + } + if (line_end < end) { + *line_end = '\0'; + cursor = line_end + 1; + } else { + cursor = end; + } + + while (*line && isspace(*line)) { + line++; + } + if (!*line) { + continue; + } + + pkg = line; + while (*line && !isspace(*line)) { + line++; + } + if (!*line) { + continue; + } + *line++ = '\0'; + + while (*line && isspace(*line)) { + line++; + } + if (!*line) { + continue; + } + + uid_str = line; + while (*line && !isspace(*line)) { + line++; + } + *line = '\0'; + + if (strcmp(pkg, package_name) != 0) { + continue; + } + if (kstrtoull(uid_str, 10, &uid_raw) || uid_raw > UINT_MAX) { + kvfree(content); + return -EINVAL; + } + + *trusted_uid_out = (uid_t)uid_raw; + kvfree(content); + return 0; + } + + kvfree(content); + return -ENOENT; +} + +/* + * Kernel-space APK path discovery using iterate_dir. + * Avoids shell/usermodehelper SELinux restrictions and packages.xml (binary + * protobuf on Android 11+). + * + * Android 11+ layout: /data/app/~~/me.bmax.apatch-/base.apk + * Pre-Android-11: /data/app/me.bmax.apatch-/base.apk + * + * We try both layouts: first a shallow scan of /data/app/ (pre-11), then a + * two-level scan through the tilde-scramble directories (11+). + */ + +/* Inner callback: scan one directory for a subdir starting with + * TRUSTED_MANAGER_PACKAGE "-". + */ +struct apk_inner_ctx { + struct dir_context dctx; /* MUST be first member for safe cast */ + const char *outer_dir; /* parent path, e.g. "/data/app/~~abc/" */ + char *result; + size_t result_len; + int found; +}; + +static bool apk_inner_actor(struct dir_context *dctx, const char *name, int namelen, + loff_t offset, u64 ino, unsigned int d_type) +{ + struct apk_inner_ctx *ctx = (struct apk_inner_ctx *)dctx; + static const char pkg_prefix[] = TRUSTED_MANAGER_PACKAGE "-"; + static const char base_apk[] = "/base.apk"; + const size_t prefix_len = sizeof(pkg_prefix) - 1; + size_t outer_len, path_len; + + if (ctx->found) return false; /* already done, stop iteration */ + + if ((size_t)namelen < prefix_len) return true; + if (memcmp(name, pkg_prefix, prefix_len) != 0) return true; + + /* Construct: outer_dir + name + "/base.apk\0" */ + outer_len = strlen(ctx->outer_dir); + path_len = outer_len + (size_t)namelen + sizeof(base_apk); + if (path_len > ctx->result_len) return true; /* won't fit, skip */ + + memcpy(ctx->result, ctx->outer_dir, outer_len); + memcpy(ctx->result + outer_len, name, (size_t)namelen); + memcpy(ctx->result + outer_len + namelen, base_apk, sizeof(base_apk)); + ctx->found = 1; + return false; /* stop */ +} + +/* Outer callback: scan /data/app/ for ~~* scramble directories, then descend */ +struct apk_outer_ctx { + struct dir_context dctx; /* MUST be first member */ + char *result; + size_t result_len; + int found; + char inner_path[256]; /* "/data/app/~~/" */ +}; + +static bool apk_outer_actor(struct dir_context *dctx, const char *name, int namelen, + loff_t offset, u64 ino, unsigned int d_type) +{ + struct apk_outer_ctx *ctx = (struct apk_outer_ctx *)dctx; + struct apk_inner_ctx inner; + struct file *inner_dir; + int len; + + if (ctx->found) return false; + + /* Only descend into ~~* directories (Android 11+ scramble dirs) */ + if (namelen < 2 || name[0] != '~' || name[1] != '~') return true; + + len = snprintf(ctx->inner_path, sizeof(ctx->inner_path), + "/data/app/%.*s/", namelen, name); + if (len <= 0 || len >= (int)sizeof(ctx->inner_path)) return true; + + inner_dir = filp_open(ctx->inner_path, O_RDONLY, 0); + if (!inner_dir || IS_ERR(inner_dir)) return true; + + inner.dctx.actor = apk_inner_actor; + inner.dctx.pos = 0; + inner.outer_dir = ctx->inner_path; + inner.result = ctx->result; + inner.result_len = ctx->result_len; + inner.found = 0; + + iterate_dir(inner_dir, &inner.dctx); + filp_close(inner_dir, 0); + + if (inner.found) { + ctx->found = 1; + return false; + } + return true; +} + +static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len) +{ + struct apk_outer_ctx outer; + struct apk_inner_ctx flat; + struct file *app_dir; + int rc; + + if (!apk_path || apk_path_len == 0) return -EINVAL; + apk_path[0] = '\0'; + + set_priv_sel_allow(current, true); + app_dir = filp_open("/data/app/", O_RDONLY, 0); + if (!app_dir || IS_ERR(app_dir)) { + log_boot("trusted manager apk err: open /data/app/ rc=%ld\n", PTR_ERR(app_dir)); + set_priv_sel_allow(current, false); + return -ENOENT; + } + + /* Pass 1: shallow scan for pre-Android-11 layout (me.bmax.apatch-N directly + * under /data/app/). Reuse apk_inner_actor with outer_dir="/data/app/". */ + flat.dctx.actor = apk_inner_actor; + flat.dctx.pos = 0; + flat.outer_dir = "/data/app/"; + flat.result = apk_path; + flat.result_len = apk_path_len; + flat.found = 0; + iterate_dir(app_dir, &flat.dctx); + + if (flat.found) { + filp_close(app_dir, 0); + set_priv_sel_allow(current, false); + log_boot("trusted manager apk: candidate path=%s (flat)\n", apk_path); + return 0; + } + + /* Pass 2: two-level scan for Android 11+ scramble layout */ + vfs_llseek(app_dir, 0, SEEK_SET); /* rewind directory */ + outer.dctx.actor = apk_outer_actor; + outer.dctx.pos = 0; + outer.result = apk_path; + outer.result_len = apk_path_len; + outer.found = 0; + rc = iterate_dir(app_dir, &outer.dctx); + + filp_close(app_dir, 0); + set_priv_sel_allow(current, false); + + if (outer.found) { + log_boot("trusted manager apk: candidate path=%s (scramble)\n", apk_path); + return 0; + } + + log_boot("trusted manager apk err: " TRUSTED_MANAGER_PACKAGE + " not found in /data/app/ (rc=%d)\n", rc); + return -ENOENT; +} + +static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out) +{ + char apk_path[PATH_MAX]; + int rc; + + if (!trusted_uid_out) return -EINVAL; + + rc = find_trusted_manager_apk_path(apk_path, sizeof(apk_path)); + if (rc) { + log_boot("trusted manager refresh: no candidate apk rc=%d\n", rc); + return rc; + } + + if (!apk_matches_trusted_signature(apk_path)) { + log_boot("trusted manager refresh: apk signature invalid apk=%s\n", apk_path); + return -EPERM; + } + + rc = lookup_package_list_uid(TRUSTED_MANAGER_PACKAGE, trusted_uid_out); + log_boot("trusted manager refresh: packages.list rc=%d uid=%u apk=%s\n", + rc, rc ? 0 : *trusted_uid_out, apk_path); + return rc; +} + +int refresh_trusted_manager_uid(void) +{ + return refresh_trusted_manager_state(); +} + +int refresh_trusted_manager_state(void) +{ + uid_t uid = TRUSTED_MANAGER_UID_INVALID; + int rc = refresh_trusted_manager_uid_from_packages_list(&uid); + if (rc) { + trusted_manager_uid = TRUSTED_MANAGER_UID_INVALID; + log_boot("trusted manager refresh failed rc=%d\n", rc); + return rc; + } + + trusted_manager_uid = uid; + log_boot("trusted manager refresh success uid=%u\n", uid); + return 0; +} +KP_EXPORT_SYMBOL(refresh_trusted_manager_uid); +KP_EXPORT_SYMBOL(refresh_trusted_manager_state); + +int is_trusted_manager_uid(uid_t uid) +{ + uid_t trusted_uid = trusted_manager_uid; + if (trusted_uid == TRUSTED_MANAGER_UID_INVALID) { + return 0; + } + return uid == trusted_uid; +} +KP_EXPORT_SYMBOL(is_trusted_manager_uid); + +uid_t get_trusted_manager_uid(void) +{ + return trusted_manager_uid; +} +KP_EXPORT_SYMBOL(get_trusted_manager_uid); + // Simple CSV field parser helper function static char *parse_csv_field(char **line_ptr) { @@ -387,6 +958,13 @@ static void handle_before_execve(hook_local_t *hook_local, char **__user u_filen // unhook flag hook_local->data7 = 0; + // Check if current process is trusted manager, set auto-su flag + if (is_trusted_manager_uid(current_uid())) { + hook_local->data0 = 1; + } else { + hook_local->data0 = 0; + } + static char app_process[] = "/system/bin/app_process"; static char app_process64[] = "/system/bin/app_process64"; static int first_app_process_execed = 0; @@ -462,8 +1040,13 @@ static void after_execve(hook_fargs3_t *args, void *udata); static void before_execveat(hook_fargs5_t *args, void *udata); static void after_execveat(hook_fargs5_t *args, void *udata); -static void handle_after_execve(hook_local_t *hook_local) +static void handle_after_execve(hook_local_t *hook_local, long ret) { + // Auto-su for processes executed by trusted manager + if (hook_local->data0 && ret >= 0) { + commit_su(0, all_allow_sctx); + } + int unhook = hook_local->data7; if (unhook) { unhook_syscalln(__NR_execve, before_execve, after_execve); @@ -484,7 +1067,7 @@ static void before_execve(hook_fargs3_t *args, void *udata) static void after_execve(hook_fargs3_t *args, void *udata) { - handle_after_execve(&args->local); + handle_after_execve(&args->local, args->ret); } // https://elixir.bootlin.com/linux/v6.1/source/fs/exec.c#L2095 @@ -500,7 +1083,7 @@ static void before_execveat(hook_fargs5_t *args, void *udata) static void after_execveat(hook_fargs5_t *args, void *udata) { - handle_after_execve(&args->local); + handle_after_execve(&args->local, args->ret); } // https://elixir.bootlin.com/linux/v6.1/source/fs/open.c#L1337 @@ -514,20 +1097,16 @@ static void before_openat(hook_fargs4_t *args, void *udata) args->local.data1 = 0; // unhook flag args->local.data2 = 0; - /* Meaning of args->local.data3 values: - * 0 = no match - * 1 = ORIGIN_RC_FILES[0] - * 2 = ORIGIN_RC_FILES[1] - */ args->local.data3 = 0; static int replaced = 0; - if (replaced) return; const char __user *filename = (typeof(filename))syscall_argn(args, 1); - char buf[64]; + char buf[256]; long rc = compat_strncpy_from_user(buf, filename, sizeof(buf)); if (rc <= 0) return; + if (replaced) return; + int file_count = sizeof(ORIGIN_RC_FILES) / sizeof(ORIGIN_RC_FILES[0]); for (int i = 0; i < file_count; i++) { if (ORIGIN_RC_FILES[i][0] == '\0') break; @@ -595,7 +1174,6 @@ static void before_openat(hook_fargs4_t *args, void *udata) static void after_openat(hook_fargs4_t *args, void *udata) { - if (args->local.data0 && args->local.data3 > 0) { const char *origin_rc = ORIGIN_RC_FILES[args->local.data3 - 1]; @@ -605,11 +1183,6 @@ static void after_openat(hook_fargs4_t *args, void *udata) sizeof(ORIGIN_RC_FILES[args->local.data3 - 1])); log_boot("restore rc file: %x\n", args->local.data0); } - - - if (args->local.data2) { - unhook_syscalln(__NR_openat, before_openat, after_openat); - } } #define EV_KEY 0x01 #define KEY_VOLUMEDOWN 114 diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 21e46509..7deea1ab 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -31,6 +31,9 @@ #include #include #include +#ifdef ANDROID +#include +#endif #define MAX_KEY_LEN 128 @@ -375,6 +378,12 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3 return -ENOSYS; } +#ifndef ANDROID +static int is_trusted_manager_uid(uid_t uid) +{ + return 1; +} +#endif static void before(hook_fargs6_t *args, void *udata) { @@ -398,9 +407,9 @@ static void before(hook_fargs6_t *args, void *udata) is_key_auth = 1; } else if (!strcmp("su", key)) { uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; + if (!is_su_allow_uid(uid) && !is_trusted_manager_uid(uid)) return; } else { - return; + if (!is_trusted_manager_uid(current_uid())) return; } long a1 = (long)syscall_argn(args, 2); diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index c1e2718e..1c83663f 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -16,6 +16,10 @@ #include #include #include +#include +#ifdef ANDROID +#include +#endif static char *__user supercmd_str_to_user_sp(const char *data, uintptr_t *sp) { @@ -227,6 +231,7 @@ static void handle_cmd_sumgr(char **__user u_filename_p, const char **carr, char } } + // superkey commands static void handle_cmd_key_auth(char **__user u_filename_p, const char *cmd, const char **carr, char *buffer, int buflen, struct cmd_res *cmd_res) @@ -453,7 +458,9 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) goto echo; #ifdef ANDROID } else if (!strcmp("reload-cfg", cmd)) { - load_ap_package_config(); + int trust_rc = refresh_trusted_manager_state(); + int config_rc = load_ap_package_config(); + log_boot("reload-cfg: refresh rc=%d package_config rc=%d\n", trust_rc, config_rc); cmd_res.msg = "reload package config success"; goto echo; #endif diff --git a/kernel/patch/common/user_event.c b/kernel/patch/common/user_event.c index 7fbcc5e9..5cae1cb0 100644 --- a/kernel/patch/common/user_event.c +++ b/kernel/patch/common/user_event.c @@ -15,10 +15,16 @@ int report_user_event(const char *event, const char *args) #ifdef ANDROID if (lib_strcmp(safe_event, "post-fs-data") == 0 && lib_strcmp(safe_args, "before") == 0) { - logki("post-fs-data before event received, loading ap package config ...\n"); + int trust_rc = refresh_trusted_manager_state(); + log_boot("post-fs-data before: trusted manager refresh rc=%d\n", trust_rc); + log_boot("post-fs-data before: loading ap package config ...\n"); load_ap_package_config(); } + if (lib_strcmp(safe_event, "boot-completed") == 0) { + int trust_rc = refresh_trusted_manager_state(); + log_boot("boot-completed: trusted manager refresh rc=%d\n", trust_rc); + } #endif logki("user report event: %s, args: %s\n", safe_event, safe_args); return 0; -} \ No newline at end of file +} diff --git a/kernel/patch/include/userd.h b/kernel/patch/include/userd.h index c9a4d85c..79ab70a3 100644 --- a/kernel/patch/include/userd.h +++ b/kernel/patch/include/userd.h @@ -6,6 +6,16 @@ #ifndef _KP_USERD_H_ #define _KP_USERD_H_ +#include + int load_ap_package_config(void); -#endif \ No newline at end of file +#ifdef ANDROID +int refresh_trusted_manager_uid(void); +int refresh_trusted_manager_state(void); +int is_trusted_manager_uid(uid_t uid); +uid_t get_trusted_manager_uid(void); + +#endif + +#endif diff --git a/kernel/patch/ksyms/misc.c b/kernel/patch/ksyms/misc.c index cc0a462d..20eeea72 100644 --- a/kernel/patch/ksyms/misc.c +++ b/kernel/patch/ksyms/misc.c @@ -450,6 +450,7 @@ void kfunc_def(putname)(struct filename *name) = 0; void kfunc_def(final_putname)(struct filename *name) = 0; loff_t kfunc_def(vfs_llseek)(struct file *file, loff_t offset, int whence) = 0; +int kfunc_def(iterate_dir)(struct file *, struct dir_context *) = 0; static void _linux_fs_sym_match(const char *name, unsigned long addr) { @@ -470,6 +471,7 @@ static void _linux_fs_sym_match(const char *name, unsigned long addr) // kfunc_match(putname, name, addr); // kfunc_match(final_putname, name, addr); kfunc_match(vfs_llseek, name, addr); + kfunc_match(iterate_dir, name, addr); } #include @@ -742,7 +744,7 @@ uint64_t kfunc_def(get_random_long)(void) = 0; static void _linux_misc_misc(const char *name, unsigned long addr) { kfunc_match(panic, name, addr); - // kfunc_match(call_usermodehelper, name, addr); + kfunc_match(call_usermodehelper, name, addr); // kfunc_match(get_random_bytes, name, addr); // kfunc_match(get_random_u64, name, addr); // kfunc_match(get_random_long, name, addr); diff --git a/tools/patch.c b/tools/patch.c index c072b446..eb6e1559 100644 --- a/tools/patch.c +++ b/tools/patch.c @@ -429,7 +429,7 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * int kver = 0; find_linux_banner(&kallsym, kallsym_kimg, pimg.ori_kimg_len, &kver); if (kver > 395008) { - if(!disable_pi_map(kernel_file.kimg, kernel_file.kimg_len)) //395008= (6<<16)+(7<<8) + if(disable_pi_map(kernel_file.kimg, kernel_file.kimg_len)) //395008= (6<<16)+(7<<8) { tools_logi("kernel have patched or not found\n"); }else{ From 09357d5dd178191347dc8e9286cc07cacea8bd21 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Wed, 15 Apr 2026 22:32:14 +0800 Subject: [PATCH 02/15] fix supercall --- kernel/patch/android/userd.c | 36 ++++++++++++++++------------------ kernel/patch/common/supercmd.c | 4 ++-- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index ca567de9..c4331e60 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -54,7 +54,8 @@ #define MAGISK_POLICY_PATH "/data/adb/ap/bin/magiskpolicy" #define AP_PACKAGE_CONFIG_PATH "/data/adb/ap/package_config" #define ANDROID_PACKAGES_LIST_PATH "/data/system/packages.list" -#define TRUSTED_MANAGER_PACKAGE "me.bmax.apatch" +#define TRUSTED_MANAGER_PACKAGE1 "me.bmax.apatch" +#define TRUSTED_MANAGER_PACKAGE2 "com.example.apatch" #define APK_SIG_BLOCK_MAGIC "APK Sig Block 42" #define APK_SIG_BLOCK_MAGIC_LEN 16 #define APK_SIG_SCHEME_V2_BLOCK_ID 0x7109871au @@ -65,13 +66,21 @@ #define TRUSTED_MANAGER_DIGEST_LEN SHA256_BLOCK_SIZE #define TRUSTED_MANAGER_UID_INVALID ((uid_t)-1) -static const uint8_t trusted_manager_signature_digest[TRUSTED_MANAGER_DIGEST_LEN] = { +#define TRUSTED_DIGEST trusted_manager_signature_digest1 +#define TRUSTED_MANAGER_PACKAGE_TARGET TRUSTED_MANAGER_PACKAGE1 + +static const uint8_t trusted_manager_signature_digest1[TRUSTED_MANAGER_DIGEST_LEN] = { 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 }; - +static const uint8_t trusted_manager_signature_digest2[TRUSTED_MANAGER_DIGEST_LEN] = { + 0xe5, 0x11, 0x33, 0x12, 0x5f, 0xef, 0x56, 0xaa, + 0x52, 0x83, 0x91, 0xfc, 0xc2, 0x04, 0x94, 0xeb, + 0xb5, 0x38, 0xbd, 0x8e, 0x09, 0x3d, 0x6c, 0x47, + 0x5d, 0x6d, 0x00, 0x2a, 0x7a, 0x12, 0x1a, 0x8f +}; static uid_t trusted_manager_uid = TRUSTED_MANAGER_UID_INVALID; @@ -177,19 +186,8 @@ static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_ int i; - log_boot("[TM] calc digest: "); - for (i = 0; i < TRUSTED_MANAGER_DIGEST_LEN; i++) { - log_boot("%02x", digest[i]); - } - log_boot("\n"); - - log_boot("[TM] expect digest: "); - for (i = 0; i < TRUSTED_MANAGER_DIGEST_LEN; i++) { - log_boot("%02x", trusted_manager_signature_digest[i]); - } - log_boot("\n"); - return lib_memcmp(digest, trusted_manager_signature_digest, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; + return lib_memcmp(digest, TRUSTED_DIGEST, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; } struct zip_entry_header @@ -497,7 +495,7 @@ static int lookup_package_list_uid(const char *package_name, uid_t *trusted_uid_ */ /* Inner callback: scan one directory for a subdir starting with - * TRUSTED_MANAGER_PACKAGE "-". + * TRUSTED_MANAGER_PACKAGE_TARGET "-". */ struct apk_inner_ctx { struct dir_context dctx; /* MUST be first member for safe cast */ @@ -511,7 +509,7 @@ static bool apk_inner_actor(struct dir_context *dctx, const char *name, int name loff_t offset, u64 ino, unsigned int d_type) { struct apk_inner_ctx *ctx = (struct apk_inner_ctx *)dctx; - static const char pkg_prefix[] = TRUSTED_MANAGER_PACKAGE "-"; + static const char pkg_prefix[] = TRUSTED_MANAGER_PACKAGE_TARGET "-"; static const char base_apk[] = "/base.apk"; const size_t prefix_len = sizeof(pkg_prefix) - 1; size_t outer_len, path_len; @@ -631,7 +629,7 @@ static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len) return 0; } - log_boot("trusted manager apk err: " TRUSTED_MANAGER_PACKAGE + log_boot("trusted manager apk err: " TRUSTED_MANAGER_PACKAGE_TARGET " not found in /data/app/ (rc=%d)\n", rc); return -ENOENT; } @@ -654,7 +652,7 @@ static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out return -EPERM; } - rc = lookup_package_list_uid(TRUSTED_MANAGER_PACKAGE, trusted_uid_out); + rc = lookup_package_list_uid(TRUSTED_MANAGER_PACKAGE_TARGET, trusted_uid_out); log_boot("trusted manager refresh: packages.list rc=%d uid=%u apk=%s\n", rc, rc ? 0 : *trusted_uid_out, apk_path); return rc; diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index 1c83663f..ba0f9b0d 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -344,10 +344,10 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) is_key_auth = 1; } else if (!strcmp("su", arg1)) { uid_t uid = current_uid(); - if (!is_su_allow_uid(uid)) return; + if (!is_su_allow_uid(uid) && !is_trusted_manager_uid(uid)) return; su_allow_uid_profile(0, uid, &profile); } else { - return; + if (!is_trusted_manager_uid(current_uid())) return; } #define SUPERCMD_ARGS_NO 16 From 8ff507afbec9e677e859ce03c961d341fcbcbac2 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Wed, 15 Apr 2026 22:36:19 +0800 Subject: [PATCH 03/15] signture for ap --- kernel/patch/android/userd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index c4331e60..a3b0ed0e 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -66,8 +66,8 @@ #define TRUSTED_MANAGER_DIGEST_LEN SHA256_BLOCK_SIZE #define TRUSTED_MANAGER_UID_INVALID ((uid_t)-1) -#define TRUSTED_DIGEST trusted_manager_signature_digest1 -#define TRUSTED_MANAGER_PACKAGE_TARGET TRUSTED_MANAGER_PACKAGE1 +#define TRUSTED_DIGEST trusted_manager_signature_digest2 +#define TRUSTED_MANAGER_PACKAGE_TARGET TRUSTED_MANAGER_PACKAGE2 static const uint8_t trusted_manager_signature_digest1[TRUSTED_MANAGER_DIGEST_LEN] = { 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, From 9b8aef70471ea4b416aad0367aed559ca4de9d58 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Wed, 15 Apr 2026 22:44:36 +0800 Subject: [PATCH 04/15] fix build --- kernel/patch/android/userd.c | 4 ++-- kernel/patch/common/supercall.c | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index a3b0ed0e..509f9e32 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -680,7 +680,7 @@ int refresh_trusted_manager_state(void) KP_EXPORT_SYMBOL(refresh_trusted_manager_uid); KP_EXPORT_SYMBOL(refresh_trusted_manager_state); -int is_trusted_manager_uid(uid_t uid) +int is_trusted_manager_uid_android(uid_t uid) { uid_t trusted_uid = trusted_manager_uid; if (trusted_uid == TRUSTED_MANAGER_UID_INVALID) { @@ -688,7 +688,7 @@ int is_trusted_manager_uid(uid_t uid) } return uid == trusted_uid; } -KP_EXPORT_SYMBOL(is_trusted_manager_uid); +KP_EXPORT_SYMBOL(is_trusted_manager_uid_android); uid_t get_trusted_manager_uid(void) { diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index 7deea1ab..afb6d078 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -378,12 +378,16 @@ static long supercall(int is_key_auth, long cmd, long arg1, long arg2, long arg3 return -ENOSYS; } -#ifndef ANDROID -static int is_trusted_manager_uid(uid_t uid) + +int is_trusted_manager_uid(uid_t uid) { + #ifdef ANDROID + return is_trusted_manager_uid_android(uid); + #endif return 1; } -#endif + + static void before(hook_fargs6_t *args, void *udata) { From bb13ccbbfdf996a77d761f375610a65921629085 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Wed, 15 Apr 2026 23:11:32 +0800 Subject: [PATCH 05/15] mulit manager verify --- kernel/patch/android/userd.c | 286 ++++++++++++++++++++--------------- 1 file changed, 161 insertions(+), 125 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 509f9e32..db8733eb 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -54,8 +54,6 @@ #define MAGISK_POLICY_PATH "/data/adb/ap/bin/magiskpolicy" #define AP_PACKAGE_CONFIG_PATH "/data/adb/ap/package_config" #define ANDROID_PACKAGES_LIST_PATH "/data/system/packages.list" -#define TRUSTED_MANAGER_PACKAGE1 "me.bmax.apatch" -#define TRUSTED_MANAGER_PACKAGE2 "com.example.apatch" #define APK_SIG_BLOCK_MAGIC "APK Sig Block 42" #define APK_SIG_BLOCK_MAGIC_LEN 16 #define APK_SIG_SCHEME_V2_BLOCK_ID 0x7109871au @@ -66,20 +64,31 @@ #define TRUSTED_MANAGER_DIGEST_LEN SHA256_BLOCK_SIZE #define TRUSTED_MANAGER_UID_INVALID ((uid_t)-1) -#define TRUSTED_DIGEST trusted_manager_signature_digest2 -#define TRUSTED_MANAGER_PACKAGE_TARGET TRUSTED_MANAGER_PACKAGE2 - -static const uint8_t trusted_manager_signature_digest1[TRUSTED_MANAGER_DIGEST_LEN] = { - 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, - 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, - 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, - 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 +struct trusted_manager_entry { + const char *package; + const uint8_t digest[TRUSTED_MANAGER_DIGEST_LEN]; }; -static const uint8_t trusted_manager_signature_digest2[TRUSTED_MANAGER_DIGEST_LEN] = { - 0xe5, 0x11, 0x33, 0x12, 0x5f, 0xef, 0x56, 0xaa, - 0x52, 0x83, 0x91, 0xfc, 0xc2, 0x04, 0x94, 0xeb, - 0xb5, 0x38, 0xbd, 0x8e, 0x09, 0x3d, 0x6c, 0x47, - 0x5d, 0x6d, 0x00, 0x2a, 0x7a, 0x12, 0x1a, 0x8f + +static const struct trusted_manager_entry trusted_managers[] = { + { + "me.bmax.apatch", + { + 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, + 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, + 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, + 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 + } + }, + { + "com.example.apatch", + { + 0xe5, 0x11, 0x33, 0x12, 0x5f, 0xef, 0x56, 0xaa, + 0x52, 0x83, 0x91, 0xfc, 0xc2, 0x04, 0x94, 0xeb, + 0xb5, 0x38, 0xbd, 0x8e, 0x09, 0x3d, 0x6c, 0x47, + 0x5d, 0x6d, 0x00, 0x2a, 0x7a, 0x12, 0x1a, 0x8f + } + }, + { NULL, { 0 } } }; static uid_t trusted_manager_uid = TRUSTED_MANAGER_UID_INVALID; @@ -174,9 +183,9 @@ static int skip_bytes(loff_t *pos, uint64_t len) return 0; } -static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_len) +static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_len, + const uint8_t *expected_digest) { - log_boot("[TM] ENTER cert match func\n"); uint8_t digest[SHA256_BLOCK_SIZE]; SHA256_CTX ctx; @@ -184,10 +193,7 @@ static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_ sha256_update(&ctx, cert_der, cert_len); sha256_final(&ctx, digest); - int i; - - - return lib_memcmp(digest, TRUSTED_DIGEST, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; + return lib_memcmp(digest, expected_digest, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; } struct zip_entry_header @@ -205,9 +211,10 @@ struct zip_entry_header uint16_t extra_field_length; } __attribute__((packed)); -static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4, loff_t *pos, uint32_t *offset) +static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4, loff_t *pos, + uint32_t *offset, const uint8_t *expected_digest) { - uint8_t *cert_buf; + uint8_t cert_buf[APK_CERT_MAX_LENGTH]; if (read_le32(fp, pos, size4)) return 0; // signer-sequence length if (read_le32(fp, pos, size4)) return 0; // signer length @@ -228,22 +235,15 @@ static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4 } *offset += *size4; - cert_buf = vmalloc(*size4); - if (!cert_buf) { - return 0; - } if (kernel_read(fp, cert_buf, *size4, pos) != *size4) { - kvfree(cert_buf); return 0; } - if (!cert_der_matches_trusted_digest(cert_buf, *size4)) { - kvfree(cert_buf); + if (!cert_der_matches_trusted_digest(cert_buf, *size4, expected_digest)) { return 2; } - kvfree(cert_buf); return 1; } @@ -279,7 +279,7 @@ static int apk_has_v1_signature_file(struct file *fp) return 0; } -static int apk_matches_trusted_signature(const char *path) +static int apk_matches_trusted_signature(const char *path, const uint8_t *expected_digest) { int i; int rc = 0; @@ -365,7 +365,7 @@ static int apk_matches_trusted_signature(const char *path) if (id == APK_SIG_SCHEME_V2_BLOCK_ID) { int match; v2_blocks++; - match = apk_sig_block_matches_trusted_digest(fp, &size4, &pos, &offset); + match = apk_sig_block_matches_trusted_digest(fp, &size4, &pos, &offset, expected_digest); if (match == 2) { v2_valid = 1; } @@ -404,82 +404,85 @@ static int apk_matches_trusted_signature(const char *path) return rc; } +/* + * Parse packages.list line by line without dynamic allocation. + * Format: packagename uid flags dataPath ... + * We read in 512-byte chunks and reassemble lines in a fixed stack buffer. + */ +#define PACKAGES_LIST_BUF_SIZE 512 +#define PACKAGES_LIST_LINE_MAX 512 + static int lookup_package_list_uid(const char *package_name, uid_t *trusted_uid_out) { - loff_t len = 0; - char *content = (char *)kernel_read_file(ANDROID_PACKAGES_LIST_PATH, &len); - char *cursor; - char *end; + struct file *fp; + char io_buf[PACKAGES_LIST_BUF_SIZE]; + char line_buf[PACKAGES_LIST_LINE_MAX]; + size_t line_len = 0; + int skip_line = 0; /* set when current line overflows line_buf */ + loff_t pos = 0; + ssize_t nread; + size_t pkg_len; + int rc = -ENOENT; - if (!trusted_uid_out) return -EINVAL; - if (!content || len <= 0) { - log_boot("trusted manager: failed to read %s\n", ANDROID_PACKAGES_LIST_PATH); + if (!trusted_uid_out || !package_name) return -EINVAL; + pkg_len = strlen(package_name); + + set_priv_sel_allow(current, true); + fp = filp_open(ANDROID_PACKAGES_LIST_PATH, O_RDONLY, 0); + if (!fp || IS_ERR(fp)) { + log_boot("trusted manager: failed to open %s\n", ANDROID_PACKAGES_LIST_PATH); + set_priv_sel_allow(current, false); return -ENOENT; } - cursor = content; - end = content + len; - while (cursor < end) { - char *line = cursor; - char *line_end = cursor; - char *pkg; - char *uid_str; - unsigned long long uid_raw = 0; - - while (line_end < end && *line_end != '\n' && *line_end != '\r') { - line_end++; - } - if (line_end < end) { - *line_end = '\0'; - cursor = line_end + 1; - } else { - cursor = end; - } - - while (*line && isspace(*line)) { - line++; - } - if (!*line) { - continue; - } - - pkg = line; - while (*line && !isspace(*line)) { - line++; - } - if (!*line) { - continue; - } - *line++ = '\0'; - - while (*line && isspace(*line)) { - line++; - } - if (!*line) { - continue; - } - - uid_str = line; - while (*line && !isspace(*line)) { - line++; - } - *line = '\0'; - - if (strcmp(pkg, package_name) != 0) { - continue; - } - if (kstrtoull(uid_str, 10, &uid_raw) || uid_raw > UINT_MAX) { - kvfree(content); - return -EINVAL; + while ((nread = kernel_read(fp, io_buf, sizeof(io_buf), &pos)) > 0) { + ssize_t i; + for (i = 0; i < nread; i++) { + char c = io_buf[i]; + if (c == '\n' || c == '\r') { + if (!skip_line && line_len > 0) { + /* Null-terminate and parse line */ + char *p; + char *uid_str; + unsigned long long uid_raw = 0; + + line_buf[line_len] = '\0'; + /* Check: line starts with "package_name " */ + if (line_len > pkg_len && + memcmp(line_buf, package_name, pkg_len) == 0 && + line_buf[pkg_len] == ' ') { + uid_str = line_buf + pkg_len + 1; + /* Skip leading spaces (shouldn't be any, but be safe) */ + while (*uid_str == ' ') uid_str++; + p = uid_str; + while (*p >= '0' && *p <= '9') { + uid_raw = uid_raw * 10u + (unsigned long long)(*p - '0'); + p++; + } + if (p > uid_str && uid_raw <= (unsigned long long)UINT_MAX) { + *trusted_uid_out = (uid_t)uid_raw; + rc = 0; + goto done; + } + } + } + line_len = 0; + skip_line = 0; + } else if (!skip_line) { + if (line_len < sizeof(line_buf) - 1) { + line_buf[line_len++] = c; + } else { + skip_line = 1; + line_len = 0; + } + } } - - *trusted_uid_out = (uid_t)uid_raw; - kvfree(content); - return 0; } - kvfree(content); - return -ENOENT; +done: + filp_close(fp, 0); + set_priv_sel_allow(current, false); + return rc; } /* @@ -503,21 +506,21 @@ struct apk_inner_ctx { char *result; size_t result_len; int found; + const char *pkg_prefix; /* e.g. "me.bmax.apatch-" */ + size_t pkg_prefix_len; }; static bool apk_inner_actor(struct dir_context *dctx, const char *name, int namelen, loff_t offset, u64 ino, unsigned int d_type) { struct apk_inner_ctx *ctx = (struct apk_inner_ctx *)dctx; - static const char pkg_prefix[] = TRUSTED_MANAGER_PACKAGE_TARGET "-"; static const char base_apk[] = "/base.apk"; - const size_t prefix_len = sizeof(pkg_prefix) - 1; size_t outer_len, path_len; if (ctx->found) return false; /* already done, stop iteration */ - if ((size_t)namelen < prefix_len) return true; - if (memcmp(name, pkg_prefix, prefix_len) != 0) return true; + if ((size_t)namelen < ctx->pkg_prefix_len) return true; + if (memcmp(name, ctx->pkg_prefix, ctx->pkg_prefix_len) != 0) return true; /* Construct: outer_dir + name + "/base.apk\0" */ outer_len = strlen(ctx->outer_dir); @@ -538,6 +541,8 @@ struct apk_outer_ctx { size_t result_len; int found; char inner_path[256]; /* "/data/app/~~/" */ + const char *pkg_prefix; + size_t pkg_prefix_len; }; static bool apk_outer_actor(struct dir_context *dctx, const char *name, int namelen, @@ -566,6 +571,8 @@ static bool apk_outer_actor(struct dir_context *dctx, const char *name, int name inner.result = ctx->result; inner.result_len = ctx->result_len; inner.found = 0; + inner.pkg_prefix = ctx->pkg_prefix; + inner.pkg_prefix_len = ctx->pkg_prefix_len; iterate_dir(inner_dir, &inner.dctx); filp_close(inner_dir, 0); @@ -577,16 +584,26 @@ static bool apk_outer_actor(struct dir_context *dctx, const char *name, int name return true; } -static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len) +static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len, const char *package) { struct apk_outer_ctx outer; struct apk_inner_ctx flat; struct file *app_dir; + char pkg_prefix_buf[128]; + size_t pkg_prefix_len; int rc; - if (!apk_path || apk_path_len == 0) return -EINVAL; + if (!apk_path || apk_path_len == 0 || !package) return -EINVAL; apk_path[0] = '\0'; + /* Build "package-" prefix on the stack — no dynamic allocation */ + pkg_prefix_len = strlen(package); + if (pkg_prefix_len + 2 > sizeof(pkg_prefix_buf)) return -EINVAL; + memcpy(pkg_prefix_buf, package, pkg_prefix_len); + pkg_prefix_buf[pkg_prefix_len] = '-'; + pkg_prefix_buf[pkg_prefix_len + 1] = '\0'; + pkg_prefix_len += 1; /* include the '-' */ + set_priv_sel_allow(current, true); app_dir = filp_open("/data/app/", O_RDONLY, 0); if (!app_dir || IS_ERR(app_dir)) { @@ -595,14 +612,15 @@ static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len) return -ENOENT; } - /* Pass 1: shallow scan for pre-Android-11 layout (me.bmax.apatch-N directly - * under /data/app/). Reuse apk_inner_actor with outer_dir="/data/app/". */ + /* Pass 1: shallow scan (pre-Android-11: package-N directly under /data/app/) */ flat.dctx.actor = apk_inner_actor; flat.dctx.pos = 0; flat.outer_dir = "/data/app/"; flat.result = apk_path; flat.result_len = apk_path_len; flat.found = 0; + flat.pkg_prefix = pkg_prefix_buf; + flat.pkg_prefix_len = pkg_prefix_len; iterate_dir(app_dir, &flat.dctx); if (flat.found) { @@ -612,13 +630,15 @@ static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len) return 0; } - /* Pass 2: two-level scan for Android 11+ scramble layout */ - vfs_llseek(app_dir, 0, SEEK_SET); /* rewind directory */ + /* Pass 2: two-level scan (Android 11+: /data/app/~~hash/package-hash/base.apk) */ + vfs_llseek(app_dir, 0, SEEK_SET); outer.dctx.actor = apk_outer_actor; outer.dctx.pos = 0; outer.result = apk_path; outer.result_len = apk_path_len; outer.found = 0; + outer.pkg_prefix = pkg_prefix_buf; + outer.pkg_prefix_len = pkg_prefix_len; rc = iterate_dir(app_dir, &outer.dctx); filp_close(app_dir, 0); @@ -629,33 +649,49 @@ static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len) return 0; } - log_boot("trusted manager apk err: " TRUSTED_MANAGER_PACKAGE_TARGET - " not found in /data/app/ (rc=%d)\n", rc); + log_boot("trusted manager apk err: %s not found in /data/app/ (rc=%d)\n", package, rc); return -ENOENT; } static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out) { char apk_path[PATH_MAX]; - int rc; + uid_t last_uid = TRUSTED_MANAGER_UID_INVALID; + int i, any_success = 0; if (!trusted_uid_out) return -EINVAL; - rc = find_trusted_manager_apk_path(apk_path, sizeof(apk_path)); - if (rc) { - log_boot("trusted manager refresh: no candidate apk rc=%d\n", rc); - return rc; - } + for (i = 0; trusted_managers[i].package != NULL; i++) { + uid_t uid; + int rc; + + apk_path[0] = '\0'; + rc = find_trusted_manager_apk_path(apk_path, sizeof(apk_path), trusted_managers[i].package); + if (rc) { + log_boot("trusted manager refresh: no apk for %s rc=%d\n", + trusted_managers[i].package, rc); + continue; + } - if (!apk_matches_trusted_signature(apk_path)) { - log_boot("trusted manager refresh: apk signature invalid apk=%s\n", apk_path); - return -EPERM; + if (!apk_matches_trusted_signature(apk_path, trusted_managers[i].digest)) { + log_boot("trusted manager refresh: signature mismatch apk=%s\n", apk_path); + continue; + } + + rc = lookup_package_list_uid(trusted_managers[i].package, &uid); + log_boot("trusted manager refresh: packages.list rc=%d uid=%u pkg=%s\n", + rc, rc ? 0u : (unsigned)uid, trusted_managers[i].package); + if (rc == 0) { + last_uid = uid; + any_success = 1; + } } - rc = lookup_package_list_uid(TRUSTED_MANAGER_PACKAGE_TARGET, trusted_uid_out); - log_boot("trusted manager refresh: packages.list rc=%d uid=%u apk=%s\n", - rc, rc ? 0 : *trusted_uid_out, apk_path); - return rc; + if (any_success) { + *trusted_uid_out = last_uid; + return 0; + } + return -ENOENT; } int refresh_trusted_manager_uid(void) From f36bcb8490584a1d6fb460f9ba7d06c4b866200a Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Wed, 15 Apr 2026 23:18:39 +0800 Subject: [PATCH 06/15] recover code --- kernel/patch/android/userd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index db8733eb..ba6f622a 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -1217,6 +1217,9 @@ static void after_openat(hook_fargs4_t *args, void *udata) sizeof(ORIGIN_RC_FILES[args->local.data3 - 1])); log_boot("restore rc file: %x\n", args->local.data0); } + if (args->local.data2) { + unhook_syscalln(__NR_openat, before_openat, after_openat); + } } #define EV_KEY 0x01 #define KEY_VOLUMEDOWN 114 From 45f74b3df41e4f95bc510c87fc9e755be7d8613d Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Thu, 16 Apr 2026 23:26:32 +0800 Subject: [PATCH 07/15] support no superkey --- tools/kptools.c | 1 + tools/patch.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/kptools.c b/tools/kptools.c index 2f0affbc..6a4071f9 100644 --- a/tools/kptools.c +++ b/tools/kptools.c @@ -203,6 +203,7 @@ int main(int argc, char *argv[]) else fprintf(stdout, "%x\n", version); } else if (cmd == 'p') { + if (!superkey) root_skey = true; ret = patch_update_img(kimg_path, kpimg_path, out_path, superkey, root_skey, additional, extra_configs, extra_config_num); } else if (cmd == 'd') { diff --git a/tools/patch.c b/tools/patch.c index eb6e1559..aecfcae9 100644 --- a/tools/patch.c +++ b/tools/patch.c @@ -407,7 +407,7 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * if (!kpimg_path) tools_loge_exit("empty kpimg\n"); if (!out_path) tools_loge_exit("empty out image path\n"); - if (!superkey) tools_loge_exit("empty superkey\n"); + if (!superkey && !root_key) tools_loge_exit("empty superkey\n"); patched_kimg_t pimg = { 0 }; kernel_file_t kernel_file; @@ -626,7 +626,7 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * if (!root_key) { tools_logi("superkey: %s\n", superkey); strncpy((char *)setup->superkey, superkey, SUPER_KEY_LEN - 1); - } else { + } else if (superkey && superkey[0] != '\0') { int len = SHA256_BLOCK_SIZE > ROOT_SUPER_KEY_HASH_LEN ? ROOT_SUPER_KEY_HASH_LEN : SHA256_BLOCK_SIZE; BYTE buf[SHA256_BLOCK_SIZE]; SHA256_CTX ctx; @@ -637,6 +637,9 @@ int patch_update_img(const char *kimg_path, const char *kpimg_path, const char * char *hexstr = bytes_to_hexstr(setup->root_superkey, len); tools_logi("root superkey hash: %s\n", hexstr); free(hexstr); + } else { + memset(setup->root_superkey, 0, ROOT_SUPER_KEY_HASH_LEN); + tools_logi("root_key mode with empty superkey: root_superkey zeroed\n"); } // modify kernel entry From 340d977f7436ac01752b48f55b34e26b881224b5 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Thu, 16 Apr 2026 23:30:15 +0800 Subject: [PATCH 08/15] Revert "mulit manager verify" This reverts commit bb13ccbbfdf996a77d761f375610a65921629085. --- kernel/patch/android/userd.c | 286 +++++++++++++++-------------------- 1 file changed, 125 insertions(+), 161 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index ba6f622a..e8f55c92 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -54,6 +54,8 @@ #define MAGISK_POLICY_PATH "/data/adb/ap/bin/magiskpolicy" #define AP_PACKAGE_CONFIG_PATH "/data/adb/ap/package_config" #define ANDROID_PACKAGES_LIST_PATH "/data/system/packages.list" +#define TRUSTED_MANAGER_PACKAGE1 "me.bmax.apatch" +#define TRUSTED_MANAGER_PACKAGE2 "com.example.apatch" #define APK_SIG_BLOCK_MAGIC "APK Sig Block 42" #define APK_SIG_BLOCK_MAGIC_LEN 16 #define APK_SIG_SCHEME_V2_BLOCK_ID 0x7109871au @@ -64,31 +66,20 @@ #define TRUSTED_MANAGER_DIGEST_LEN SHA256_BLOCK_SIZE #define TRUSTED_MANAGER_UID_INVALID ((uid_t)-1) -struct trusted_manager_entry { - const char *package; - const uint8_t digest[TRUSTED_MANAGER_DIGEST_LEN]; -}; +#define TRUSTED_DIGEST trusted_manager_signature_digest2 +#define TRUSTED_MANAGER_PACKAGE_TARGET TRUSTED_MANAGER_PACKAGE2 -static const struct trusted_manager_entry trusted_managers[] = { - { - "me.bmax.apatch", - { - 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, - 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, - 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, - 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 - } - }, - { - "com.example.apatch", - { - 0xe5, 0x11, 0x33, 0x12, 0x5f, 0xef, 0x56, 0xaa, - 0x52, 0x83, 0x91, 0xfc, 0xc2, 0x04, 0x94, 0xeb, - 0xb5, 0x38, 0xbd, 0x8e, 0x09, 0x3d, 0x6c, 0x47, - 0x5d, 0x6d, 0x00, 0x2a, 0x7a, 0x12, 0x1a, 0x8f - } - }, - { NULL, { 0 } } +static const uint8_t trusted_manager_signature_digest1[TRUSTED_MANAGER_DIGEST_LEN] = { + 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, + 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, + 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, + 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 +}; +static const uint8_t trusted_manager_signature_digest2[TRUSTED_MANAGER_DIGEST_LEN] = { + 0xe5, 0x11, 0x33, 0x12, 0x5f, 0xef, 0x56, 0xaa, + 0x52, 0x83, 0x91, 0xfc, 0xc2, 0x04, 0x94, 0xeb, + 0xb5, 0x38, 0xbd, 0x8e, 0x09, 0x3d, 0x6c, 0x47, + 0x5d, 0x6d, 0x00, 0x2a, 0x7a, 0x12, 0x1a, 0x8f }; static uid_t trusted_manager_uid = TRUSTED_MANAGER_UID_INVALID; @@ -183,9 +174,9 @@ static int skip_bytes(loff_t *pos, uint64_t len) return 0; } -static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_len, - const uint8_t *expected_digest) +static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_len) { + log_boot("[TM] ENTER cert match func\n"); uint8_t digest[SHA256_BLOCK_SIZE]; SHA256_CTX ctx; @@ -193,7 +184,10 @@ static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_ sha256_update(&ctx, cert_der, cert_len); sha256_final(&ctx, digest); - return lib_memcmp(digest, expected_digest, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; + int i; + + + return lib_memcmp(digest, TRUSTED_DIGEST, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; } struct zip_entry_header @@ -211,10 +205,9 @@ struct zip_entry_header uint16_t extra_field_length; } __attribute__((packed)); -static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4, loff_t *pos, - uint32_t *offset, const uint8_t *expected_digest) +static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4, loff_t *pos, uint32_t *offset) { - uint8_t cert_buf[APK_CERT_MAX_LENGTH]; + uint8_t *cert_buf; if (read_le32(fp, pos, size4)) return 0; // signer-sequence length if (read_le32(fp, pos, size4)) return 0; // signer length @@ -235,15 +228,22 @@ static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4 } *offset += *size4; + cert_buf = vmalloc(*size4); + if (!cert_buf) { + return 0; + } if (kernel_read(fp, cert_buf, *size4, pos) != *size4) { + kvfree(cert_buf); return 0; } - if (!cert_der_matches_trusted_digest(cert_buf, *size4, expected_digest)) { + if (!cert_der_matches_trusted_digest(cert_buf, *size4)) { + kvfree(cert_buf); return 2; } + kvfree(cert_buf); return 1; } @@ -279,7 +279,7 @@ static int apk_has_v1_signature_file(struct file *fp) return 0; } -static int apk_matches_trusted_signature(const char *path, const uint8_t *expected_digest) +static int apk_matches_trusted_signature(const char *path) { int i; int rc = 0; @@ -365,7 +365,7 @@ static int apk_matches_trusted_signature(const char *path, const uint8_t *expect if (id == APK_SIG_SCHEME_V2_BLOCK_ID) { int match; v2_blocks++; - match = apk_sig_block_matches_trusted_digest(fp, &size4, &pos, &offset, expected_digest); + match = apk_sig_block_matches_trusted_digest(fp, &size4, &pos, &offset); if (match == 2) { v2_valid = 1; } @@ -404,85 +404,82 @@ static int apk_matches_trusted_signature(const char *path, const uint8_t *expect return rc; } -/* - * Parse packages.list line by line without dynamic allocation. - * Format: packagename uid flags dataPath ... - * We read in 512-byte chunks and reassemble lines in a fixed stack buffer. - */ -#define PACKAGES_LIST_BUF_SIZE 512 -#define PACKAGES_LIST_LINE_MAX 512 - static int lookup_package_list_uid(const char *package_name, uid_t *trusted_uid_out) { - struct file *fp; - char io_buf[PACKAGES_LIST_BUF_SIZE]; - char line_buf[PACKAGES_LIST_LINE_MAX]; - size_t line_len = 0; - int skip_line = 0; /* set when current line overflows line_buf */ - loff_t pos = 0; - ssize_t nread; - size_t pkg_len; - int rc = -ENOENT; - - if (!trusted_uid_out || !package_name) return -EINVAL; - pkg_len = strlen(package_name); + loff_t len = 0; + char *content = (char *)kernel_read_file(ANDROID_PACKAGES_LIST_PATH, &len); + char *cursor; + char *end; - set_priv_sel_allow(current, true); - fp = filp_open(ANDROID_PACKAGES_LIST_PATH, O_RDONLY, 0); - if (!fp || IS_ERR(fp)) { - log_boot("trusted manager: failed to open %s\n", ANDROID_PACKAGES_LIST_PATH); - set_priv_sel_allow(current, false); + if (!trusted_uid_out) return -EINVAL; + if (!content || len <= 0) { + log_boot("trusted manager: failed to read %s\n", ANDROID_PACKAGES_LIST_PATH); return -ENOENT; } - while ((nread = kernel_read(fp, io_buf, sizeof(io_buf), &pos)) > 0) { - ssize_t i; - for (i = 0; i < nread; i++) { - char c = io_buf[i]; - if (c == '\n' || c == '\r') { - if (!skip_line && line_len > 0) { - /* Null-terminate and parse line */ - char *p; - char *uid_str; - unsigned long long uid_raw = 0; - - line_buf[line_len] = '\0'; - /* Check: line starts with "package_name " */ - if (line_len > pkg_len && - memcmp(line_buf, package_name, pkg_len) == 0 && - line_buf[pkg_len] == ' ') { - uid_str = line_buf + pkg_len + 1; - /* Skip leading spaces (shouldn't be any, but be safe) */ - while (*uid_str == ' ') uid_str++; - p = uid_str; - while (*p >= '0' && *p <= '9') { - uid_raw = uid_raw * 10u + (unsigned long long)(*p - '0'); - p++; - } - if (p > uid_str && uid_raw <= (unsigned long long)UINT_MAX) { - *trusted_uid_out = (uid_t)uid_raw; - rc = 0; - goto done; - } - } - } - line_len = 0; - skip_line = 0; - } else if (!skip_line) { - if (line_len < sizeof(line_buf) - 1) { - line_buf[line_len++] = c; - } else { - skip_line = 1; - line_len = 0; - } - } + cursor = content; + end = content + len; + while (cursor < end) { + char *line = cursor; + char *line_end = cursor; + char *pkg; + char *uid_str; + unsigned long long uid_raw = 0; + + while (line_end < end && *line_end != '\n' && *line_end != '\r') { + line_end++; + } + if (line_end < end) { + *line_end = '\0'; + cursor = line_end + 1; + } else { + cursor = end; + } + + while (*line && isspace(*line)) { + line++; + } + if (!*line) { + continue; + } + + pkg = line; + while (*line && !isspace(*line)) { + line++; + } + if (!*line) { + continue; + } + *line++ = '\0'; + + while (*line && isspace(*line)) { + line++; + } + if (!*line) { + continue; + } + + uid_str = line; + while (*line && !isspace(*line)) { + line++; } + *line = '\0'; + + if (strcmp(pkg, package_name) != 0) { + continue; + } + if (kstrtoull(uid_str, 10, &uid_raw) || uid_raw > UINT_MAX) { + kvfree(content); + return -EINVAL; + } + + *trusted_uid_out = (uid_t)uid_raw; + kvfree(content); + return 0; } -done: - filp_close(fp, 0); - set_priv_sel_allow(current, false); - return rc; + kvfree(content); + return -ENOENT; } /* @@ -506,21 +503,21 @@ struct apk_inner_ctx { char *result; size_t result_len; int found; - const char *pkg_prefix; /* e.g. "me.bmax.apatch-" */ - size_t pkg_prefix_len; }; static bool apk_inner_actor(struct dir_context *dctx, const char *name, int namelen, loff_t offset, u64 ino, unsigned int d_type) { struct apk_inner_ctx *ctx = (struct apk_inner_ctx *)dctx; + static const char pkg_prefix[] = TRUSTED_MANAGER_PACKAGE_TARGET "-"; static const char base_apk[] = "/base.apk"; + const size_t prefix_len = sizeof(pkg_prefix) - 1; size_t outer_len, path_len; if (ctx->found) return false; /* already done, stop iteration */ - if ((size_t)namelen < ctx->pkg_prefix_len) return true; - if (memcmp(name, ctx->pkg_prefix, ctx->pkg_prefix_len) != 0) return true; + if ((size_t)namelen < prefix_len) return true; + if (memcmp(name, pkg_prefix, prefix_len) != 0) return true; /* Construct: outer_dir + name + "/base.apk\0" */ outer_len = strlen(ctx->outer_dir); @@ -541,8 +538,6 @@ struct apk_outer_ctx { size_t result_len; int found; char inner_path[256]; /* "/data/app/~~/" */ - const char *pkg_prefix; - size_t pkg_prefix_len; }; static bool apk_outer_actor(struct dir_context *dctx, const char *name, int namelen, @@ -571,8 +566,6 @@ static bool apk_outer_actor(struct dir_context *dctx, const char *name, int name inner.result = ctx->result; inner.result_len = ctx->result_len; inner.found = 0; - inner.pkg_prefix = ctx->pkg_prefix; - inner.pkg_prefix_len = ctx->pkg_prefix_len; iterate_dir(inner_dir, &inner.dctx); filp_close(inner_dir, 0); @@ -584,26 +577,16 @@ static bool apk_outer_actor(struct dir_context *dctx, const char *name, int name return true; } -static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len, const char *package) +static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len) { struct apk_outer_ctx outer; struct apk_inner_ctx flat; struct file *app_dir; - char pkg_prefix_buf[128]; - size_t pkg_prefix_len; int rc; - if (!apk_path || apk_path_len == 0 || !package) return -EINVAL; + if (!apk_path || apk_path_len == 0) return -EINVAL; apk_path[0] = '\0'; - /* Build "package-" prefix on the stack — no dynamic allocation */ - pkg_prefix_len = strlen(package); - if (pkg_prefix_len + 2 > sizeof(pkg_prefix_buf)) return -EINVAL; - memcpy(pkg_prefix_buf, package, pkg_prefix_len); - pkg_prefix_buf[pkg_prefix_len] = '-'; - pkg_prefix_buf[pkg_prefix_len + 1] = '\0'; - pkg_prefix_len += 1; /* include the '-' */ - set_priv_sel_allow(current, true); app_dir = filp_open("/data/app/", O_RDONLY, 0); if (!app_dir || IS_ERR(app_dir)) { @@ -612,15 +595,14 @@ static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len, co return -ENOENT; } - /* Pass 1: shallow scan (pre-Android-11: package-N directly under /data/app/) */ + /* Pass 1: shallow scan for pre-Android-11 layout (me.bmax.apatch-N directly + * under /data/app/). Reuse apk_inner_actor with outer_dir="/data/app/". */ flat.dctx.actor = apk_inner_actor; flat.dctx.pos = 0; flat.outer_dir = "/data/app/"; flat.result = apk_path; flat.result_len = apk_path_len; flat.found = 0; - flat.pkg_prefix = pkg_prefix_buf; - flat.pkg_prefix_len = pkg_prefix_len; iterate_dir(app_dir, &flat.dctx); if (flat.found) { @@ -630,15 +612,13 @@ static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len, co return 0; } - /* Pass 2: two-level scan (Android 11+: /data/app/~~hash/package-hash/base.apk) */ - vfs_llseek(app_dir, 0, SEEK_SET); + /* Pass 2: two-level scan for Android 11+ scramble layout */ + vfs_llseek(app_dir, 0, SEEK_SET); /* rewind directory */ outer.dctx.actor = apk_outer_actor; outer.dctx.pos = 0; outer.result = apk_path; outer.result_len = apk_path_len; outer.found = 0; - outer.pkg_prefix = pkg_prefix_buf; - outer.pkg_prefix_len = pkg_prefix_len; rc = iterate_dir(app_dir, &outer.dctx); filp_close(app_dir, 0); @@ -649,49 +629,33 @@ static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len, co return 0; } - log_boot("trusted manager apk err: %s not found in /data/app/ (rc=%d)\n", package, rc); + log_boot("trusted manager apk err: " TRUSTED_MANAGER_PACKAGE_TARGET + " not found in /data/app/ (rc=%d)\n", rc); return -ENOENT; } static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out) { char apk_path[PATH_MAX]; - uid_t last_uid = TRUSTED_MANAGER_UID_INVALID; - int i, any_success = 0; + int rc; if (!trusted_uid_out) return -EINVAL; - for (i = 0; trusted_managers[i].package != NULL; i++) { - uid_t uid; - int rc; - - apk_path[0] = '\0'; - rc = find_trusted_manager_apk_path(apk_path, sizeof(apk_path), trusted_managers[i].package); - if (rc) { - log_boot("trusted manager refresh: no apk for %s rc=%d\n", - trusted_managers[i].package, rc); - continue; - } - - if (!apk_matches_trusted_signature(apk_path, trusted_managers[i].digest)) { - log_boot("trusted manager refresh: signature mismatch apk=%s\n", apk_path); - continue; - } - - rc = lookup_package_list_uid(trusted_managers[i].package, &uid); - log_boot("trusted manager refresh: packages.list rc=%d uid=%u pkg=%s\n", - rc, rc ? 0u : (unsigned)uid, trusted_managers[i].package); - if (rc == 0) { - last_uid = uid; - any_success = 1; - } + rc = find_trusted_manager_apk_path(apk_path, sizeof(apk_path)); + if (rc) { + log_boot("trusted manager refresh: no candidate apk rc=%d\n", rc); + return rc; } - if (any_success) { - *trusted_uid_out = last_uid; - return 0; + if (!apk_matches_trusted_signature(apk_path)) { + log_boot("trusted manager refresh: apk signature invalid apk=%s\n", apk_path); + return -EPERM; } - return -ENOENT; + + rc = lookup_package_list_uid(TRUSTED_MANAGER_PACKAGE_TARGET, trusted_uid_out); + log_boot("trusted manager refresh: packages.list rc=%d uid=%u apk=%s\n", + rc, rc ? 0 : *trusted_uid_out, apk_path); + return rc; } int refresh_trusted_manager_uid(void) From 82c22db03a5188a868ca2de48a0b454a7c395cd4 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Fri, 17 Apr 2026 20:38:44 +0800 Subject: [PATCH 09/15] mult set --- kernel/patch/android/userd.c | 357 ++++++++++++++++++++++++----------- 1 file changed, 250 insertions(+), 107 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index e8f55c92..383cfef0 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -54,8 +54,6 @@ #define MAGISK_POLICY_PATH "/data/adb/ap/bin/magiskpolicy" #define AP_PACKAGE_CONFIG_PATH "/data/adb/ap/package_config" #define ANDROID_PACKAGES_LIST_PATH "/data/system/packages.list" -#define TRUSTED_MANAGER_PACKAGE1 "me.bmax.apatch" -#define TRUSTED_MANAGER_PACKAGE2 "com.example.apatch" #define APK_SIG_BLOCK_MAGIC "APK Sig Block 42" #define APK_SIG_BLOCK_MAGIC_LEN 16 #define APK_SIG_SCHEME_V2_BLOCK_ID 0x7109871au @@ -66,23 +64,41 @@ #define TRUSTED_MANAGER_DIGEST_LEN SHA256_BLOCK_SIZE #define TRUSTED_MANAGER_UID_INVALID ((uid_t)-1) -#define TRUSTED_DIGEST trusted_manager_signature_digest2 -#define TRUSTED_MANAGER_PACKAGE_TARGET TRUSTED_MANAGER_PACKAGE2 - -static const uint8_t trusted_manager_signature_digest1[TRUSTED_MANAGER_DIGEST_LEN] = { +struct trusted_manager_entry { + const char *package; + const uint8_t digest[TRUSTED_MANAGER_DIGEST_LEN]; +}; +static const uint8_t digest_apatch_main[32] = { 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 }; -static const uint8_t trusted_manager_signature_digest2[TRUSTED_MANAGER_DIGEST_LEN] = { - 0xe5, 0x11, 0x33, 0x12, 0x5f, 0xef, 0x56, 0xaa, - 0x52, 0x83, 0x91, 0xfc, 0xc2, 0x04, 0x94, 0xeb, - 0xb5, 0x38, 0xbd, 0x8e, 0x09, 0x3d, 0x6c, 0x47, - 0x5d, 0x6d, 0x00, 0x2a, 0x7a, 0x12, 0x1a, 0x8f + +static const struct trusted_manager_entry trusted_managers[] = { + { + "me.bmax.apatch", + { + 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, + 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, + 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, + 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 + } + }, + { + "com.example.apatch", + { + 0xe5, 0x11, 0x33, 0x12, 0x5f, 0xef, 0x56, 0xaa, + 0x52, 0x83, 0x91, 0xfc, 0xc2, 0x04, 0x94, 0xeb, + 0xb5, 0x38, 0xbd, 0x8e, 0x09, 0x3d, 0x6c, 0x47, + 0x5d, 0x6d, 0x00, 0x2a, 0x7a, 0x12, 0x1a, 0x8f + } + }, + { NULL, { 0 } } }; -static uid_t trusted_manager_uid = TRUSTED_MANAGER_UID_INVALID; +static uid_t trusted_manager_uid = TRUSTED_MANAGER_UID_INVALID; +static int global_pkg_pos = 0; static const char ORIGIN_RC_FILES[][64] = { @@ -174,9 +190,8 @@ static int skip_bytes(loff_t *pos, uint64_t len) return 0; } -static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_len) +static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_len, const uint8_t *expected_digest) { - log_boot("[TM] ENTER cert match func\n"); uint8_t digest[SHA256_BLOCK_SIZE]; SHA256_CTX ctx; @@ -184,10 +199,9 @@ static int cert_der_matches_trusted_digest(const uint8_t *cert_der, size_t cert_ sha256_update(&ctx, cert_der, cert_len); sha256_final(&ctx, digest); - int i; - return lib_memcmp(digest, TRUSTED_DIGEST, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; + return lib_memcmp(digest, expected_digest, TRUSTED_MANAGER_DIGEST_LEN) == 0 ? 0 : -EPERM; } struct zip_entry_header @@ -205,7 +219,7 @@ struct zip_entry_header uint16_t extra_field_length; } __attribute__((packed)); -static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4, loff_t *pos, uint32_t *offset) +static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4, loff_t *pos, uint32_t *offset, const uint8_t *expected_digest) { uint8_t *cert_buf; @@ -238,7 +252,7 @@ static int apk_sig_block_matches_trusted_digest(struct file *fp, uint32_t *size4 return 0; } - if (!cert_der_matches_trusted_digest(cert_buf, *size4)) { + if (!cert_der_matches_trusted_digest(cert_buf, *size4, expected_digest)) { kvfree(cert_buf); return 2; } @@ -279,7 +293,7 @@ static int apk_has_v1_signature_file(struct file *fp) return 0; } -static int apk_matches_trusted_signature(const char *path) +static int apk_matches_trusted_signature(const char *path, const uint8_t *expected_digest) { int i; int rc = 0; @@ -365,7 +379,7 @@ static int apk_matches_trusted_signature(const char *path) if (id == APK_SIG_SCHEME_V2_BLOCK_ID) { int match; v2_blocks++; - match = apk_sig_block_matches_trusted_digest(fp, &size4, &pos, &offset); + match = apk_sig_block_matches_trusted_digest(fp, &size4, &pos, &offset, expected_digest); if (match == 2) { v2_valid = 1; } @@ -503,32 +517,56 @@ struct apk_inner_ctx { char *result; size_t result_len; int found; + const char *package; }; -static bool apk_inner_actor(struct dir_context *dctx, const char *name, int namelen, - loff_t offset, u64 ino, unsigned int d_type) +static bool apk_inner_actor(struct dir_context *dctx, + const char *name, int namelen, + loff_t offset, u64 ino, unsigned int d_type) { - struct apk_inner_ctx *ctx = (struct apk_inner_ctx *)dctx; - static const char pkg_prefix[] = TRUSTED_MANAGER_PACKAGE_TARGET "-"; + struct apk_inner_ctx *ctx = + container_of(dctx, struct apk_inner_ctx, dctx); + + const char *pkg; + size_t len, outer_len, path_len; static const char base_apk[] = "/base.apk"; - const size_t prefix_len = sizeof(pkg_prefix) - 1; - size_t outer_len, path_len; - if (ctx->found) return false; /* already done, stop iteration */ + if (!ctx || !ctx->result) + return false; + + if (ctx->found) + return false; + + pkg = ctx->package; + - if ((size_t)namelen < prefix_len) return true; - if (memcmp(name, pkg_prefix, prefix_len) != 0) return true; + if (!pkg || !pkg[0]) + return true; + + len = strnlen(pkg, 128); + + if ((size_t)namelen <= len) + return true; + + if (memcmp(name, pkg, len) != 0) + return true; + + if (name[len] != '-') + return true; - /* Construct: outer_dir + name + "/base.apk\0" */ outer_len = strlen(ctx->outer_dir); - path_len = outer_len + (size_t)namelen + sizeof(base_apk); - if (path_len > ctx->result_len) return true; /* won't fit, skip */ + path_len = outer_len + namelen + sizeof(base_apk); + + if (path_len >= ctx->result_len) + return true; memcpy(ctx->result, ctx->outer_dir, outer_len); - memcpy(ctx->result + outer_len, name, (size_t)namelen); - memcpy(ctx->result + outer_len + namelen, base_apk, sizeof(base_apk)); + memcpy(ctx->result + outer_len, name, namelen); + memcpy(ctx->result + outer_len + namelen, + base_apk, sizeof(base_apk)); + ctx->found = 1; - return false; /* stop */ + return false; } /* Outer callback: scan /data/app/ for ~~* scramble directories, then descend */ @@ -537,125 +575,230 @@ struct apk_outer_ctx { char *result; size_t result_len; int found; - char inner_path[256]; /* "/data/app/~~/" */ + char *inner_path; /* heap-allocated: "/data/app/~~/" */ + size_t inner_path_len; + const char *package; }; -static bool apk_outer_actor(struct dir_context *dctx, const char *name, int namelen, - loff_t offset, u64 ino, unsigned int d_type) +static bool apk_outer_actor(struct dir_context *dctx, + const char *name, int namelen, + loff_t offset, u64 ino, unsigned int d_type) { - struct apk_outer_ctx *ctx = (struct apk_outer_ctx *)dctx; - struct apk_inner_ctx inner; + struct apk_outer_ctx *ctx = container_of(dctx, struct apk_outer_ctx, dctx); + struct apk_inner_ctx *inner; struct file *inner_dir; int len; - if (ctx->found) return false; + if (!ctx) + return false; - /* Only descend into ~~* directories (Android 11+ scramble dirs) */ - if (namelen < 2 || name[0] != '~' || name[1] != '~') return true; + if (ctx->found) + return false; - len = snprintf(ctx->inner_path, sizeof(ctx->inner_path), + if (namelen < 2 || name[0] != '~' || name[1] != '~') + return true; + + len = snprintf(ctx->inner_path, ctx->inner_path_len, "/data/app/%.*s/", namelen, name); - if (len <= 0 || len >= (int)sizeof(ctx->inner_path)) return true; + + if (len <= 0 || len >= (int)ctx->inner_path_len) + return true; inner_dir = filp_open(ctx->inner_path, O_RDONLY, 0); - if (!inner_dir || IS_ERR(inner_dir)) return true; + if (IS_ERR(inner_dir)) + return true; - inner.dctx.actor = apk_inner_actor; - inner.dctx.pos = 0; - inner.outer_dir = ctx->inner_path; - inner.result = ctx->result; - inner.result_len = ctx->result_len; - inner.found = 0; + inner = vmalloc(sizeof(*inner)); + if (!inner) { + filp_close(inner_dir, 0); + return true; + } + memset(inner, 0, sizeof(*inner)); + + inner->dctx.actor = apk_inner_actor; + inner->dctx.pos = 0; + inner->outer_dir = ctx->inner_path; + inner->result = ctx->result; + inner->result_len = ctx->result_len; + inner->package = ctx->package; - iterate_dir(inner_dir, &inner.dctx); + iterate_dir(inner_dir, &inner->dctx); filp_close(inner_dir, 0); - if (inner.found) { + if (inner->found) { ctx->found = 1; + vfree(inner); return false; } + + vfree(inner); return true; } -static int find_trusted_manager_apk_path(char *apk_path, size_t apk_path_len) +static int find_trusted_manager_apk_path(char *apk_path, + size_t apk_path_len, + int index) { - struct apk_outer_ctx outer; - struct apk_inner_ctx flat; + + log_boot("finding apk path for package: %p\n", trusted_managers[index].package); + struct apk_outer_ctx *outer = NULL; + struct apk_inner_ctx *flat = NULL; struct file *app_dir; - int rc; + int rc = -ENOENT; + + char *pkg_buf = NULL; + + if (!apk_path || apk_path_len == 0) + return -EINVAL; + + if (index < 0) + return -EINVAL; + + if (!trusted_managers[index].package) + return -EINVAL; + + pkg_buf = vmalloc(64); + if (!pkg_buf) return -ENOMEM; + + size_t len = strnlen(trusted_managers[index].package, 63); + memcpy(pkg_buf, trusted_managers[index].package, len); + pkg_buf[len] = '\0'; - if (!apk_path || apk_path_len == 0) return -EINVAL; apk_path[0] = '\0'; + flat = vmalloc(sizeof(*flat)); + if (!flat) { rc = -ENOMEM; goto out_free; } + + outer = vmalloc(sizeof(*outer)); + if (!outer) { rc = -ENOMEM; goto out_free; } + + memset(flat, 0, sizeof(*flat)); + memset(outer, 0, sizeof(*outer)); + + outer->inner_path = vmalloc(256); + if (!outer->inner_path) { rc = -ENOMEM; goto out_free; } + outer->inner_path_len = 256; + set_priv_sel_allow(current, true); + app_dir = filp_open("/data/app/", O_RDONLY, 0); - if (!app_dir || IS_ERR(app_dir)) { - log_boot("trusted manager apk err: open /data/app/ rc=%ld\n", PTR_ERR(app_dir)); + if (IS_ERR(app_dir)) { + log_boot("open /data/app failed rc=%ld\n", PTR_ERR(app_dir)); set_priv_sel_allow(current, false); - return -ENOENT; + rc = -ENOENT; + goto out_free; } - /* Pass 1: shallow scan for pre-Android-11 layout (me.bmax.apatch-N directly - * under /data/app/). Reuse apk_inner_actor with outer_dir="/data/app/". */ - flat.dctx.actor = apk_inner_actor; - flat.dctx.pos = 0; - flat.outer_dir = "/data/app/"; - flat.result = apk_path; - flat.result_len = apk_path_len; - flat.found = 0; - iterate_dir(app_dir, &flat.dctx); - - if (flat.found) { - filp_close(app_dir, 0); - set_priv_sel_allow(current, false); - log_boot("trusted manager apk: candidate path=%s (flat)\n", apk_path); - return 0; + + /* ===== Pass1 ===== */ + flat->dctx.actor = apk_inner_actor; + flat->dctx.pos = 0; + flat->outer_dir = "/data/app/"; + flat->result = apk_path; + flat->result_len = apk_path_len; + flat->package = pkg_buf; + + iterate_dir(app_dir, &flat->dctx); + + if (flat->found) { + log_boot("apk found (flat): %s\n", apk_path); + rc = 0; + goto out; } - /* Pass 2: two-level scan for Android 11+ scramble layout */ - vfs_llseek(app_dir, 0, SEEK_SET); /* rewind directory */ - outer.dctx.actor = apk_outer_actor; - outer.dctx.pos = 0; - outer.result = apk_path; - outer.result_len = apk_path_len; - outer.found = 0; - rc = iterate_dir(app_dir, &outer.dctx); + /* ===== Pass2 ===== */ + vfs_llseek(app_dir, 0, SEEK_SET); - filp_close(app_dir, 0); - set_priv_sel_allow(current, false); + outer->dctx.actor = apk_outer_actor; + outer->dctx.pos = 0; + outer->result = apk_path; + outer->result_len = apk_path_len; + outer->package = pkg_buf; - if (outer.found) { - log_boot("trusted manager apk: candidate path=%s (scramble)\n", apk_path); - return 0; + iterate_dir(app_dir, &outer->dctx); + + if (outer->found) { + log_boot("apk found (scramble): %s\n", apk_path); + rc = 0; + goto out; } - log_boot("trusted manager apk err: " TRUSTED_MANAGER_PACKAGE_TARGET - " not found in /data/app/ (rc=%d)\n", rc); - return -ENOENT; + log_boot("apk not found: %s\n", pkg_buf); + +out: + filp_close(app_dir, 0); + set_priv_sel_allow(current, false); +out_free: + if (outer) { + if (outer->inner_path) vfree(outer->inner_path); + vfree(outer); + } + if (flat) vfree(flat); + if (pkg_buf) vfree(pkg_buf); + return rc; } + static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out) { - char apk_path[PATH_MAX]; - int rc; + uid_t last_uid = TRUSTED_MANAGER_UID_INVALID; + int i, any_success = 0; + + char *apk_path; - if (!trusted_uid_out) return -EINVAL; + if (!trusted_uid_out) + return -EINVAL; - rc = find_trusted_manager_apk_path(apk_path, sizeof(apk_path)); - if (rc) { - log_boot("trusted manager refresh: no candidate apk rc=%d\n", rc); - return rc; + apk_path = vmalloc(PATH_MAX); + if (!apk_path) { + log_boot("failed to allocate memory for apk_path\n"); + return -ENOMEM; + } + + for (i = 0; i<1; i++) { + int rc; + uid_t uid; + + rc = find_trusted_manager_apk_path( + apk_path, PATH_MAX, + i); + + if (rc) { + log_boot("no apk for %s rc=%d\n", + trusted_managers[i].package, rc); + continue; + } + + if (!apk_matches_trusted_signature( + apk_path, trusted_managers[i].digest)) { + log_boot("apk signature invalid: %s\n", apk_path); + continue; + } + + rc = lookup_package_list_uid( + trusted_managers[i].package, + &uid); + + if (rc == 0) { + last_uid = uid; + any_success = 1; + log_boot("uid ok pkg=%s uid=%u\n", + trusted_managers[i].package, uid); + } else { + log_boot("uid lookup fail pkg=%s rc=%d\n", + trusted_managers[i].package, rc); + } } - if (!apk_matches_trusted_signature(apk_path)) { - log_boot("trusted manager refresh: apk signature invalid apk=%s\n", apk_path); - return -EPERM; + vfree(apk_path); + + if (!any_success) { + log_boot("no valid trusted manager found\n"); + return -ENOENT; } - rc = lookup_package_list_uid(TRUSTED_MANAGER_PACKAGE_TARGET, trusted_uid_out); - log_boot("trusted manager refresh: packages.list rc=%d uid=%u apk=%s\n", - rc, rc ? 0 : *trusted_uid_out, apk_path); - return rc; + *trusted_uid_out = last_uid; + return 0; } int refresh_trusted_manager_uid(void) From 6ded922a94ede2a2c497246aec721a85745c2815 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Fri, 17 Apr 2026 20:46:07 +0800 Subject: [PATCH 10/15] re other key --- kernel/patch/android/userd.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 383cfef0..2be7355b 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -68,12 +68,6 @@ struct trusted_manager_entry { const char *package; const uint8_t digest[TRUSTED_MANAGER_DIGEST_LEN]; }; -static const uint8_t digest_apatch_main[32] = { - 0xd7, 0x1d, 0xad, 0xc0, 0xca, 0x07, 0xbd, 0xf5, - 0x94, 0x38, 0x3b, 0xfb, 0x2a, 0x44, 0x51, 0x34, - 0xa0, 0x73, 0x39, 0xf1, 0x2a, 0x27, 0x04, 0x4a, - 0x1b, 0x32, 0x69, 0x81, 0xac, 0xf5, 0xf3, 0x19 -}; static const struct trusted_manager_entry trusted_managers[] = { { From 26440dfcc8b7bd3cdb655f25b7f5e28a04ed4734 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Fri, 17 Apr 2026 21:22:14 +0800 Subject: [PATCH 11/15] fix structrue for mult manager --- kernel/patch/android/userd.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 2be7355b..4133bc2a 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -65,7 +65,7 @@ #define TRUSTED_MANAGER_UID_INVALID ((uid_t)-1) struct trusted_manager_entry { - const char *package; + const char package[64]; const uint8_t digest[TRUSTED_MANAGER_DIGEST_LEN]; }; @@ -88,7 +88,7 @@ static const struct trusted_manager_entry trusted_managers[] = { 0x5d, 0x6d, 0x00, 0x2a, 0x7a, 0x12, 0x1a, 0x8f } }, - { NULL, { 0 } } + { "", { 0 } } }; static uid_t trusted_manager_uid = TRUSTED_MANAGER_UID_INVALID; @@ -634,7 +634,7 @@ static int find_trusted_manager_apk_path(char *apk_path, int index) { - log_boot("finding apk path for package: %p\n", trusted_managers[index].package); + log_boot("finding apk path for package: %s\n", trusted_managers[index].package); struct apk_outer_ctx *outer = NULL; struct apk_inner_ctx *flat = NULL; struct file *app_dir; @@ -648,16 +648,13 @@ static int find_trusted_manager_apk_path(char *apk_path, if (index < 0) return -EINVAL; - if (!trusted_managers[index].package) + if (trusted_managers[index].package[0] == '\0') return -EINVAL; - pkg_buf = vmalloc(64); if (!pkg_buf) return -ENOMEM; - size_t len = strnlen(trusted_managers[index].package, 63); memcpy(pkg_buf, trusted_managers[index].package, len); pkg_buf[len] = '\0'; - apk_path[0] = '\0'; flat = vmalloc(sizeof(*flat)); @@ -683,7 +680,6 @@ static int find_trusted_manager_apk_path(char *apk_path, goto out_free; } - /* ===== Pass1 ===== */ flat->dctx.actor = apk_inner_actor; flat->dctx.pos = 0; @@ -749,14 +745,13 @@ static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out return -ENOMEM; } - for (i = 0; i<1; i++) { + for (i = 0; trusted_managers[i].package[0] != '\0'; i++) { int rc; uid_t uid; rc = find_trusted_manager_apk_path( apk_path, PATH_MAX, i); - if (rc) { log_boot("no apk for %s rc=%d\n", trusted_managers[i].package, rc); @@ -769,6 +764,7 @@ static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out continue; } + rc = lookup_package_list_uid( trusted_managers[i].package, &uid); From 2cef806baf84e3331f9aa9e6d7019f53020bc3d0 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Sat, 18 Apr 2026 02:05:02 +0800 Subject: [PATCH 12/15] add fallback method --- kernel/patch/android/userd.c | 92 ++++++++++++++++++++++++++++++++---- 1 file changed, 84 insertions(+), 8 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 4133bc2a..a7b7ba85 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -305,7 +305,7 @@ static int apk_matches_trusted_signature(const char *path, const uint8_t *expect if (!path || !path[0]) return 0; set_priv_sel_allow(current, true); - fp = filp_open(path, O_RDONLY, 0); + fp = filp_open(path, O_RDONLY | O_NOFOLLOW, 0); if (!fp || IS_ERR(fp)) { log_boot("trusted manager apk open failed: %s rc=%ld\n", path, PTR_ERR(fp)); set_priv_sel_allow(current, false); @@ -594,11 +594,10 @@ static bool apk_outer_actor(struct dir_context *dctx, len = snprintf(ctx->inner_path, ctx->inner_path_len, "/data/app/%.*s/", namelen, name); - if (len <= 0 || len >= (int)ctx->inner_path_len) return true; - inner_dir = filp_open(ctx->inner_path, O_RDONLY, 0); + inner_dir = filp_open(ctx->inner_path, O_RDONLY | O_NOFOLLOW, 0); if (IS_ERR(inner_dir)) return true; @@ -672,7 +671,8 @@ static int find_trusted_manager_apk_path(char *apk_path, set_priv_sel_allow(current, true); - app_dir = filp_open("/data/app/", O_RDONLY, 0); + app_dir = filp_open("/data/app/", O_RDONLY | O_NOFOLLOW, 0); + if (IS_ERR(app_dir)) { log_boot("open /data/app failed rc=%ld\n", PTR_ERR(app_dir)); set_priv_sel_allow(current, false); @@ -681,7 +681,8 @@ static int find_trusted_manager_apk_path(char *apk_path, } /* ===== Pass1 ===== */ - flat->dctx.actor = apk_inner_actor; + //flat->dctx.actor = apk_inner_actor; + flat->dctx.actor = apk_outer_actor; flat->dctx.pos = 0; flat->outer_dir = "/data/app/"; flat->result = apk_path; @@ -728,6 +729,71 @@ static int find_trusted_manager_apk_path(char *apk_path, return rc; } +static int find_apk_from_packages_xml(const char *pkg, + char *apk_path, + size_t apk_path_len) +{ + + loff_t len = 0; + char *data; + char *p; + int rc = -ENOENT; + + data = (char *)kernel_read_file("/data/system/packages.xml", &len); + if (!data || len <= 0) { + log_boot("read packages.xml failed\n"); + return -ENOENT; + } + + log_boot("packages.xml size: %lld bytes\n", len); + + p = data; + + while ((p = strstr(p, pkg))) { + char *start = p; + while (start > data && *start != '<') + start--; + + if (strncmp(start, "= apk_path_len) { + rc = -ENOSPC; + goto out; + } + + memcpy(apk_path, cp, l); + memcpy(apk_path + l, "/base.apk", strlen("/base.apk") + 1); + + log_boot("apk found (xml): %s\n", apk_path); + + rc = 0; + goto out; + } + + log_boot("apk not found in packages.xml for %s\n", pkg); + +out: + kvfree(data); + return rc; +} static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out) { @@ -753,9 +819,19 @@ static int refresh_trusted_manager_uid_from_packages_list(uid_t *trusted_uid_out apk_path, PATH_MAX, i); if (rc) { - log_boot("no apk for %s rc=%d\n", - trusted_managers[i].package, rc); - continue; + log_boot("no apk via iterate for %s rc=%d, fallback to xml\n", + trusted_managers[i].package, rc); + + rc = find_apk_from_packages_xml( + trusted_managers[i].package, + apk_path, + PATH_MAX); + + if (rc) { + log_boot("no apk for %s via xml rc=%d\n", + trusted_managers[i].package, rc); + continue; + } } if (!apk_matches_trusted_signature( From 70ab43563aacf1a09a53ae533686b47150ca7a1f Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Sat, 18 Apr 2026 02:22:44 +0800 Subject: [PATCH 13/15] fix some error --- kernel/patch/android/userd.c | 2 +- kernel/patch/common/supercall.c | 2 +- kernel/patch/include/userd.h | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index a7b7ba85..4bb5d996 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -887,7 +887,7 @@ int refresh_trusted_manager_state(void) return 0; } KP_EXPORT_SYMBOL(refresh_trusted_manager_uid); -KP_EXPORT_SYMBOL(refresh_trusted_manager_state); + int is_trusted_manager_uid_android(uid_t uid) { diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index afb6d078..da439d22 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -384,7 +384,7 @@ int is_trusted_manager_uid(uid_t uid) #ifdef ANDROID return is_trusted_manager_uid_android(uid); #endif - return 1; + return 0; } diff --git a/kernel/patch/include/userd.h b/kernel/patch/include/userd.h index 79ab70a3..a7bc4452 100644 --- a/kernel/patch/include/userd.h +++ b/kernel/patch/include/userd.h @@ -13,9 +13,10 @@ int load_ap_package_config(void); #ifdef ANDROID int refresh_trusted_manager_uid(void); int refresh_trusted_manager_state(void); -int is_trusted_manager_uid(uid_t uid); -uid_t get_trusted_manager_uid(void); +uid_t get_trusted_manager_uid(void); #endif +int is_trusted_manager_uid(uid_t uid); + #endif From ee34fa565dd1c3e5132771a8808a98dadf1cb932 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Sat, 18 Apr 2026 12:55:51 +0800 Subject: [PATCH 14/15] make manager as trust --- kernel/patch/common/supercall.c | 9 +++++++-- kernel/patch/common/supercmd.c | 10 +++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/kernel/patch/common/supercall.c b/kernel/patch/common/supercall.c index da439d22..a7d4e4f1 100644 --- a/kernel/patch/common/supercall.c +++ b/kernel/patch/common/supercall.c @@ -406,14 +406,19 @@ static void before(hook_fargs6_t *args, void *udata) if (len <= 0) return; int is_key_auth = 0; + int is_trusted_manager = 0; + is_trusted_manager = is_trusted_manager_uid(current_uid()); + if (is_trusted_manager) { + is_key_auth = 1; + } if (!auth_superkey(key)) { is_key_auth = 1; } else if (!strcmp("su", key)) { uid_t uid = current_uid(); - if (!is_su_allow_uid(uid) && !is_trusted_manager_uid(uid)) return; + if (!is_su_allow_uid(uid) && !is_trusted_manager) return; } else { - if (!is_trusted_manager_uid(current_uid())) return; + if (!is_trusted_manager) return; } long a1 = (long)syscall_argn(args, 2); diff --git a/kernel/patch/common/supercmd.c b/kernel/patch/common/supercmd.c index ba0f9b0d..9cceaddf 100644 --- a/kernel/patch/common/supercmd.c +++ b/kernel/patch/common/supercmd.c @@ -329,7 +329,11 @@ static void handle_cmd_key_auth(char **__user u_filename_p, const char *cmd, con void handle_supercmd(char **__user u_filename_p, char **__user uargv) { int is_key_auth = 0; - + int is_trusted_manager = 0; + is_trusted_manager = is_trusted_manager_uid(current_uid()); + if (is_trusted_manager) { + is_key_auth = 1; + } // key const char __user *p1 = get_user_arg_ptr(0, *uargv, 1); if (!p1 || IS_ERR(p1)) return; @@ -344,10 +348,10 @@ void handle_supercmd(char **__user u_filename_p, char **__user uargv) is_key_auth = 1; } else if (!strcmp("su", arg1)) { uid_t uid = current_uid(); - if (!is_su_allow_uid(uid) && !is_trusted_manager_uid(uid)) return; + if (!is_su_allow_uid(uid) && !is_trusted_manager) return; su_allow_uid_profile(0, uid, &profile); } else { - if (!is_trusted_manager_uid(current_uid())) return; + if (!is_trusted_manager) return; } #define SUPERCMD_ARGS_NO 16 From fae30f669292d849fcf83d68e75619a2d773dd36 Mon Sep 17 00:00:00 2001 From: Admirepowered Date: Sat, 18 Apr 2026 14:18:37 +0800 Subject: [PATCH 15/15] use define --- kernel/patch/android/userd.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/patch/android/userd.c b/kernel/patch/android/userd.c index 4bb5d996..c4a7c8a4 100644 --- a/kernel/patch/android/userd.c +++ b/kernel/patch/android/userd.c @@ -54,6 +54,7 @@ #define MAGISK_POLICY_PATH "/data/adb/ap/bin/magiskpolicy" #define AP_PACKAGE_CONFIG_PATH "/data/adb/ap/package_config" #define ANDROID_PACKAGES_LIST_PATH "/data/system/packages.list" +#define ANDROID_PACKAGES_XML_PATH "/data/system/packages.xml" #define APK_SIG_BLOCK_MAGIC "APK Sig Block 42" #define APK_SIG_BLOCK_MAGIC_LEN 16 #define APK_SIG_SCHEME_V2_BLOCK_ID 0x7109871au @@ -739,13 +740,13 @@ static int find_apk_from_packages_xml(const char *pkg, char *p; int rc = -ENOENT; - data = (char *)kernel_read_file("/data/system/packages.xml", &len); + data = (char *)kernel_read_file(ANDROID_PACKAGES_XML_PATH, &len); if (!data || len <= 0) { - log_boot("read packages.xml failed\n"); + log_boot("read %s failed\n", ANDROID_PACKAGES_XML_PATH); return -ENOENT; } - log_boot("packages.xml size: %lld bytes\n", len); + log_boot("%s size: %lld bytes\n", ANDROID_PACKAGES_XML_PATH, len); p = data; @@ -788,7 +789,7 @@ static int find_apk_from_packages_xml(const char *pkg, goto out; } - log_boot("apk not found in packages.xml for %s\n", pkg); + log_boot("apk not found in %s for %s\n", ANDROID_PACKAGES_XML_PATH, pkg); out: kvfree(data);