mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-15 02:05:33 +00:00
module: Factor out elf_validity_cache_index_info
Centralize .modinfo detection and property validation. Signed-off-by: Matthew Maurer <mmaurer@google.com> Reviewed-by: Sami Tolvanen <samitolvanen@google.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
This commit is contained in:
parent
3c5700aeab
commit
fbc0e4e482
@ -195,6 +195,38 @@ static unsigned int find_sec(const struct load_info *info, const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_any_unique_sec() - Find a unique section index by name
|
||||
* @info: Load info for the module to scan
|
||||
* @name: Name of the section we're looking for
|
||||
*
|
||||
* Locates a unique section by name. Ignores SHF_ALLOC.
|
||||
*
|
||||
* Return: Section index if found uniquely, zero if absent, negative count
|
||||
* of total instances if multiple were found.
|
||||
*/
|
||||
static int find_any_unique_sec(const struct load_info *info, const char *name)
|
||||
{
|
||||
unsigned int idx;
|
||||
unsigned int count = 0;
|
||||
int i;
|
||||
|
||||
for (i = 1; i < info->hdr->e_shnum; i++) {
|
||||
if (strcmp(info->secstrings + info->sechdrs[i].sh_name,
|
||||
name) == 0) {
|
||||
count++;
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
if (count == 1) {
|
||||
return idx;
|
||||
} else if (count == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return -count;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find a module section, or NULL. */
|
||||
static void *section_addr(const struct load_info *info, const char *name)
|
||||
{
|
||||
@ -1854,6 +1886,39 @@ static int elf_validity_cache_secstrings(struct load_info *info)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* elf_validity_cache_index_info() - Validate and cache modinfo section
|
||||
* @info: Load info to populate the modinfo index on.
|
||||
* Must have &load_info->sechdrs and &load_info->secstrings populated
|
||||
*
|
||||
* Checks that if there is a .modinfo section, it is unique.
|
||||
* Then, it caches its index in &load_info->index.info.
|
||||
* Finally, it tries to populate the name to improve error messages.
|
||||
*
|
||||
* Return: %0 if valid, %-ENOEXEC if multiple modinfo sections were found.
|
||||
*/
|
||||
static int elf_validity_cache_index_info(struct load_info *info)
|
||||
{
|
||||
int info_idx;
|
||||
|
||||
info_idx = find_any_unique_sec(info, ".modinfo");
|
||||
|
||||
if (info_idx == 0)
|
||||
/* Early return, no .modinfo */
|
||||
return 0;
|
||||
|
||||
if (info_idx < 0) {
|
||||
pr_err("Only one .modinfo section must exist.\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
info->index.info = info_idx;
|
||||
/* Try to find a name early so we can log errors with a module name */
|
||||
info->name = get_modinfo(info, "name");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check userspace passed ELF module against our expectations, and cache
|
||||
* useful variables for further processing as we go.
|
||||
@ -1880,13 +1945,15 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
|
||||
Elf_Shdr *shdr;
|
||||
int err;
|
||||
unsigned int num_mod_secs = 0, mod_idx;
|
||||
unsigned int num_info_secs = 0, info_idx;
|
||||
unsigned int num_sym_secs = 0, sym_idx;
|
||||
|
||||
err = elf_validity_cache_sechdrs(info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = elf_validity_cache_secstrings(info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = elf_validity_cache_index_info(info);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@ -1912,24 +1979,11 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
|
||||
".gnu.linkonce.this_module") == 0) {
|
||||
num_mod_secs++;
|
||||
mod_idx = i;
|
||||
} else if (strcmp(info->secstrings + shdr->sh_name,
|
||||
".modinfo") == 0) {
|
||||
num_info_secs++;
|
||||
info_idx = i;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_info_secs > 1) {
|
||||
pr_err("Only one .modinfo section must exist.\n");
|
||||
goto no_exec;
|
||||
} else if (num_info_secs == 1) {
|
||||
/* Try to find a name early so we can log errors with a module name */
|
||||
info->index.info = info_idx;
|
||||
info->name = get_modinfo(info, "name");
|
||||
}
|
||||
|
||||
if (num_sym_secs != 1) {
|
||||
pr_warn("%s: module has no symbols (stripped?)\n",
|
||||
info->name ?: "(missing .modinfo section or name field)");
|
||||
|
Loading…
x
Reference in New Issue
Block a user