Patch: ldd and ld-2.0.7.so

ralf@uni-koblenz.de
Tue, 27 Oct 1998 16:31:26 +0100


On Sat, Oct 24, 1998 at 04:02:00AM -0400, Ralf Wierzbicki wrote:

> The dynamic loader (2.0.7) coredumps in linux 2.1.126 with a segmentation
> fault. I checked in 2.1.125 and ldd works fine, the problem occurs
> only in 2.1.126 when trying to run ld-2.0.7 --verify (ldd).

The problem was in my fix to binfmt_elf to handle certain address
combinations, certain executables linked to addresses != 0 would have
dumped core. This is (for the sake of tradition ...) the case on MIPS.

The fix has a bug which crashes ET_DYN executables like ld-2.0.7.so on
certain architectures like Intel where addresses are just right. The
appended patch fixes this. The patch looks quite a bit bigger than it
actually is since I used the occassion to rewrite and reformat the code
in question a bit so it is less heavily indented. The actuall functional
fix is a two liner or so. Tested on Intel and MIPS. Linus, please include
the appended fix.

Ralf

--- linux-2.1.126.orig/fs/binfmt_elf.c Tue Oct 27 04:41:35 1998
+++ linux-2.1.126/fs/binfmt_elf.c Tue Oct 27 13:15:35 1998
@@ -608,7 +608,7 @@
base, as well as whatever program they might try to exec. This
is because the brk will follow the loader, and is not movable. */

- load_bias = (elf_ex.e_type == ET_DYN ? ELF_ET_DYN_BASE : 0);
+ load_bias = ELF_PAGESTART(elf_ex.e_type==ET_DYN ? ELF_ET_DYN_BASE : 0);

/* Now we do a little grungy work by mmaping the ELF image into
the correct location in memory. At this point, we assume that
@@ -618,51 +618,50 @@
old_fs = get_fs();
set_fs(get_ds());
for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
- if (elf_ppnt->p_type == PT_LOAD) {
- int elf_prot = 0, elf_flags;
- unsigned long vaddr;
-
- if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
- if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
- if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
-
- elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
-
- vaddr = elf_ppnt->p_vaddr;
- if (elf_ex.e_type == ET_EXEC || load_addr_set) {
- elf_flags |= MAP_FIXED;
- }
+ int elf_prot = 0, elf_flags;
+ unsigned long vaddr;
+
+ if (elf_ppnt->p_type != PT_LOAD)
+ continue;
+
+ if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
+ if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+ if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
+
+ elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
+
+ vaddr = elf_ppnt->p_vaddr;
+ 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)));
-
- if (!load_addr_set) {
- load_addr_set = 1;
- load_addr = (elf_ppnt->p_vaddr -
- elf_ppnt->p_offset);
- if (elf_ex.e_type == ET_DYN) {
- load_bias = error - ELF_PAGESTART(load_bias + vaddr);
- load_addr += error;
- }
+ 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)));
+
+ if (!load_addr_set) {
+ load_addr_set = 1;
+ load_addr = (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
+ if (elf_ex.e_type == ET_DYN) {
+ load_bias += error -
+ ELF_PAGESTART(load_bias + vaddr);
+ load_addr += error;
}
- k = elf_ppnt->p_vaddr;
- if (k < start_code) start_code = k;
- k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
- if (k > elf_bss)
- elf_bss = k;
- if ((elf_ppnt->p_flags & PF_X) && end_code < k)
- end_code = k;
- if (end_data < k)
- end_data = k;
- k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
- if (k > elf_brk)
- elf_brk = k;
}
+ k = elf_ppnt->p_vaddr;
+ if (k < start_code) start_code = k;
+ k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
+ if (k > elf_bss)
+ elf_bss = k;
+ if ((elf_ppnt->p_flags & PF_X) && end_code < k)
+ end_code = k;
+ if (end_data < k)
+ end_data = k;
+ k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
+ if (k > elf_brk)
+ elf_brk = k;
}
set_fs(old_fs);
fput(file); /* all done with the file */

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