From 552a021d7dfdf4a12c3d2553b4da8919a2a29f3f 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 (cherry picked from commit fd1e768866606ff230280f26faca797bb47bd8c0) --- android/abi_gki_protected_exports | 0 kernel/module/Makefile | 10 ++++++++-- kernel/module/gki_module.c | 21 ++++++++++++++++++--- kernel/module/internal.h | 5 +++++ kernel/module/main.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/module/Makefile b/kernel/module/Makefile index 756419001b30..06201b9a0574 100644 --- a/kernel/module/Makefile +++ b/kernel/module/Makefile @@ -25,9 +25,15 @@ obj-$(CONFIG_MODULE_UNLOAD_TAINT_TRACKING) += tracking.o # ANDROID: GKI: Generate headerfile 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) + $(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/module/gki_module.c b/kernel/module/gki_module.c index f2367d77e3a2..fc2968c3791e 100644 --- a/kernel/module/gki_module.c +++ b/kernel/module/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 6f96a966f387..d51b047b4a54 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -306,9 +306,14 @@ static inline int same_magic(const char *amagic, const char *bmagic, bool has_cr #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 true; } +static inline bool gki_is_module_protected_export(const char *name) +{ + return false; +} #endif /* CONFIG_MODULE_SIG_PROTECT */ diff --git a/kernel/module/main.c b/kernel/module/main.c index 0087414df044..3aaa90ed7929 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1267,6 +1267,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 99f82bab8a02..4fe9d6faa19b 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