From fd1e768866606ff230280f26faca797bb47bd8c0 Mon Sep 17 00:00:00 2001 From: Ramji Jiyani Date: Fri, 16 Dec 2022 06:32:13 +0000 Subject: [PATCH] ANDROID: GKI: Protect exports of protected GKI modules Implement support for protecting the exported symbols of protected GKI modules. Only signed GKI modules are permitted to export symbols listed in the android/abi_gki_protected_exports file. Attempting to export these symbols from an unsigned module will result in the module failing to load, with a 'Permission denied' error message. Bug: 232430739 Test: TH Change-Id: I3e8b330938e116bb2e022d356ac0d55108a84a01 Signed-off-by: Ramji Jiyani --- android/abi_gki_protected_exports | 0 kernel/Makefile | 10 ++++++++-- kernel/gki_module.c | 21 ++++++++++++++++++--- kernel/module-internal.h | 5 +++++ kernel/module.c | 8 ++++++++ scripts/gen_gki_modules_headers.sh | 23 +++++++++++++++-------- 6 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 android/abi_gki_protected_exports diff --git a/android/abi_gki_protected_exports b/android/abi_gki_protected_exports new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/kernel/Makefile b/kernel/Makefile index 3946218ab2f6..8c78b7e0d73f 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -160,12 +160,18 @@ $(obj)/kheaders_data.tar.xz: FORCE clean-files := kheaders_data.tar.xz kheaders.md5 # -# ANDROID: GKI: Generate headerfile required for gki_module.o +# ANDROID: GKI: Generate headerfiles required for gki_module.o # # Dependencies on generated files need to be listed explicitly -$(obj)/gki_module.o: $(obj)/gki_module_unprotected.h +$(obj)/gki_module.o: $(obj)/gki_module_protected_exports.h \ + $(obj)/gki_module_unprotected.h $(obj)/gki_module_unprotected.h: $(srctree)/scripts/gen_gki_modules_headers.sh \ $(if $(wildcard ${OUT_DIR}/abi_symbollist.raw), ${OUT_DIR}/abi_symbollist.raw) $(Q)$(CONFIG_SHELL) $(srctree)/scripts/gen_gki_modules_headers.sh $@ \ "$(srctree)" + +$(obj)/gki_module_protected_exports.h: $(srctree)/android/abi_gki_protected_exports \ + $(srctree)/scripts/gen_gki_modules_headers.sh + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/gen_gki_modules_headers.sh $@ \ + "$(srctree)" diff --git a/kernel/gki_module.c b/kernel/gki_module.c index f2367d77e3a2..fc2968c3791e 100644 --- a/kernel/gki_module.c +++ b/kernel/gki_module.c @@ -13,14 +13,29 @@ /* * Build time generated header files * + * gki_module_protected_exports.h -- Symbols protected from _export_ by unsigned modules * gki_module_unprotected.h -- Symbols allowed to _access_ by unsigned modules */ +#include "gki_module_protected_exports.h" #include "gki_module_unprotected.h" +#define MAX_STRCMP_LEN (max(MAX_UNPROTECTED_NAME_LEN, MAX_PROTECTED_EXPORTS_NAME_LEN)) + /* bsearch() comparision callback */ static int cmp_name(const void *sym, const void *protected_sym) { - return strncmp(sym, protected_sym, MAX_UNPROTECTED_NAME_LEN); + return strncmp(sym, protected_sym, MAX_STRCMP_LEN); +} + +/** + * gki_is_module_protected_export - Is a symbol exported from a protected GKI module? + * + * @name: Symbol being checked against exported symbols from protected GKI modules + */ +bool gki_is_module_protected_export(const char *name) +{ + return bsearch(name, gki_protected_exports_symbols, NR_PROTECTED_EXPORTS_SYMBOLS, + MAX_PROTECTED_EXPORTS_NAME_LEN, cmp_name) != NULL; } /** @@ -30,8 +45,8 @@ static int cmp_name(const void *sym, const void *protected_sym) */ bool gki_is_module_unprotected_symbol(const char *name) { - if (NO_OF_UNPROTECTED_SYMBOLS) { - return bsearch(name, gki_unprotected_symbols, NO_OF_UNPROTECTED_SYMBOLS, + if (NR_UNPROTECTED_SYMBOLS) { + return bsearch(name, gki_unprotected_symbols, NR_UNPROTECTED_SYMBOLS, MAX_UNPROTECTED_NAME_LEN, cmp_name) != NULL; } else { /* diff --git a/kernel/module-internal.h b/kernel/module-internal.h index 2a8e3a2062e8..321070747f88 100644 --- a/kernel/module-internal.h +++ b/kernel/module-internal.h @@ -32,9 +32,14 @@ extern int mod_verify_sig(const void *mod, struct load_info *info); #ifdef CONFIG_MODULE_SIG_PROTECT extern bool gki_is_module_unprotected_symbol(const char *name); +extern bool gki_is_module_protected_export(const char *name); #else static inline bool gki_is_module_unprotected_symbol(const char *name) { return 1; } +static inline bool gki_is_module_protected_export(const char *name) +{ + return 0; +} #endif /* CONFIG_MODULE_SIG_PROTECT */ diff --git a/kernel/module.c b/kernel/module.c index 1a08745b84c0..dbaa0093a7a5 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2282,6 +2282,14 @@ static int verify_exported_symbols(struct module *mod) .name = kernel_symbol_name(s), .gplok = true, }; + + if (!mod->sig_ok && gki_is_module_protected_export( + kernel_symbol_name(s))) { + pr_err("%s: exports protected symbol %s\n", + mod->name, kernel_symbol_name(s)); + return -EACCES; + } + if (find_symbol(&fsa)) { pr_err("%s: exports duplicate symbol %s" " (owned by %s)\n", diff --git a/scripts/gen_gki_modules_headers.sh b/scripts/gen_gki_modules_headers.sh index b9ab5dcc4c75..ae7dff17cfb1 100755 --- a/scripts/gen_gki_modules_headers.sh +++ b/scripts/gen_gki_modules_headers.sh @@ -49,11 +49,11 @@ generate_header() { # Find Maximum symbol name length if valid symbol_file exist if [ -s "${symbol_file}" ]; then - # Skip 1st line (symbol header), Trim white spaces & +1 for null termination + # Trim white spaces & +1 for null termination local max_name_len=$(awk ' { $1=$1; - if ( length > L && NR > 1) { + if ( length > L ) { L=length } } END { print ++L }' "${symbol_file}") @@ -67,11 +67,11 @@ generate_header() { /* * DO NOT EDIT * - * Build generated header file with unprotected symbols/exports + * Build generated header file with ${symbol_type} */ - #define NO_OF_$(printf ${symbol_type} | tr [:lower:] [:upper:])_SYMBOLS \\ - $(printf '\t')(sizeof(gki_${symbol_type}_symbols) / sizeof(gki_${symbol_type}_symbols[0])) + #define NR_$(printf ${symbol_type} | tr [:lower:] [:upper:])_SYMBOLS \\ + $(printf '\t')(ARRAY_SIZE(gki_${symbol_type}_symbols)) #define MAX_$(printf ${symbol_type} | tr [:lower:] [:upper:])_NAME_LEN (${max_name_len}) static const char gki_${symbol_type}_symbols[][MAX_$(printf ${symbol_type} | @@ -87,8 +87,15 @@ generate_header() { echo "};" >> "${header_file}" } -# Sorted list of vendor symbols -GKI_VENDOR_SYMBOLS="${OUT_DIR}/abi_symbollist.raw" +if [ "$(basename "${TARGET}")" = "gki_module_unprotected.h" ]; then + # Sorted list of vendor symbols + GKI_VENDOR_SYMBOLS="${OUT_DIR}/abi_symbollist.raw" -generate_header "${TARGET}" "${GKI_VENDOR_SYMBOLS}" "unprotected" + generate_header "${TARGET}" "${GKI_VENDOR_SYMBOLS}" "unprotected" +else + # Sorted list of exported symbols + GKI_EXPORTED_SYMBOLS="${SRCTREE}/android/abi_gki_protected_exports" + + generate_header "${TARGET}" "${GKI_EXPORTED_SYMBOLS}" "protected_exports" +fi