ANDROID: enforce symbol export protection

The module loader will check each unsigned module's exported symbols
against the generated list of protected exports. If a match is found,
the module will be rejected and fail to load.

Bug: 393366754
Change-Id: I2157e193042d30880ca603802f3d79daf7498308
Signed-off-by: Sid Nayyar <sidnayyar@google.com>
This commit is contained in:
Sid Nayyar
2025-01-31 02:24:14 -08:00
parent a16ea85f69
commit cf33526ab7
+27
View File
@@ -90,6 +90,13 @@ struct symsearch {
enum mod_license license; enum mod_license license;
}; };
#ifdef CONFIG_MODULE_SIG_PROTECT
static int cmp_string(const void *a, const void *b)
{
return strcmp((const char *)a, *(const char **)b);
}
#endif
/* /*
* Bounds of module memory, for speeding up __module_address. * Bounds of module memory, for speeding up __module_address.
* Protected by module_mutex. * Protected by module_mutex.
@@ -1360,6 +1367,15 @@ fail:
} }
EXPORT_SYMBOL_GPL(__symbol_get); EXPORT_SYMBOL_GPL(__symbol_get);
#ifdef CONFIG_MODULE_SIG_PROTECT
static bool is_protected_symbol_export(const char *name)
{
return bsearch(name, protected_symbol_exports,
protected_symbol_exports_count,
sizeof(const char *), cmp_string) != NULL;
}
#endif
/* /*
* Ensure that an exported symbol [global namespace] does not already exist * Ensure that an exported symbol [global namespace] does not already exist
* in the kernel or in some other module's exported symbol table. * in the kernel or in some other module's exported symbol table.
@@ -1391,6 +1407,13 @@ static int verify_exported_symbols(struct module *mod)
module_name(fsa.owner)); module_name(fsa.owner));
return -ENOEXEC; return -ENOEXEC;
} }
#ifdef CONFIG_MODULE_SIG_PROTECT
if (!mod->sig_ok && is_protected_symbol_export(kernel_symbol_name(s))) {
pr_err("%s: exports protected symbol %s\n",
mod->name, kernel_symbol_name(s));
return -EACCES;
}
#endif
} }
} }
return 0; return 0;
@@ -2416,6 +2439,7 @@ static void module_augment_kernel_taints(struct module *mod, struct load_info *i
} }
#ifdef CONFIG_MODULE_SIG #ifdef CONFIG_MODULE_SIG
mod->sig_ok = info->sig_ok; mod->sig_ok = info->sig_ok;
#ifndef CONFIG_MODULE_SIG_PROTECT
if (!mod->sig_ok) { if (!mod->sig_ok) {
pr_notice_once("%s: module verification failed: signature " pr_notice_once("%s: module verification failed: signature "
"and/or required key missing - tainting " "and/or required key missing - tainting "
@@ -2423,6 +2447,9 @@ static void module_augment_kernel_taints(struct module *mod, struct load_info *i
add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK); add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK);
} }
#endif #endif
#else
mod->sig_ok = 0;
#endif
/* /*
* ndiswrapper is under GPL by itself, but loads proprietary modules. * ndiswrapper is under GPL by itself, but loads proprietary modules.