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

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
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 */
208static 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. */
199static void *section_addr(const struct load_info *info, const char *name)231static 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 */
1900static 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 cache1923 * 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)");