Centralize .modinfo detection and property validation.
Showing the changes to kernel/module (1 of 1 file). Show all
Unified · Split
| @@ -195,6 +195,38 @@ static unsigned int find_sec(const struct load_info *info, const char *name) · 194 unmodified lines | |||
| 195 | return 0; | 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 | /* Find a module section, or NULL. */ | 230 | /* Find a module section, or NULL. */ |
| 199 | static void *section_addr(const struct load_info *info, const char *name) | 231 | static void *section_addr(const struct load_info *info, const char *name) |
| 200 | { | 232 | { |
| @@ -1854,6 +1886,39 @@ static int elf_validity_cache_secstrings(struct load_info *info) · 1653 unmodified lines | |||
| 1854 | return 0; | 1886 | return 0; |
| 1855 | } | 1887 | } |
| 1856 | 1888 | ||
| 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 | |||
| 1857 | /* | 1922 | /* |
| 1858 | * Check userspace passed ELF module against our expectations, and cache | 1923 | * Check userspace passed ELF module against our expectations, and cache |
| 1859 | * useful variables for further processing as we go. | 1924 | * 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 | |||
| 1880 | Elf_Shdr *shdr; | 1945 | Elf_Shdr *shdr; |
| 1881 | int err; | 1946 | int err; |
| 1882 | unsigned int num_mod_secs = 0, mod_idx; | 1947 | unsigned int num_mod_secs = 0, mod_idx; |
| 1883 | unsigned int num_info_secs = 0, info_idx; | ||
| 1884 | unsigned int num_sym_secs = 0, sym_idx; | 1948 | unsigned int num_sym_secs = 0, sym_idx; |
| 1885 | 1949 | ||
| 1886 | err = elf_validity_cache_sechdrs(info); | 1950 | err = elf_validity_cache_sechdrs(info); |
| 1887 | if (err < 0) | 1951 | if (err < 0) |
| 1888 | return err; | 1952 | return err; |
| 1889 | err = elf_validity_cache_secstrings(info); | 1953 | err = elf_validity_cache_secstrings(info); |
| 1954 | if (err < 0) | ||
| 1955 | return err; | ||
| 1956 | err = elf_validity_cache_index_info(info); | ||
| 1890 | if (err < 0) | 1957 | if (err < 0) |
| 1891 | return err; | 1958 | return err; |
| 1892 | 1959 | ||
| @@ -1912,24 +1979,11 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) · 19 unmodified lines | |||
| 1912 | ".gnu.linkonce.this_module") == 0) { | 1979 | ".gnu.linkonce.this_module") == 0) { |
| 1913 | num_mod_secs++; | 1980 | num_mod_secs++; |
| 1914 | mod_idx = i; | 1981 | mod_idx = i; |
| 1915 | } else if (strcmp(info->secstrings + shdr->sh_name, | ||
| 1916 | ".modinfo") == 0) { | ||
| 1917 | num_info_secs++; | ||
| 1918 | info_idx = i; | ||
| 1919 | } | 1982 | } |
| 1920 | break; | 1983 | break; |
| 1921 | } | 1984 | } |
| 1922 | } | 1985 | } |
| 1923 | 1986 | ||
| 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 | |||
| 1933 | if (num_sym_secs != 1) { | 1987 | if (num_sym_secs != 1) { |
| 1934 | pr_warn("%s: module has no symbols (stripped?)\n", | 1988 | pr_warn("%s: module has no symbols (stripped?)\n", |
| 1935 | info->name ?: "(missing .modinfo section or name field)"); | 1989 | info->name ?: "(missing .modinfo section or name field)"); |