From f5794dc18420234c36aa0dc5a823958f2689d8d6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 28 Jun 2022 12:01:10 +0200 Subject: [PATCH] Revert "Revert "Revert "Revert "ANDROID: GKI: Add module load time protected symbol lookup"""" This reverts commit 090a1da69705ab33ae9a49214636e2176638bf7f. It brings it back now that we have merged around the problem area. Bug: 200082547 Bug: 214445388 Cc: Ramji Jiyani Signed-off-by: Greg Kroah-Hartman Change-Id: Iaa69221f341bf2face454ec0452efff2cbba9042 --- android/abi_gki_modules_exports | 1 + android/abi_gki_modules_protected | 1 + arch/arm64/configs/gki_defconfig | 2 ++ arch/x86/configs/gki_defconfig | 2 ++ init/Kconfig | 13 ++++++++ kernel/Makefile | 17 +++++++++++ kernel/gki_module.c | 50 +++++++++++++++++++++++++++++++ kernel/module/internal.h | 14 +++++++++ kernel/module/main.c | 17 +++++++++++ 9 files changed, 117 insertions(+) create mode 100644 android/abi_gki_modules_exports create mode 100644 android/abi_gki_modules_protected create mode 100644 kernel/gki_module.c diff --git a/android/abi_gki_modules_exports b/android/abi_gki_modules_exports new file mode 100644 index 000000000000..88b5a4b3adce --- /dev/null +++ b/android/abi_gki_modules_exports @@ -0,0 +1 @@ +[abi_symbol_list] diff --git a/android/abi_gki_modules_protected b/android/abi_gki_modules_protected new file mode 100644 index 000000000000..88b5a4b3adce --- /dev/null +++ b/android/abi_gki_modules_protected @@ -0,0 +1 @@ +[abi_symbol_list] diff --git a/arch/arm64/configs/gki_defconfig b/arch/arm64/configs/gki_defconfig index 3f6c4bfdc14e..8d23da6e3c27 100644 --- a/arch/arm64/configs/gki_defconfig +++ b/arch/arm64/configs/gki_defconfig @@ -85,6 +85,8 @@ CONFIG_SHADOW_CALL_STACK=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_PROTECT=y CONFIG_BLK_DEV_ZONED=y CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y diff --git a/arch/x86/configs/gki_defconfig b/arch/x86/configs/gki_defconfig index ff4e9c54c6e0..7b79035c7fe2 100644 --- a/arch/x86/configs/gki_defconfig +++ b/arch/x86/configs/gki_defconfig @@ -71,6 +71,8 @@ CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_MODULE_SIG=y +CONFIG_MODULE_SIG_PROTECT=y CONFIG_BLK_DEV_ZONED=y CONFIG_BLK_INLINE_ENCRYPTION=y CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK=y diff --git a/init/Kconfig b/init/Kconfig index c90b03159f2a..cfb5907670ea 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -2052,6 +2052,19 @@ config MODULE_SIG_FORCE Reject unsigned modules or signed modules for which we don't have a key. Without this, such modules will simply taint the kernel. +config MODULE_SIG_PROTECT + bool "Android GKI module protection" + depends on MODULE_SIG && !MODULE_SIG_FORCE + help + Enables Android GKI symbol and export protection support. + + This modifies the behavior of the MODULE_SIG_FORCE as follows: + - Allows Android GKI Modules signed using MODULE_SIG_ALL during build. + - Allows other modules to load if they don't violate the access to + Android GKI protected symbols and do not export the symbols already + exported by the Android GKI modules. Loading will fail and return + -EACCES (Permission denied) if symbol access contidions are not met. + config MODULE_SIG_ALL bool "Automatically sign all modules" default y diff --git a/kernel/Makefile b/kernel/Makefile index 318789c728d3..fe1b6341e0a4 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -67,6 +67,7 @@ obj-y += up.o endif obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signature.o +obj-$(CONFIG_MODULE_SIG_PROTECT) += gki_module.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_CRASH_CORE) += crash_core.o @@ -158,3 +159,19 @@ $(obj)/kheaders_data.tar.xz: FORCE $(call cmd,genikh) clean-files := kheaders_data.tar.xz kheaders.md5 + +# +# 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_protected.h $(obj)/gki_module_exported.h + +$(obj)/gki_module_protected.h: $(srctree)/android/abi_gki_modules_protected \ + $(srctree)/scripts/gen_gki_modules_headers.sh + $(Q)$(CONFIG_SHELL) $(srctree)/scripts/gen_gki_modules_headers.sh $@ \ + "$(srctree)" + +$(obj)/gki_module_exported.h: $(srctree)/android/abi_gki_modules_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 new file mode 100644 index 000000000000..24651dfc34f8 --- /dev/null +++ b/kernel/gki_module.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2021 Google LLC + * Author: ramjiyani@google.com (Ramji Jiyani) + */ + +#include +#include +#include +#include +#include + +/* + * Build time generated header files + * + * gki_module_exported.h -- Symbols protected from _export_ by unsigned modules + * gki_module_protected.h -- Symbols protected from _access_ by unsigned modules + */ +#include "gki_module_protected.h" +#include "gki_module_exported.h" + +#define MAX_STRCMP_LEN (max(MAX_PROTECTED_NAME_LEN, MAX_EXPORTED_NAME_LEN)) + +/* bsearch() comparision callback */ +static int cmp_name(const void *sym, const void *protected_sym) +{ + return strncmp(sym, protected_sym, MAX_STRCMP_LEN); +} + +/** + * gki_is_module_protected_symbol - Is a symbol protected from unsigned module? + * + * @name: Symbol being checked against protection from unsigned module + */ +bool gki_is_module_protected_symbol(const char *name) +{ + return bsearch(name, gki_protected_symbols, NO_OF_PROTECTED_SYMBOLS, + MAX_PROTECTED_NAME_LEN, cmp_name) != NULL; +} + +/** + * gki_is_module_exported_symbol - Is a symbol exported from a GKI module? + * + * @name: Symbol being checked against exported symbols from GKI modules + */ +bool gki_is_module_exported_symbol(const char *name) +{ + return bsearch(name, gki_exported_symbols, NO_OF_EXPORTED_SYMBOLS, + MAX_EXPORTED_NAME_LEN, cmp_name) != NULL; +} diff --git a/kernel/module/internal.h b/kernel/module/internal.h index bc5507ab8450..d0b7a8c2c968 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -300,3 +300,17 @@ static inline int same_magic(const char *amagic, const char *bmagic, bool has_cr return strcmp(amagic, bmagic) == 0; } #endif /* CONFIG_MODVERSIONS */ + +#ifdef CONFIG_MODULE_SIG_PROTECT +extern bool gki_is_module_exported_symbol(const char *name); +extern bool gki_is_module_protected_symbol(const char *name); +#else +static inline bool gki_is_module_exported_symbol(const char *name) +{ + return 0; +} +static inline bool gki_is_module_protected_symbol(const char *name) +{ + return 0; +} +#endif /* CONFIG_MODULE_SIG_PROTECT */ diff --git a/kernel/module/main.c b/kernel/module/main.c index fed58d30725d..ef2f76fa7849 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -1246,6 +1246,14 @@ static int verify_exported_symbols(struct module *mod) .name = kernel_symbol_name(s), .gplok = true, }; + + if (!mod->sig_ok && gki_is_module_exported_symbol( + kernel_symbol_name(s))) { + pr_err("%s: exporting 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", @@ -1313,6 +1321,13 @@ static int simplify_symbols(struct module *mod, const struct load_info *info) break; case SHN_UNDEF: + if (!mod->sig_ok && + gki_is_module_protected_symbol(name)) { + pr_err("%s: is not an Android GKI signed module. It can not access protected symbol: %s\n", + mod->name, name); + return -EACCES; + } + ksym = resolve_symbol_wait(mod, info, name); /* Ok if resolved. */ if (ksym && !IS_ERR(ksym)) { @@ -2728,6 +2743,8 @@ static int load_module(struct load_info *info, const char __user *uargs, "kernel\n", mod->name); add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK); } +#else + mod->sig_ok = 0; #endif /* To avoid stressing percpu allocator, do this once we're unique. */