Loading kernel/module/main.c +68 −14 Original line number Diff line number Diff line Loading @@ -195,6 +195,38 @@ static unsigned int find_sec(const struct load_info *info, const char *name) return 0; } /** * find_any_unique_sec() - Find a unique section index by name * @info: Load info for the module to scan * @name: Name of the section we're looking for * * Locates a unique section by name. Ignores SHF_ALLOC. * * Return: Section index if found uniquely, zero if absent, negative count * of total instances if multiple were found. */ static int find_any_unique_sec(const struct load_info *info, const char *name) { unsigned int idx; unsigned int count = 0; int i; for (i = 1; i < info->hdr->e_shnum; i++) { if (strcmp(info->secstrings + info->sechdrs[i].sh_name, name) == 0) { count++; idx = i; } } if (count == 1) { return idx; } else if (count == 0) { return 0; } else { return -count; } } /* Find a module section, or NULL. */ static void *section_addr(const struct load_info *info, const char *name) { Loading Loading @@ -1854,6 +1886,39 @@ static int elf_validity_cache_secstrings(struct load_info *info) return 0; } /** * elf_validity_cache_index_info() - Validate and cache modinfo section * @info: Load info to populate the modinfo index on. * Must have &load_info->sechdrs and &load_info->secstrings populated * * Checks that if there is a .modinfo section, it is unique. * Then, it caches its index in &load_info->index.info. * Finally, it tries to populate the name to improve error messages. * * Return: %0 if valid, %-ENOEXEC if multiple modinfo sections were found. */ static int elf_validity_cache_index_info(struct load_info *info) { int info_idx; info_idx = find_any_unique_sec(info, ".modinfo"); if (info_idx == 0) /* Early return, no .modinfo */ return 0; if (info_idx < 0) { pr_err("Only one .modinfo section must exist.\n"); return -ENOEXEC; } info->index.info = info_idx; /* Try to find a name early so we can log errors with a module name */ info->name = get_modinfo(info, "name"); return 0; } /* * Check userspace passed ELF module against our expectations, and cache * useful variables for further processing as we go. Loading @@ -1880,13 +1945,15 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) Elf_Shdr *shdr; int err; unsigned int num_mod_secs = 0, mod_idx; unsigned int num_info_secs = 0, info_idx; unsigned int num_sym_secs = 0, sym_idx; err = elf_validity_cache_sechdrs(info); if (err < 0) return err; err = elf_validity_cache_secstrings(info); if (err < 0) return err; err = elf_validity_cache_index_info(info); if (err < 0) return err; Loading @@ -1912,24 +1979,11 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) ".gnu.linkonce.this_module") == 0) { num_mod_secs++; mod_idx = i; } else if (strcmp(info->secstrings + shdr->sh_name, ".modinfo") == 0) { num_info_secs++; info_idx = i; } break; } } if (num_info_secs > 1) { pr_err("Only one .modinfo section must exist.\n"); goto no_exec; } else if (num_info_secs == 1) { /* Try to find a name early so we can log errors with a module name */ info->index.info = info_idx; info->name = get_modinfo(info, "name"); } if (num_sym_secs != 1) { pr_warn("%s: module has no symbols (stripped?)\n", info->name ?: "(missing .modinfo section or name field)"); Loading Loading
kernel/module/main.c +68 −14 Original line number Diff line number Diff line Loading @@ -195,6 +195,38 @@ static unsigned int find_sec(const struct load_info *info, const char *name) return 0; } /** * find_any_unique_sec() - Find a unique section index by name * @info: Load info for the module to scan * @name: Name of the section we're looking for * * Locates a unique section by name. Ignores SHF_ALLOC. * * Return: Section index if found uniquely, zero if absent, negative count * of total instances if multiple were found. */ static int find_any_unique_sec(const struct load_info *info, const char *name) { unsigned int idx; unsigned int count = 0; int i; for (i = 1; i < info->hdr->e_shnum; i++) { if (strcmp(info->secstrings + info->sechdrs[i].sh_name, name) == 0) { count++; idx = i; } } if (count == 1) { return idx; } else if (count == 0) { return 0; } else { return -count; } } /* Find a module section, or NULL. */ static void *section_addr(const struct load_info *info, const char *name) { Loading Loading @@ -1854,6 +1886,39 @@ static int elf_validity_cache_secstrings(struct load_info *info) return 0; } /** * elf_validity_cache_index_info() - Validate and cache modinfo section * @info: Load info to populate the modinfo index on. * Must have &load_info->sechdrs and &load_info->secstrings populated * * Checks that if there is a .modinfo section, it is unique. * Then, it caches its index in &load_info->index.info. * Finally, it tries to populate the name to improve error messages. * * Return: %0 if valid, %-ENOEXEC if multiple modinfo sections were found. */ static int elf_validity_cache_index_info(struct load_info *info) { int info_idx; info_idx = find_any_unique_sec(info, ".modinfo"); if (info_idx == 0) /* Early return, no .modinfo */ return 0; if (info_idx < 0) { pr_err("Only one .modinfo section must exist.\n"); return -ENOEXEC; } info->index.info = info_idx; /* Try to find a name early so we can log errors with a module name */ info->name = get_modinfo(info, "name"); return 0; } /* * Check userspace passed ELF module against our expectations, and cache * useful variables for further processing as we go. Loading @@ -1880,13 +1945,15 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) Elf_Shdr *shdr; int err; unsigned int num_mod_secs = 0, mod_idx; unsigned int num_info_secs = 0, info_idx; unsigned int num_sym_secs = 0, sym_idx; err = elf_validity_cache_sechdrs(info); if (err < 0) return err; err = elf_validity_cache_secstrings(info); if (err < 0) return err; err = elf_validity_cache_index_info(info); if (err < 0) return err; Loading @@ -1912,24 +1979,11 @@ static int elf_validity_cache_copy(struct load_info *info, int flags) ".gnu.linkonce.this_module") == 0) { num_mod_secs++; mod_idx = i; } else if (strcmp(info->secstrings + shdr->sh_name, ".modinfo") == 0) { num_info_secs++; info_idx = i; } break; } } if (num_info_secs > 1) { pr_err("Only one .modinfo section must exist.\n"); goto no_exec; } else if (num_info_secs == 1) { /* Try to find a name early so we can log errors with a module name */ info->index.info = info_idx; info->name = get_modinfo(info, "name"); } if (num_sym_secs != 1) { pr_warn("%s: module has no symbols (stripped?)\n", info->name ?: "(missing .modinfo section or name field)"); Loading