Patchwork Patch to fix mapping of elf pheaders specifying both .data and .bss segments

login
register
mail settings
Submitter Kai Backman
Date Aug. 6, 2009, 10:41 p.m.
Message ID <c7187c3d0908061541o539e0e16ka87ebbc58f7cd873@mail.gmail.com>
Download mbox | patch
Permalink /patch/30911/
State Superseded
Headers show

Comments

Kai Backman - Aug. 6, 2009, 10:41 p.m.
On Thu, Jun 18, 2009 at 11:57 AM, Riku Voipio<riku.voipio@iki.fi> wrote:
> The patch attached is totally messed up thou.

Sorry for the delay. I was vacationing in Finland (incidentally)..

To restart the thread, I've re-attached the patch.

 Kai
Riku Voipio - Aug. 12, 2009, 3:06 p.m.
On Thu, Aug 06, 2009 at 03:41:02PM -0700, Kai Backman wrote:
> On Thu, Jun 18, 2009 at 11:57 AM, Riku Voipio<riku.voipio@iki.fi> wrote:
> > The patch attached is totally messed up thou.
> 
> Sorry for the delay. I was vacationing in Finland (incidentally)..
> 
> To restart the thread, I've re-attached the patch.

I see Max Filippov has touched the same function for possibly the same
issue?

http://lists.gnu.org/archive/html/qemu-devel/2009-07/msg00902.html

> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 190ad14..e4e75d5 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -1211,7 +1211,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
>      abi_ulong mapped_addr;
>      struct elf_phdr * elf_ppnt;
>      struct elf_phdr *elf_phdata;
> -    abi_ulong elf_bss, k, elf_brk;
> +    abi_ulong elf_bss, last_bss, mapped_bss, k, elf_brk;
>      int retval;
>      char * elf_interpreter;
>      abi_ulong elf_entry, interp_load_addr = 0;
> @@ -1271,6 +1271,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
>      elf_ppnt = elf_phdata;
>  
>      elf_bss = 0;
> +    last_bss = 0;
>      elf_brk = 0;
>  
>  
> @@ -1495,12 +1496,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
>          k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
>          if (k > elf_bss)
>              elf_bss = k;
> +        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
> +        if (k > last_bss)
> +            last_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;
> +        if (!elf_interpreter && last_bss > elf_bss) {
> +      	    padzero(elf_bss, last_bss);
> +	    mapped_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1);
> +
> +	    /* Map the last of the bss segment */
> +            target_mmap(load_bias + mapped_bss, last_bss-mapped_bss,
> +                        PROT_READ|PROT_WRITE|PROT_EXEC,
> +                        MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
> +        }
>      }
>  
>      elf_entry += load_bias;
Max Filippov - Aug. 28, 2009, 8:10 p.m.
Hello.

> On Thu, Aug 06, 2009 at 03:41:02PM -0700, Kai Backman wrote:
> > On Thu, Jun 18, 2009 at 11:57 AM, Riku Voipio<riku.voipio@iki.fi> wrote:
> > > The patch attached is totally messed up thou.
> > 
> > Sorry for the delay. I was vacationing in Finland (incidentally)..
> > 
> > To restart the thread, I've re-attached the patch.
> 
> I see Max Filippov has touched the same function for possibly the same
> issue?
> 
> http://lists.gnu.org/archive/html/qemu-devel/2009-07/msg00902.html
> 

You're right, the same issue. But the patch doesn't fix it for me: elf_interpreter mentioned in the last
hunk is always set to "/lib/ld.so.1". Having this condition removed it works perfectly.

> > diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> > index 190ad14..e4e75d5 100644
> > --- a/linux-user/elfload.c
> > +++ b/linux-user/elfload.c
> > @@ -1211,7 +1211,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
> >      abi_ulong mapped_addr;
> >      struct elf_phdr * elf_ppnt;
> >      struct elf_phdr *elf_phdata;
> > -    abi_ulong elf_bss, k, elf_brk;
> > +    abi_ulong elf_bss, last_bss, mapped_bss, k, elf_brk;
> >      int retval;
> >      char * elf_interpreter;
> >      abi_ulong elf_entry, interp_load_addr = 0;
> > @@ -1271,6 +1271,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
> >      elf_ppnt = elf_phdata;
> >  
> >      elf_bss = 0;
> > +    last_bss = 0;
> >      elf_brk = 0;
> >  
> >  
> > @@ -1495,12 +1496,24 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
> >          k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
> >          if (k > elf_bss)
> >              elf_bss = k;
> > +        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
> > +        if (k > last_bss)
> > +            last_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;
> > +        if (!elf_interpreter && last_bss > elf_bss) {
> > +      	    padzero(elf_bss, last_bss);
> > +	    mapped_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1);
> > +
> > +	    /* Map the last of the bss segment */
> > +            target_mmap(load_bias + mapped_bss, last_bss-mapped_bss,
> > +                        PROT_READ|PROT_WRITE|PROT_EXEC,
> > +                        MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
> > +        }
> >      }
> >  
> >      elf_entry += load_bias;
> 
> 

Thanks.
-- Max

Patch

diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 190ad14..e4e75d5 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1211,7 +1211,7 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     abi_ulong mapped_addr;
     struct elf_phdr * elf_ppnt;
     struct elf_phdr *elf_phdata;
-    abi_ulong elf_bss, k, elf_brk;
+    abi_ulong elf_bss, last_bss, mapped_bss, k, elf_brk;
     int retval;
     char * elf_interpreter;
     abi_ulong elf_entry, interp_load_addr = 0;
@@ -1271,6 +1271,7 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
     elf_ppnt = elf_phdata;
 
     elf_bss = 0;
+    last_bss = 0;
     elf_brk = 0;
 
 
@@ -1495,12 +1496,24 @@  int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
         if (k > elf_bss)
             elf_bss = k;
+        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
+        if (k > last_bss)
+            last_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;
+        if (!elf_interpreter && last_bss > elf_bss) {
+      	    padzero(elf_bss, last_bss);
+	    mapped_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1);
+
+	    /* Map the last of the bss segment */
+            target_mmap(load_bias + mapped_bss, last_bss-mapped_bss,
+                        PROT_READ|PROT_WRITE|PROT_EXEC,
+                        MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+        }
     }
 
     elf_entry += load_bias;