Subject: Re: Non executable mappings and compatibility options bugs
To: Chuck Silvers <chuq@chuq.com>
From: Charles M. Hannum <abuse@spamalicious.com>
List: tech-kern
Date: 06/28/2004 19:33:35
On Monday 28 June 2004 16:57, Chuck Silvers wrote:
> 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.

I have a dim memory that there is a problem with the GNU linker, that it will 
not set the attributes correctly on the GOT section when there is nothing 
else in it -- i.e. when linking with -Bsymbolic, and that this used to be 
worked around in the single case where we use -Bsymbolic, in ld.elf_so, with 
an explicit cache flush there.  This is no longer the case, though, and I 
removed the cache flush some last year.