From: Masahiro Yamada Date: Mon, 25 May 2020 05:47:04 +0000 (+0900) Subject: modpost: fix potential segmentation fault for addend_i386_rel() X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=d2e4d05cf1a1f8bfe168ea29b217355be7a4e9ec;p=uclinux-h8%2Flinux.git modpost: fix potential segmentation fault for addend_i386_rel() This may not be a practical problem, but the second pass of ARCH=i386 modpost causes segmentation fault if the -s option is not passed. MODPOST 12 modules Segmentation fault (core dumped) make[2]: *** [scripts/Makefile.modpost:94: __modpost] Error 139 make[1]: *** [Makefile:1339: modules] Error 2 make[1]: *** Waiting for unfinished jobs.... The segmentation fault occurs when section_rel() is called for vmlinux, which is untested in regular builds. The cause of the problem is reloc_location() returning a wrong pointer for ET_EXEC object type. In this case, you need to subtract sechdr->sh_addr, otherwise it would get access beyond the mmap'ed memory. Add sym_get_data_by_offset() helper to avoid code duplication. Signed-off-by: Masahiro Yamada --- diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 4d4b979d76be..8c5f1bd75481 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -300,19 +300,23 @@ static const char *sec_name(struct elf_info *elf, int secindex) return sech_name(elf, &elf->sechdrs[secindex]); } -static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym) +static void *sym_get_data_by_offset(const struct elf_info *info, + unsigned int secindex, unsigned long offset) { - unsigned int secindex = get_secindex(info, sym); Elf_Shdr *sechdr = &info->sechdrs[secindex]; - unsigned long offset; - offset = sym->st_value; if (info->hdr->e_type != ET_REL) offset -= sechdr->sh_addr; return (void *)info->hdr + sechdr->sh_offset + offset; } +static void *sym_get_data(const struct elf_info *info, const Elf_Sym *sym) +{ + return sym_get_data_by_offset(info, get_secindex(info, sym), + sym->st_value); +} + #define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0) static enum export export_from_secname(struct elf_info *elf, unsigned int sec) @@ -1752,11 +1756,7 @@ static void check_section_mismatch(const char *modname, struct elf_info *elf, static unsigned int *reloc_location(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) { - Elf_Shdr *sechdrs = elf->sechdrs; - int section = sechdr->sh_info; - - return (void *)elf->hdr + sechdrs[section].sh_offset + - r->r_offset; + return sym_get_data_by_offset(elf, sechdr->sh_info, r->r_offset); } static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)