diff --git a/kernel/module/internal.h b/kernel/module/internal.h index 887838589020..0f58ceac655d 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -420,3 +420,11 @@ 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 const char *const protected_symbol_exports[]; +extern size_t protected_symbol_exports_count; +#else +#define protected_symbol_exports NULL +#define protected_symbol_exports_count 0UL +#endif diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 555828fe7395..931e72ab75fb 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,8 @@ static bool extra_warn; bool target_is_big_endian; bool host_is_big_endian; +static unsigned int nr_module_exported_symbols; + /* * Cut off the warnings when there are too many. This typically occurs when * vmlinux is missing. ('make modules' without building vmlinux.) @@ -99,6 +102,11 @@ static inline bool strends(const char *str, const char *postfix) return strcmp(str + strlen(str) - strlen(postfix), postfix) == 0; } +static int symbol_cmp(const void *a, const void *b) +{ + return strcmp(*(const char **)a, *(const char **)b); +} + char *read_text_file(const char *filename) { struct stat st; @@ -365,6 +373,9 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, s->namespace = xstrdup(namespace); list_add_tail(&s->list, &mod->exported_symbols); hash_add_symbol(s); + if (!mod->is_vmlinux && !mod->from_dump) { + ++nr_module_exported_symbols; + } return s; } @@ -2179,17 +2190,65 @@ static void check_host_endian(void) } } +static void handle_protected_modules_list(const char *fname) +{ + char *buf, *p, *name; + + buf = read_text_file(fname); + p = buf; + + while ((name = strsep(&p, "\n"))) { + struct module *mod = find_module(name); + + if (mod) + mod->is_protected = true; + } + + free(buf); +} + +static void write_protected_exports_c_file(void) +{ + const char* symbols[nr_module_exported_symbols]; + unsigned int symbols_size = 0; + unsigned int i; + struct module *mod; + struct symbol *sym; + struct buffer buf = {}; + + list_for_each_entry(mod, &modules, list) { + if (mod->is_vmlinux || mod->from_dump || !mod->is_protected) + continue; + + list_for_each_entry(sym, &mod->exported_symbols, list) { + symbols[symbols_size++] = sym->name; + } + } + qsort(symbols, symbols_size, sizeof(const char*), symbol_cmp); + + buf_printf(&buf, "#include \"../kernel/module/internal.h\"\n\n"); + buf_printf(&buf, "size_t protected_symbol_exports_count = %d;\n\n", symbols_size); + buf_printf(&buf, "const char *const protected_symbol_exports[] = {\n"); + for (i=0; i