diff --git a/kernel/base/hook.c b/kernel/base/hook.c index 93cd538e..1701eb8c 100644 --- a/kernel/base/hook.c +++ b/kernel/base/hook.c @@ -58,18 +58,18 @@ typedef uint32_t inst_mask_t; #define MASK_HINT 0xFFFFF01F #define MASK_IGNORE 0x0 -static inst_mask_t masks[] = { +static const inst_mask_t masks[] = { MASK_B, MASK_BC, MASK_BL, MASK_ADR, MASK_ADRP, MASK_LDR_32, MASK_LDR_64, MASK_LDRSW_LIT, MASK_PRFM_LIT, MASK_LDR_SIMD_32, MASK_LDR_SIMD_64, MASK_LDR_SIMD_128, MASK_CBZ, MASK_CBNZ, MASK_TBZ, MASK_TBNZ, MASK_IGNORE, }; -static inst_type_t types[] = { +static const inst_type_t types[] = { INST_B, INST_BC, INST_BL, INST_ADR, INST_ADRP, INST_LDR_32, INST_LDR_64, INST_LDRSW_LIT, INST_PRFM_LIT, INST_LDR_SIMD_32, INST_LDR_SIMD_64, INST_LDR_SIMD_128, INST_CBZ, INST_CBNZ, INST_TBZ, INST_TBNZ, INST_IGNORE, }; -static int32_t relo_len[] = { 6, 8, 8, 4, 4, 6, 6, 6, 8, 8, 8, 8, 6, 6, 6, 6, 2 }; +static const int32_t relo_len[] = { 6, 8, 8, 4, 4, 6, 6, 6, 8, 8, 8, 8, 6, 6, 6, 6, 2 }; // static uint64_t sign_extend(uint64_t x, uint32_t len) // { diff --git a/kernel/include/preset.h b/kernel/include/preset.h index 6f9b601b..25fc9cd1 100644 --- a/kernel/include/preset.h +++ b/kernel/include/preset.h @@ -197,30 +197,6 @@ _Static_assert(sizeof(patch_extra_item_t) == PATCH_EXTRA_ITEM_LEN, "sizeof patch #ifndef __ASSEMBLY__ -// TODO: remove -typedef struct -{ - version_t kernel_version; - int32_t _; - int64_t kimg_size; // must aligned - int64_t kpimg_size; // must aligned - int64_t kernel_size; // must aligned - int64_t page_shift; - int64_t setup_offset; // must aligned - int64_t start_offset; // must aligned - int64_t extra_size; // must aligned - int64_t map_offset; // must aligned MAP_ALIGN - int64_t map_max_size; - int64_t kallsyms_lookup_name_offset; - int64_t paging_init_offset; - int64_t printk_offset; - map_symbol_t map_symbol; - uint8_t header_backup[HDR_BACKUP_SIZE]; - uint8_t superkey[SUPER_KEY_LEN]; - patch_config_t patch_config; - char additional[ADDITIONAL_LEN]; -} setup_preset_be_000a04_t; - typedef struct _setup_preset_t { version_t kernel_version; @@ -275,4 +251,4 @@ typedef struct } preset_t; #endif -#endif // _KP_PRESET_H_ \ No newline at end of file +#endif // _KP_PRESET_H_ diff --git a/tools/kallsym.c b/tools/kallsym.c index cb5b579e..4fdc2e02 100644 --- a/tools/kallsym.c +++ b/tools/kallsym.c @@ -39,6 +39,21 @@ static void *memmem(const void *haystack, size_t haystack_len, const void *const } #endif +static void record_linux_banner_offset(kallsym_t *info, int32_t offset) +{ + const int32_t max = (int32_t)ARRAY_SIZE(info->linux_banner_offset); + + if (info->banner_num < max) { + info->linux_banner_offset[info->banner_num++] = offset; + return; + } + + for (int32_t i = 1; i < max; i++) { + info->linux_banner_offset[i - 1] = info->linux_banner_offset[i]; + } + info->linux_banner_offset[max - 1] = offset; +} + static int find_linux_banner(kallsym_t *info, char *img, int32_t imglen) { /* @@ -59,12 +74,18 @@ static int find_linux_banner(kallsym_t *info, char *img, int32_t imglen) char *banner = (char *)img; info->banner_num = 0; while ((banner = (char *)memmem(banner + 1, imgend - banner - 1, linux_banner_prefix, prefix_len)) != NULL) { - if (isdigit(*(banner + prefix_len)) && *(banner + prefix_len + 1) == '.') { - info->linux_banner_offset[info->banner_num++] = (int32_t)(banner - img); + size_t remaining = (size_t)(imgend - banner); + if (remaining <= prefix_len + 1) continue; + if (isdigit((unsigned char)banner[prefix_len]) && banner[prefix_len + 1] == '.') { + record_linux_banner_offset(info, (int32_t)(banner - img)); tools_logi("linux_banner %d: %s", info->banner_num, banner); tools_logi("linux_banner offset: 0x%lx\n", banner - img); } } + if (info->banner_num <= 0) { + tools_loge("can't find linux banner\n"); + return -1; + } banner = img + info->linux_banner_offset[info->banner_num - 1]; char *uts_release_start = banner + prefix_len; @@ -94,10 +115,13 @@ int kernel_if_need_patch(kallsym_t *info, char *img, int32_t imglen) char *banner = (char *)img; info->banner_num = 0; while ((banner = (char *)memmem(banner + 1, imgend - banner - 1, linux_banner_prefix, prefix_len)) != NULL) { - if (isdigit(*(banner + prefix_len)) && *(banner + prefix_len + 1) == '.') { - info->linux_banner_offset[info->banner_num++] = (int32_t)(banner - img); + size_t remaining = (size_t)(imgend - banner); + if (remaining <= prefix_len + 1) continue; + if (isdigit((unsigned char)banner[prefix_len]) && banner[prefix_len + 1] == '.') { + record_linux_banner_offset(info, (int32_t)(banner - img)); } } + if (info->banner_num <= 0) tools_loge_exit("can't find linux banner\n"); banner = img + info->linux_banner_offset[info->banner_num - 1]; char *uts_release_start = banner + prefix_len; diff --git a/tools/patch.c b/tools/patch.c index 245c5092..520cae93 100644 --- a/tools/patch.c +++ b/tools/patch.c @@ -81,9 +81,13 @@ uint32_t get_kpimg_version(const char *kpimg_path) int kpimg_len = 0; read_file(kpimg_path, &kpimg, &kpimg_len); preset_t *preset = get_preset(kpimg, kpimg_len); - if (!preset) tools_loge_exit("not patched kernel image\n"); + if (!preset) { + free(kpimg); + tools_loge_exit("not patched kernel image\n"); + } version_t ver = preset->header.kp_version; uint32_t version = (ver.major << 16) + (ver.minor << 8) + ver.patch; + free(kpimg); return version; } @@ -125,11 +129,16 @@ const char *extra_type_str(extra_item_type extra_type) static char *bytes_to_hexstr(const unsigned char *data, int len) { - char *buf = (char *)malloc(2 * len + 1); - buf[2 * len] = '\0'; + enum { HEX_CHARS_PER_BYTE = 2 }; + static const char hex_digits[] = "0123456789abcdef"; + + char *buf = (char *)malloc((size_t)len * HEX_CHARS_PER_BYTE + 1); for (int i = 0; i < len; i++) { - sprintf(&buf[2 * i], "%02x", data[i]); + unsigned char byte = data[i]; + buf[i * HEX_CHARS_PER_BYTE] = hex_digits[byte >> 4]; + buf[i * HEX_CHARS_PER_BYTE + 1] = hex_digits[byte & 0x0F]; } + buf[len * HEX_CHARS_PER_BYTE] = '\0'; return buf; } @@ -148,19 +157,12 @@ void print_preset_info(preset_t *preset) fprintf(stdout, "config=%s,%s\n", is_android ? "android" : "linux", is_debug ? "debug" : "release"); fprintf(stdout, "superkey=%s\n", setup->superkey); - // todo: remove compat version - if (ver_num > 0xa04) { - char *hexstr = bytes_to_hexstr(setup->root_superkey, ROOT_SUPER_KEY_HASH_LEN); - fprintf(stdout, "root_superkey=%s\n", hexstr); - free(hexstr); - } + char *hexstr = bytes_to_hexstr(setup->root_superkey, ROOT_SUPER_KEY_HASH_LEN); + fprintf(stdout, "root_superkey=%s\n", hexstr); + free(hexstr); fprintf(stdout, INFO_ADDITIONAL_SESSION "\n"); char *addition = setup->additional; - // todo: remove compat version - if (ver_num <= 0xa04) { - addition -= (ROOT_SUPER_KEY_HASH_LEN + SETUP_PRESERVE_LEN); - } char *pos = addition; while (pos < addition + ADDITIONAL_LEN) { int len = *pos; @@ -177,7 +179,7 @@ void print_preset_info(preset_t *preset) int print_kp_image_info_path(const char *kpimg_path) { int rc = 0; - char *kpimg; + char *kpimg = NULL; int len = 0; read_file(kpimg_path, &kpimg, &len); preset_t *preset = (preset_t *)kpimg; @@ -186,8 +188,8 @@ int print_kp_image_info_path(const char *kpimg_path) } else { print_preset_info(preset); fprintf(stdout, "\n"); - free(kpimg); } + free(kpimg); return rc; } @@ -204,12 +206,18 @@ int parse_image_patch_info(const char *kimg, int kimg_len, patched_kimg_t *pimg) char linux_banner_prefix[] = "Linux version "; size_t prefix_len = strlen(linux_banner_prefix); const char *imgend = pimg->kimg + pimg->kimg_len; - const char *banner = (char *)pimg->kimg; - while ((banner = (char *)memmem(banner + 1, imgend - banner, linux_banner_prefix, prefix_len)) != NULL) { - if (isdigit(*(banner + prefix_len)) && *(banner + prefix_len + 1) == '.') { + const char *search = pimg->kimg; + if (search < imgend) search++; + while (search < imgend) { + size_t search_len = (size_t)(imgend - search); + const char *banner = (const char *)memmem(search, search_len, linux_banner_prefix, prefix_len); + if (!banner) break; + size_t remaining = (size_t)(imgend - banner); + if (remaining > prefix_len + 1 && isdigit((unsigned char)banner[prefix_len]) && banner[prefix_len + 1] == '.') { pimg->banner = banner; break; } + search = banner + 1; } if (!pimg->banner) tools_loge_exit("can't find linux banner\n"); @@ -771,4 +779,4 @@ int dump_ikconfig(const char *kimg_path) set_log_enable(false); free_kernel_file(&kernel_file); return 0; -} \ No newline at end of file +}