History

module: Factor out elf_validity_cache_index_info

Centralize .modinfo detection and property validation.

Matthew Maurer committed 2 years ago

Commit fbc0e4e1 parent 3c5700a1 file · +68 −14Browse files

Showing the changes to kernel/module (1 of 1 file). Show all

Unified · Split

kernel/module/main.c+68−14
@@ -195,6 +195,38 @@ static unsigned int find_sec(const struct load_info *info, const char *name) · 194 unmodified lines
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) · 1653 unmodified lines
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) · 20 unmodified lines
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) · 19 unmodified lines
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)");