2001-08-30 Miles Bader * binfmt_flat.c (load_flat_binary): Don't use the executable's entry point as the start of the text segment (it may not be). Skip header correctly when calculating start_code/end_code. Don't assume data follows text when calculating end_code. Relocate non-longword-aligned pointers correctly. Include . diff -ruP -Xcludes linux-2.4.6.uclinux-orig/fs/binfmt_flat.c linux-2.4.6/fs/binfmt_flat.c --- linux-2.4.6.uclinux-orig/fs/binfmt_flat.c Mon Aug 27 17:12:20 2001 +++ linux-2.4.6/fs/binfmt_flat.c Fri Sep 7 16:47:40 2001 @@ -1,7 +1,7 @@ /* * linux/fs/binfmt_flat.c * - * Copyright (C) 2000 Lineo, by David McCullough + * Copyright (C) 2000, 2001 Lineo, by David McCullough * based heavily on: * * linux/fs/binfmt_aout.c: @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef DEBUG #define DBG_FLT(a...) printk(##a) @@ -535,11 +536,14 @@ */ if (flags & FLAT_FLAG_GZIP) { result = decompress_exec(bprm, - ntohl(hdr->entry), - ((char *) textpos) + ntohl(hdr->entry), - text_len + data_len + (relocs * sizeof(unsigned long)) - - ntohl(hdr->entry), - 0); + sizeof (struct flat_hdr), + (((char *) textpos) + + sizeof (struct flat_hdr)), + (text_len + data_len + + (relocs + * sizeof(unsigned long)) + - sizeof (struct flat_hdr)), + 0); if (result >= (unsigned long) -4096) { printk("Unable to decompress data+bss, errno %d\n", (int)-result); @@ -560,7 +564,7 @@ } } - datapos = textpos + text_len; + datapos = textpos + ntohl (hdr->data_start); reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start)); memp = textpos; memkasked = text_len + data_len + extra; @@ -569,8 +573,8 @@ DBG_FLT("Mapping is %x, Entry point is %x, data_start is %x\n", textpos, ntohl(hdr->entry), ntohl(hdr->data_start)); - current->mm->start_code = textpos + ntohl(hdr->entry); - current->mm->end_code = textpos + ntohl(hdr->data_start); + current->mm->start_code = textpos + sizeof (struct flat_hdr); + current->mm->end_code = textpos + sizeof (struct flat_hdr) + text_len; current->mm->start_data = datapos; current->mm->end_data = datapos + data_len; #ifdef NO_MM @@ -624,9 +628,34 @@ if (rev > OLD_FLAT_VERSION) { for (i=0; i < relocs; i++) { + unsigned long addr; + + /* Get the address of the pointer to be + relocated (of course, the address has to be + relocated first). */ rp = (unsigned long *) calc_reloc(ntohl(reloc[i]), text_len); - if (*rp != 0) - *rp = calc_reloc(ntohl(*rp), text_len); /* And relocate it */ + + /* Get the pointer's value. */ + if (((unsigned long)rp & 0x3) == 0) + /* RP is longword aligned. */ + addr = *rp; + else + /* RP is not longword aligned; deal with it. */ + addr = get_unaligned (rp); + + if (addr != 0) { + /* Do the relocation. */ + addr = calc_reloc (ntohl (addr), text_len); + + /* Write back the relocated pointer. */ + if (((unsigned long)rp & 0x3) == 0) + /* RP is longword aligned. */ + *rp = addr; + else + /* RP is not longword aligned; + deal with it. */ + put_unaligned (addr, rp); + } } } else { for (i=0; i < relocs; i++) @@ -657,9 +686,11 @@ current->mm->start_stack = (unsigned long) create_flat_tables(p, bprm); - DBG_FLT("start_thread(regs=0x%x, start_code=0x%x, start_stack=0x%x)\n", - regs, current->mm->start_code, current->mm->start_stack); - start_thread(regs, current->mm->start_code, current->mm->start_stack); + DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n", + regs, textpos + ntohl(hdr->entry), current->mm->start_stack); + start_thread(regs, + textpos + ntohl(hdr->entry), + current->mm->start_stack); if (current->ptrace & PT_PTRACED) send_sig(SIGTRAP, current, 0);