Hi,
I would like to report a SEGFAULT in nm(1) that occurs with object-file
with no section headers (e_shnum = 0). This object-file was generated by
eg++ (I am not sure if the object-file is valid or not).
I am also able to reproduce the problem with edited elf object (using
hte [editors/ht]) by manually setting the section header count to zero.
$ readelf -h obj/cciVHsvd-2.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 8932544 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 0 (73122)
Section header string table index: 65535 (73374)
$ gdb -q -args ./obj/nm -n obj/cciVHsvd-2.o
(gdb) r
Starting program: /usr/obj/usr.bin/nm/nm -n obj/cciVHsvd-2.o
Program received signal SIGSEGV, Segmentation fault.
0x000019a9f830728e in elf64_symload (name=0x7f7ffffefe82 "obj/cciVHsvd-2.o",
fp=0x19aca16c7180, foff=0, eh=0x7f7ffffefbb0,
shdr=0x19aca4026720, pnames=0x7f7ffffefb38, psnames=0x7f7ffffefb30,
pstabsize=0x7f7ffffefb28, pnrawnames=0x7f7ffffefb70) at elf64.c:529
529 shstrsize = shdr[eh->e_shstrndx].sh_size;
(gdb) bt
#0 0x000019a9f830728e in elf64_symload (name=0x7f7ffffefe82
"obj/cciVHsvd-2.o", fp=0x19aca16c7180, foff=0, eh=0x7f7ffffefbb0,
shdr=0x19aca4026720, pnames=0x7f7ffffefb38, psnames=0x7f7ffffefb30,
pstabsize=0x7f7ffffefb28, pnrawnames=0x7f7ffffefb70) at elf64.c:529
#1 0x000019a9f83037ca in show_file (count=1, warn_fmt=1, name=0x7f7ffffefe82
"obj/cciVHsvd-2.o", fp=0x19aca16c7180, foff=0,
head=0x7f7ffffefbb0) at /usr/src/usr.bin/nm/nm.c:636
#2 0x000019a9f8302548 in process_file (count=1, fname=0x7f7ffffefe82
"obj/cciVHsvd-2.o") at /usr/src/usr.bin/nm/nm.c:267
#3 0x000019a9f83022e3 in main (argc=1, argv=0x7f7ffffefcd8) at
/usr/src/usr.bin/nm/nm.c:208
(gdb) print eh
$1 = (Elf64_Ehdr *) 0x7f7ffffefbb0
(gdb) print *eh
$2 = {e_ident = "\177ELF\002\001\001\000\000\000\000\000\000\000\000", e_type =
1, e_machine = 62, e_version = 1, e_entry = 0, e_phoff = 0,
e_shoff = 8932544, e_flags = 0, e_ehsize = 64, e_phentsize = 0, e_phnum = 0,
e_shentsize = 64, e_shnum = 0, e_shstrndx = 65535}
(gdb) print shdr
$3 = (Elf64_Shdr *) 0x19aca4026720
(gdb) print *shdr
Cannot access memory at address 0x19aca4026720
(gdb) quit
The segfault is caused by "shdr[eh->e_shstrndx]" (src/usr.bin/nm/elf.c:528).
shdr is allocated by elf_load_shdrs() (elf.c:152):
> if ((shdr = calloc(head->e_shentsize, head->e_shnum)) == NULL) {
> warn("%s: malloc shdr", name);
> return (NULL);
> }
Here, the object-file has e_shnum=0 (no section header table), so shdr
is an zero sized object.
The patch adds two check:
- e_shnum == 0: no section header table
- a consistency check (should prevent craft object-file to generate
out-of-bound read).
Maybe a check for overflow would be needed too ?
--
Sébastien Marie
Index: elf.c
===================================================================
RCS file: /cvs/src/usr.bin/nm/elf.c,v
retrieving revision 1.28
diff -u -p -r1.28 elf.c
--- elf.c 17 May 2015 20:19:08 -0000 1.28
+++ elf.c 17 Jun 2015 12:05:25 -0000
@@ -149,6 +149,16 @@ elf_load_shdrs(const char *name, FILE *f
elf_fix_header(head);
+ if (head->e_shnum == 0) {
+ warnx("%s: no section header table", name);
+ return (NULL);
+ }
+
+ if (head->e_shstrndx >= head->e_shentsize * head->e_shnum) {
+ warnx("%s: inconsistent section header table", name);
+ return (NULL);
+ }
+
if ((shdr = calloc(head->e_shentsize, head->e_shnum)) == NULL) {
warn("%s: malloc shdr", name);
return (NULL);