ANDROID: enforce symbol import protection

The module loader will check each unsigned module's imported symbols
against the generated list of permitted imports. If any lookup fails,
the module will be rejected and fail to load.

Bug: 393366754
Change-Id: Ifd4d242135eaba1f215f982c5d6e8a76b1fc8522
Signed-off-by: Sid Nayyar <sidnayyar@google.com>
This commit is contained in:
Sid Nayyar
2025-04-30 13:50:17 +00:00
parent 9593e47f47
commit a3fde76f1e

View File

@@ -90,7 +90,7 @@ struct symsearch {
enum mod_license license;
};
#ifdef CONFIG_MODULE_SIG_PROTECT
#if defined(CONFIG_MODULE_SIG_PROTECT) || defined(CONFIG_TRIM_UNUSED_KSYMS)
static int cmp_string(const void *a, const void *b)
{
return strcmp((const char *)a, *(const char **)b);
@@ -1148,12 +1148,25 @@ static bool inherit_taint(struct module *mod, struct module *owner, const char *
return true;
}
#ifdef CONFIG_TRIM_UNUSED_KSYMS
static bool is_permitted_symbol_import(const char *name)
{
return bsearch(name, permitted_symbol_imports,
permitted_symbol_imports_count,
sizeof(const char *), cmp_string) != NULL;
}
#endif
/* Resolve a symbol for this module. I.e. if we find one, record usage. */
static const struct kernel_symbol *resolve_symbol(struct module *mod,
const struct load_info *info,
const char *name,
char ownername[])
{
#ifdef CONFIG_TRIM_UNUSED_KSYMS
bool is_vendor_module;
bool is_vendor_exported_symbol;
#endif
struct find_symbol_arg fsa = {
.name = name,
.gplok = !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)),
@@ -1190,6 +1203,26 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod,
goto getname;
}
/*
* ANDROID GKI
*
* Vendor (i.e., unsigned) modules are only permitted to use:
*
* 1. symbols exported by other vendor (unsigned) modules
* 2. symbols which are permitted explicitly
*/
#ifdef CONFIG_TRIM_UNUSED_KSYMS
is_vendor_module = !mod->sig_ok;
is_vendor_exported_symbol = fsa.owner && !fsa.owner->sig_ok;
if (is_vendor_module &&
!is_vendor_exported_symbol &&
!is_permitted_symbol_import(name)) {
fsa.sym = ERR_PTR(-EACCES);
goto getname;
}
#endif
err = ref_module(mod, fsa.owner);
if (err) {
fsa.sym = ERR_PTR(err);
@@ -1487,9 +1520,15 @@ static int simplify_symbols(struct module *mod, const struct load_info *info)
ignore_undef_symbol(info->hdr->e_machine, name)))
break;
ret = PTR_ERR(ksym) ?: -ENOENT;
pr_warn("%s: Unknown symbol %s (err %d)\n",
mod->name, name, ret);
if (PTR_ERR(ksym) == -EACCES) {
ret = -EACCES;
pr_warn("%s: Protected symbol: %s (err %d)\n",
mod->name, name, ret);
} else {
ret = PTR_ERR(ksym) ?: -ENOENT;
pr_warn("%s: Unknown symbol %s (err %d)\n",
mod->name, name, ret);
}
break;
default: