Skip to content

Commit fbc0e4e

Browse files
maurermcgrof
authored andcommitted
module: Factor out elf_validity_cache_index_info
Centralize .modinfo detection and property validation. Signed-off-by: Matthew Maurer <[email protected]> Reviewed-by: Sami Tolvanen <[email protected]> Signed-off-by: Luis Chamberlain <[email protected]>
1 parent 3c5700a commit fbc0e4e

File tree

1 file changed

+68
-14
lines changed

1 file changed

+68
-14
lines changed

kernel/module/main.c

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,38 @@ static unsigned int find_sec(const struct load_info *info, const char *name)
195195
return 0;
196196
}
197197

198+
/**
199+
* find_any_unique_sec() - Find a unique section index by name
200+
* @info: Load info for the module to scan
201+
* @name: Name of the section we're looking for
202+
*
203+
* Locates a unique section by name. Ignores SHF_ALLOC.
204+
*
205+
* Return: Section index if found uniquely, zero if absent, negative count
206+
* of total instances if multiple were found.
207+
*/
208+
static int find_any_unique_sec(const struct load_info *info, const char *name)
209+
{
210+
unsigned int idx;
211+
unsigned int count = 0;
212+
int i;
213+
214+
for (i = 1; i < info->hdr->e_shnum; i++) {
215+
if (strcmp(info->secstrings + info->sechdrs[i].sh_name,
216+
name) == 0) {
217+
count++;
218+
idx = i;
219+
}
220+
}
221+
if (count == 1) {
222+
return idx;
223+
} else if (count == 0) {
224+
return 0;
225+
} else {
226+
return -count;
227+
}
228+
}
229+
198230
/* Find a module section, or NULL. */
199231
static void *section_addr(const struct load_info *info, const char *name)
200232
{
@@ -1854,6 +1886,39 @@ static int elf_validity_cache_secstrings(struct load_info *info)
18541886
return 0;
18551887
}
18561888

1889+
/**
1890+
* elf_validity_cache_index_info() - Validate and cache modinfo section
1891+
* @info: Load info to populate the modinfo index on.
1892+
* Must have &load_info->sechdrs and &load_info->secstrings populated
1893+
*
1894+
* Checks that if there is a .modinfo section, it is unique.
1895+
* Then, it caches its index in &load_info->index.info.
1896+
* Finally, it tries to populate the name to improve error messages.
1897+
*
1898+
* Return: %0 if valid, %-ENOEXEC if multiple modinfo sections were found.
1899+
*/
1900+
static int elf_validity_cache_index_info(struct load_info *info)
1901+
{
1902+
int info_idx;
1903+
1904+
info_idx = find_any_unique_sec(info, ".modinfo");
1905+
1906+
if (info_idx == 0)
1907+
/* Early return, no .modinfo */
1908+
return 0;
1909+
1910+
if (info_idx < 0) {
1911+
pr_err("Only one .modinfo section must exist.\n");
1912+
return -ENOEXEC;
1913+
}
1914+
1915+
info->index.info = info_idx;
1916+
/* Try to find a name early so we can log errors with a module name */
1917+
info->name = get_modinfo(info, "name");
1918+
1919+
return 0;
1920+
}
1921+
18571922
/*
18581923
* Check userspace passed ELF module against our expectations, and cache
18591924
* useful variables for further processing as we go.
@@ -1880,13 +1945,15 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
18801945
Elf_Shdr *shdr;
18811946
int err;
18821947
unsigned int num_mod_secs = 0, mod_idx;
1883-
unsigned int num_info_secs = 0, info_idx;
18841948
unsigned int num_sym_secs = 0, sym_idx;
18851949

18861950
err = elf_validity_cache_sechdrs(info);
18871951
if (err < 0)
18881952
return err;
18891953
err = elf_validity_cache_secstrings(info);
1954+
if (err < 0)
1955+
return err;
1956+
err = elf_validity_cache_index_info(info);
18901957
if (err < 0)
18911958
return err;
18921959

@@ -1912,24 +1979,11 @@ static int elf_validity_cache_copy(struct load_info *info, int flags)
19121979
".gnu.linkonce.this_module") == 0) {
19131980
num_mod_secs++;
19141981
mod_idx = i;
1915-
} else if (strcmp(info->secstrings + shdr->sh_name,
1916-
".modinfo") == 0) {
1917-
num_info_secs++;
1918-
info_idx = i;
19191982
}
19201983
break;
19211984
}
19221985
}
19231986

1924-
if (num_info_secs > 1) {
1925-
pr_err("Only one .modinfo section must exist.\n");
1926-
goto no_exec;
1927-
} else if (num_info_secs == 1) {
1928-
/* Try to find a name early so we can log errors with a module name */
1929-
info->index.info = info_idx;
1930-
info->name = get_modinfo(info, "name");
1931-
}
1932-
19331987
if (num_sym_secs != 1) {
19341988
pr_warn("%s: module has no symbols (stripped?)\n",
19351989
info->name ?: "(missing .modinfo section or name field)");

0 commit comments

Comments
 (0)