ANDROID: modpost: generate protected exports
These are symbols that unsigned modules may not export. * kernel/module/internal.h - declares protected exports * modpost generates protected-exports.c - defines protected exports Bug: 393366754 Change-Id: I3e6d630542875e35754126e64bc279313fc131b9 Signed-off-by: Sid Nayyar <sidnayyar@google.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <hashtable.h>
|
||||
#include <list.h>
|
||||
@@ -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<symbols_size; ++i) {
|
||||
buf_printf(&buf, "\t\"%s\",\n", symbols[i]);
|
||||
}
|
||||
buf_printf(&buf, "};\n");
|
||||
write_if_changed(&buf, ".vmlinux.protected-exports.c");
|
||||
free(buf.p);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct module *mod;
|
||||
char *missing_namespace_deps = NULL;
|
||||
char *unused_exports_white_list = NULL;
|
||||
char *protected_modules_list = NULL;
|
||||
char *dump_write = NULL, *files_source = NULL;
|
||||
int opt;
|
||||
LIST_HEAD(dump_lists);
|
||||
struct dump_list *dl, *dl2;
|
||||
|
||||
while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:v:xb")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "ei:MmnT:to:au:WwENd:v:xbp:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'e':
|
||||
external_module = true;
|
||||
@@ -2247,6 +2306,9 @@ int main(int argc, char **argv)
|
||||
case 'x':
|
||||
extended_modversions = true;
|
||||
break;
|
||||
case 'p':
|
||||
protected_modules_list = optarg;
|
||||
break;
|
||||
default:
|
||||
exit(1);
|
||||
}
|
||||
@@ -2300,5 +2362,10 @@ int main(int argc, char **argv)
|
||||
warn("suppressed %u unresolved symbol warnings because there were too many)\n",
|
||||
nr_unresolved - MAX_UNRESOLVED_REPORTS);
|
||||
|
||||
if (protected_modules_list) {
|
||||
handle_protected_modules_list(protected_modules_list);
|
||||
write_protected_exports_c_file();
|
||||
}
|
||||
|
||||
return error_occurred ? 1 : 0;
|
||||
}
|
||||
|
||||
@@ -89,6 +89,7 @@ struct module {
|
||||
bool seen;
|
||||
bool has_init;
|
||||
bool has_cleanup;
|
||||
bool is_protected; /* true if module exports are protected */
|
||||
struct buffer dev_table_buf;
|
||||
char srcversion[25];
|
||||
// Missing namespace dependencies
|
||||
|
||||
Reference in New Issue
Block a user