Longstanding elf fix (2.2.19 fix)
Subsystems (2)
PATCH 1/1 Longstanding elf fix (2.2.19 fix)
A little while ago I was playing with building an elf self extracting binary. In doing so I discovered that the linux kernel does not handle elf program headers with multiple BSS segments.
Eric
Binary files linux-2.2.19/drivers/char/conmakehash and linux-2.2.19.elf-fix/drivers/char/conmakehash differ Binary files linux-2.2.19/drivers/char/hfmodem/gentbl and linux-2.2.19.elf-fix/drivers/char/hfmodem/gentbl differ
fs/binfmt_elf.c +24 -48
@@ -71,18 +71,6 @@#endif }; -static void set_brk (unsigned long start,unsigned long end) -{ - start =ELF_PAGEALIGN (start); - end =ELF_PAGEALIGN (end); -if (end <= start) -return ; -do_mmap (NULL , start, end - start, -PROT_READ |PROT_WRITE |PROT_EXEC , -MAP_FIXED |MAP_PRIVATE ,0 ); -} - -/* We need to explicitly zero any fractional pages after the data section (i.e. bss). This would contain the junk from the file that should not
@@ -213,6 +201,28 @@return sp; } +static inline unsigned long +elf_map (struct file *filep,unsigned long addr,struct elf_phdr *eppnt,int prot,int type) +{ +unsigned long start, data_len, mem_len, offset; +unsigned long map_addr; + + start =ELF_PAGESTART (addr); + data_len =ELF_PAGEALIGN (eppnt->p_filesz +ELF_PAGEOFFSET (eppnt->p_vaddr)); + mem_len =ELF_PAGEALIGN (eppnt->p_memsz +ELF_PAGEOFFSET (eppnt->p_vaddr)); + offset = eppnt->p_offset -ELF_PAGEOFFSET (eppnt->p_vaddr); + +if (eppnt->p_filesz) { + map_addr =do_mmap (filep, start, data_len, prot, type, offset); +do_mmap (NULL , map_addr + data_len, mem_len - data_len, prot, +MAP_FIXED |MAP_PRIVATE ,0 ); +padzero (map_addr + eppnt->p_filesz +ELF_PAGEOFFSET (eppnt->p_vaddr)); + }else { + map_addr =do_mmap (NULL , start, mem_len, prot,MAP_PRIVATE ,0 ); + } +return (map_addr); +} +/* This is much more generalized than the library routine read function, so we keep this separate. Technically the library read function
@@ -293,12 +303,7 @@#endif } - map_addr =do_mmap (file, - load_addr +ELF_PAGESTART (vaddr), - eppnt->p_filesz +ELF_PAGEOFFSET (eppnt->p_vaddr), - elf_prot, - elf_type, - eppnt->p_offset -ELF_PAGEOFFSET (eppnt->p_vaddr)); + map_addr =elf_map (file, load_addr + vaddr, eppnt, elf_prot, elf_type);if (map_addr >-1024UL )/* Real error */ goto out_close;
@@ -325,23 +330,6 @@ } } -/* Now use mmap to map the library into memory. */ - -/* -* Now fill out the bss section. First pad the last page up -* to the page boundary, and then perform a mmap to make sure -* that there are zero-mapped pages up to and including the -* last bss page. -*/ -padzero (elf_bss); - elf_bss =ELF_PAGESTART (elf_bss +ELF_EXEC_PAGESIZE -1 );/* What we have mapped so far */ - -/* Map the last of the bss segment */ -if (last_bss > elf_bss) -do_mmap (NULL , elf_bss, last_bss - elf_bss, -PROT_READ |PROT_WRITE |PROT_EXEC , -MAP_FIXED |MAP_PRIVATE ,0 ); - *interp_load_addr = load_addr;/* * AUDIT: is everything deallocated properly if this happens
@@ -660,12 +648,7 @@if (elf_ex.e_type ==ET_EXEC || load_addr_set) { elf_flags |=MAP_FIXED ; } - - error =do_mmap (file,ELF_PAGESTART (load_bias + vaddr), - (elf_ppnt->p_filesz + -ELF_PAGEOFFSET (elf_ppnt->p_vaddr)), - elf_prot, elf_flags, (elf_ppnt->p_offset - -ELF_PAGEOFFSET (elf_ppnt->p_vaddr))); + error =elf_map (file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);if (!load_addr_set) { load_addr_set =1 ;
@@ -760,13 +743,6 @@ current->mm->start_code = start_code; current->mm->end_data = end_data; current->mm->start_stack = bprm->p; - -/* Calling set_brk effectively mmaps the pages that we need -* for the bss and break sections -*/ -set_brk (elf_bss, elf_brk); - -padzero (elf_bss);#if 0 printk ("(start_brk) %x\n" , current->mm->start_brk);