Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Matthew Maurer and committed by
Luis Chamberlain
fbc0e4e4 3c5700ae

+68 -14
+68 -14
kernel/module/main.c
··· 195 195 return 0; 196 196 } 197 197 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 + 198 230 /* Find a module section, or NULL. */ 199 231 static void *section_addr(const struct load_info *info, const char *name) 200 232 { ··· 1886 1854 return 0; 1887 1855 } 1888 1856 1857 + /** 1858 + * elf_validity_cache_index_info() - Validate and cache modinfo section 1859 + * @info: Load info to populate the modinfo index on. 1860 + * Must have &load_info->sechdrs and &load_info->secstrings populated 1861 + * 1862 + * Checks that if there is a .modinfo section, it is unique. 1863 + * Then, it caches its index in &load_info->index.info. 1864 + * Finally, it tries to populate the name to improve error messages. 1865 + * 1866 + * Return: %0 if valid, %-ENOEXEC if multiple modinfo sections were found. 1867 + */ 1868 + static int elf_validity_cache_index_info(struct load_info *info) 1869 + { 1870 + int info_idx; 1871 + 1872 + info_idx = find_any_unique_sec(info, ".modinfo"); 1873 + 1874 + if (info_idx == 0) 1875 + /* Early return, no .modinfo */ 1876 + return 0; 1877 + 1878 + if (info_idx < 0) { 1879 + pr_err("Only one .modinfo section must exist.\n"); 1880 + return -ENOEXEC; 1881 + } 1882 + 1883 + info->index.info = info_idx; 1884 + /* Try to find a name early so we can log errors with a module name */ 1885 + info->name = get_modinfo(info, "name"); 1886 + 1887 + return 0; 1888 + } 1889 + 1889 1890 /* 1890 1891 * Check userspace passed ELF module against our expectations, and cache 1891 1892 * useful variables for further processing as we go. ··· 1945 1880 Elf_Shdr *shdr; 1946 1881 int err; 1947 1882 unsigned int num_mod_secs = 0, mod_idx; 1948 - unsigned int num_info_secs = 0, info_idx; 1949 1883 unsigned int num_sym_secs = 0, sym_idx; 1950 1884 1951 1885 err = elf_validity_cache_sechdrs(info); 1952 1886 if (err < 0) 1953 1887 return err; 1954 1888 err = elf_validity_cache_secstrings(info); 1889 + if (err < 0) 1890 + return err; 1891 + err = elf_validity_cache_index_info(info); 1955 1892 if (err < 0) 1956 1893 return err; 1957 1894 ··· 1979 1912 ".gnu.linkonce.this_module") == 0) { 1980 1913 num_mod_secs++; 1981 1914 mod_idx = i; 1982 - } else if (strcmp(info->secstrings + shdr->sh_name, 1983 - ".modinfo") == 0) { 1984 - num_info_secs++; 1985 - info_idx = i; 1986 1915 } 1987 1916 break; 1988 1917 } 1989 - } 1990 - 1991 - if (num_info_secs > 1) { 1992 - pr_err("Only one .modinfo section must exist.\n"); 1993 - goto no_exec; 1994 - } else if (num_info_secs == 1) { 1995 - /* Try to find a name early so we can log errors with a module name */ 1996 - info->index.info = info_idx; 1997 - info->name = get_modinfo(info, "name"); 1998 1918 } 1999 1919 2000 1920 if (num_sym_secs != 1) {