From Bugzilla Helper: User-Agent: Mozilla/4.75 [en] (X11; U; Linux 2.2.19-6.2.1perf2.0 i586) Description of problem: If an ELF main executable specifies a PT_INTERP program interpreter which has ET_EXEC format, and if the the program interpreter has an unusual PT_LOAD/.bss configuration, then the kernel starts the process at the wrong entry address. fs/binfmt_elf.c has a bug in RedHat 7.2 (kernel 2.4.9-7) that worked correctly in RedHat 7.1 (kernel 2.4.3-12). Version-Release number of selected component (if applicable): Red Hat Linux release 7.2 (Enigma) 2.4.9-7 i386 [i686] How reproducible: Always Steps to Reproduce: 1. Compile and run the program below to generate files "a.elf" and "pt_interp" with one of the bad configurations. Both a.elf and pt_interp exit(0) immediately [3 instructions]. 2. Set ulimit to allow a core file. Run the ./a.elf file and observe SIGSEGV, and get a core file. 3. Inspect the core file (gdb will work here) to see a PC of 0x40, which is an address that is nowhere specified in either the a.elf or pt_interp files. -----elfbug.c #include <elf.h> #include <fcntl.h> #include <string.h> #include <unistd.h> int main(void) { char const code[]={ 0xb8,1,0,0,0, /* movl $__NR_exit,%eax */ 0xbb,0,0,0,0, /* movl $0,%ebx */ 0xcd,0x80 /* syscall */ }; int fd; static char const pt_interp[]="pt_interp"; Elf32_Ehdr ehdr; Elf32_Phdr phdr[2]; memset(&ehdr, 0, sizeof(ehdr)); ehdr.e_ident[0]=ELFMAG0; ehdr.e_ident[1]=ELFMAG1; ehdr.e_ident[2]=ELFMAG2; ehdr.e_ident[3]=ELFMAG3; ehdr.e_ident[EI_CLASS]=ELFCLASS32; ehdr.e_ident[EI_DATA]=ELFDATA2LSB; ehdr.e_ident[EI_VERSION]=EV_CURRENT; ehdr.e_ident[EI_ABIVERSION]=0; ehdr.e_type=ET_EXEC; ehdr.e_machine=EM_386; ehdr.e_version=EV_CURRENT; ehdr.e_entry=0x4200000+sizeof(ehdr)+sizeof(phdr); ehdr.e_phoff=sizeof(ehdr); ehdr.e_shoff=0; ehdr.e_flags=0; ehdr.e_ehsize=sizeof(Elf32_Ehdr); ehdr.e_phentsize=sizeof(Elf32_Phdr); ehdr.e_phnum=2; ehdr.e_shentsize=0; ehdr.e_shnum=0; ehdr.e_shstrndx=0; phdr[0].p_type=PT_LOAD; phdr[0].p_offset=0; phdr[0].p_vaddr=0x4200000; phdr[0].p_paddr=0x4200000; phdr[0].p_filesz=sizeof(ehdr)+sizeof(phdr)+sizeof(pt_interp)+ sizeof(code) ; phdr[0].p_memsz=phdr[0].p_filesz; phdr[0].p_flags=PF_X | PF_R; phdr[0].p_align=1<<12; phdr[1] = phdr[0]; phdr[1].p_type=PT_INTERP; phdr[1].p_offset = sizeof(ehdr) + sizeof(phdr) + sizeof(code); phdr[1].p_vaddr += phdr[1].p_offset; phdr[1].p_paddr += phdr[1].p_offset; phdr[1].p_filesz=sizeof(pt_interp); phdr[1].p_memsz=phdr[0].p_filesz; phdr[1].p_flags=PF_R; phdr[1].p_align=1; fd=open("a.elf", O_CREAT | O_WRONLY, 0755); write(fd, &ehdr, sizeof(ehdr)); write(fd, &phdr, sizeof(phdr)); write(fd, &code, sizeof(code)); write(fd, &pt_interp[0], sizeof(pt_interp)); close(fd); ehdr.e_entry += 0x84000 - 0x4200000; phdr[0].p_vaddr=0x84000; phdr[0].p_paddr=0x84000; phdr[0].p_filesz=sizeof(ehdr)+sizeof(phdr)+sizeof(code); phdr[0].p_memsz=phdr[0].p_filesz; phdr[0].p_flags=PF_X|PF_R|PF_W; phdr[1].p_type = PT_LOAD; phdr[1].p_offset = (1<<12) + phdr[0].p_filesz; phdr[1].p_vaddr = 0; phdr[1].p_paddr = 0; phdr[1].p_filesz = 0; phdr[1].p_memsz = 0; phdr[1].p_flags = 0; phdr[1].p_align=1; fd=open(pt_interp, O_CREAT | O_WRONLY, 0755); write(fd, &ehdr, sizeof(ehdr)); write(fd, &phdr, sizeof(phdr)); write(fd, &code, sizeof(code)); close(fd); return 0; } ----- Actual Results: $ gcc -o elfbug elfbug.c $ ./elfbug $ ulimit -c 1000 $ ./a.elf Segmentation fault (core dumped) $ gdb a.elf core GNU gdb 5.0 Copyright 2000 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i586-pc-linux-gnu"..."a.elf": not in executable format: File format not recognized ### gdb is too picky about Elf32_Shdr, but it doesn't matter here Core was generated by `./a.elf'. Program terminated with signal 11, Segmentation fault. #0 0x40 in ?? () (gdb) info reg eax 0x0 0 ecx 0x0 0 edx 0x0 0 ebx 0x0 0 esp 0xbffffa80 0xbffffa80 ebp 0x0 0x0 esi 0x0 0 edi 0x0 0 eip 0x40 0x40 ### garbage address eflags 0x10246 66118 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x2b 43 gs 0x2b 43 fctrl 0x0 0 fstat 0x0 0 ftag 0x0 0 fiseg 0x0 0 fioff 0x0 0 foseg 0x0 0 fooff 0x0 0 fop 0x0 0 (gdb) q Expected Results: $ ./a.elf $ echo $? 0 $ Additional info:
Thanks for the bug report. However, Red Hat no longer maintains this version of the product. Please upgrade to the latest version and open a new bug if the problem persists. The Fedora Legacy project (http://fedoralegacy.org/) maintains some older releases, and if you believe this bug is interesting to them, please report the problem in the bug tracker at: http://bugzilla.fedora.us/