Subject: Re: Non executable mappings and compatibility options bugs
To: Charles M. Hannum <abuse@spamalicious.com>
From: Chuck Silvers <chuq@chuq.com>
List: tech-kern
Date: 06/28/2004 09:57:18
On Mon, Jun 21, 2004 at 07:21:37AM +0000, Charles M. Hannum wrote:
> On Sunday 20 June 2004 13:15, Emmanuel Dreyfus wrote:
> > Hi
> >
> > Wiz reported me a bug in COMPAT_LINUX/powerpc that might be an unwanted
> > consequence of non executable mappings: Linux's ldconfig will randomly
> > crash with either SIGSEGV or SIGILL.
> >
> > Tracking down the problem with GDB, it occurs always at the same place,
> > in a function called __DTOR_END__:
> >
> > Program received signal SIGILL, Illegal instruction.
> > 0x1007ff84 in __DTOR_END__ ()
> > (gdb) x/1i $pc
> > 0x1007ff84 <__DTOR_END__+4>:    blrl
> >
> > The instruction is perfectly legal, I assume the problem is just that
> > the memory is mapped as non executable.
> >
> > This function comes from the .dtors ELF section:
> >
> >  12 .dtors        00000008  1007ff4c  1007ff4c  0006ff4c  2**2
> >                   CONTENTS, ALLOC, LOAD, DATA
> 
> No, actually, it doesn't occur there.  If you add the size and VMA for .dtors, 
> you'll find that the address you're looking at is beyond that.  It occurs at 
> the beginning of the GOT, and is standard on PowerPC.  The .got section, and 
> the program header that contains it, are marked executable for this reason.

you're right that that address does live in the .got section:

 12 .dtors        00000008  1007ff7c  1007ff7c  0006ff7c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 13 .got          00000014  1007ff84  1007ff84  0006ff84  2**2
                  CONTENTS, ALLOC, LOAD, DATA


however, in this binary the .got section is not in an executable
program header section:

    LOAD off    0x00000000 vaddr 0x10000000 paddr 0x10000000 align 2**16
         filesz 0x0006de6c memsz 0x0006de6c flags r-x
    LOAD off    0x0006de70 vaddr 0x1007de70 paddr 0x1007de70 align 2**16
         filesz 0x000022e0 memsz 0x00003604 flags rw-
    NOTE off    0x000000a0 vaddr 0x100000a0 paddr 0x100000a0 align 2**4
         filesz 0x00000020 memsz 0x00000020 flags r--


the OEA powerpc MMU hardware only supports execute permissions at the
granularity of a segment, and since both load sections are in the same
segment, they are both executable as far as the hardware is concerned.

however, the other thing that the per-page executable permissions are
used for in this case is to decide whether or not we need to invalidate
the icache.  since the page is not "executable", skip the icache invalidation
of that page when we map it, so sometimes we trip over some stale cache data.
we're had this optimization of skipping the icache invalidation for
a couple years now, so I'm not sure why this problem with linux ldconfig
only started showing up after the non-executable support was added.
from what I can tell, the ELF code has always requested the permissions
specified by the program header, so we should have had the same problem
before.

-Chuck