[PATCH] Longstanding elf fix (2.2.19 fix)

Eric W. Biederman (ebiederman@lnxi.com)
22 Apr 2001 18:09:14 -0600


--=-=-=

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

--=-=-=
Content-Type: text/x-patch
Content-Disposition: attachment; filename=linux-2.2.19.elf-fix.diff

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
diff -uNrX linux-exclude-files linux-2.2.19/fs/binfmt_elf.c linux-2.2.19.elf-fix/fs/binfmt_elf.c
--- linux-2.2.19/fs/binfmt_elf.c Fri Apr 20 13:25:11 2001
+++ linux-2.2.19.elf-fix/fs/binfmt_elf.c Sun Apr 22 17:55:42 2001
@@ -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);

--=-=-=

--=-=-=--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/