This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH]: Bug in ppc32 ld.so



> from Geoff Keating on 05/10/02 01:01 PM
> with imbedded text from Anton Blanchard  sent 05/10/02 12:37 PM
> >
> > > This is a potential security hole, it'd be better to fix it in the
kernel.
> >
> > >From a performance viewpoint we do not want to icache synchronise all
> > zero pages we hand out. Its expensive. If a process creates code that
> > will be executed it should do the complete dcbst; sync; icbi; isync
> > sequence. I cant see how an application could gain information from a
> > stale icache, it cant read it.
>
> It can run it and look at the result.  That may be all the information
> it needs.
>
> Suppose, for instance, a process has generated an decryption function
> with the key embedded for performance reasons.  If this page gets
> swapped to disk, and then zeroed and handed to another process, and is
> still in the icache, then the new process has the ability to do a
> decryption it wouldn't otherwise be able to do.  It could be possible,
> under the right circumstances, for a malicious process to do this
> intentionally.
>
> > For some ppc64 machines Im going to switch to using the per page
execute
> > bit to lazily do icache synchonisation, but for the others (and most of
> > the ppc32 cpus) we have do not have this luxury.
> >

I need some clarification on this topic.

It is my assumption that any new page (zero page or not) , marked
executable, would have the icache cleared by the kernel before control is
returned to the user process. If the user process modifies instructions (in
an executable page) after that, it is responsible for the icbi. If the user
process stores instructions into pages that a NOT marked executable then
results are unpredictable. (this was a problem with our signal handling,
which put instructions on the stack, until we changed the kernel to mark
stack segments executable).

The PLT section is an odd duck because it is loaded into the middle of the
read/write data region(between .sbss and .bss) but contains executable code
(for PowerPC32, PowerPC64 is different). This implies that ELF/GOT/PLT
implementations must mark the data region read/write/execute! In fact it
appears that PowerPC32 (glibc-2.2.4) loader (dl-load.c) does load (mmap)
text and data regions read/write/execute (examples later).

So this begs the following questions:

If the pages containing the PLT are marked executable and the kernel will
always clear the icache for any new page in a region marked executable,
what is the problem?

1) Is the new-improved kernel not going to clear the icache for pages in
executable regions?
2) Is there is a case where the loader (glibc) does not mark the region
containing the PLT executable? (if so which; application ,gcc, binutils,
glibc versions)?
3) Given the first constraint (the kernel clears the icache), and the fact
that the PLT is the only code in the middle of a the data region, does the
loader need to icbi (during PLT initialization)?



The following is an "strace of a simple application loading libc.so:

open("/lib/libc.so.6", O_RDONLY)        = 3
read(3, "\177ELF\1\2\1\0\0\0\0\0\0\0\0\0\0\3\0\24\0\0\0\1\0\2\233"...,
1024) = 1024
SYS_197(0x3, 0xffffdb78, 0xffffdb78, 0x400298a8, 0x40029458) = 0
mmap(0x16b2000, 1300860, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 3, 0)
= 0x16b2000
mprotect(0x17c2000, 186748, PROT_NONE)  = 0
mmap(0x17c2000, 167936, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED, 3, 0x100000) = 0x17c2000
mmap(0x17eb000, 18812, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x17eb000
close(3)                                = 0

And the following is an exerpt of the proc/pid#/maps for the above:

00000000016b2000-00000000017c2000 rwxp 0000000000000000 08:03 261145
/lib/libc.so.6
00000000017c2000-00000000017eb000 rwxp 0000000000100000 08:03 261145
/lib/libc.so.6
00000000017eb000-00000000017f0000 rwxp 0000000000000000 00:00 0

Note that the entire range (in 3 regions) is marked read/write/execute. And
the following is an exerpt of libc.so objdump:

SYMBOL TABLE:
000000f4 l    d  .hash  00000000
000030dc l    d  .dynsym      00000000
0000b0cc l    d  .dynstr      00000000
00014938 l    d  .gnu.version 00000000
00015938 l    d  .gnu.version_d     00000000
00015a24 l    d  .gnu.version_r     00000000
00015a74 l    d  .rela.data   00000000
0001b108 l    d  .rela.fixup  00000000
0002121c l    d  .rela__libc_subfreeres   00000000
000214b0 l    d  .rela__libc_subinit      00000000
000214d4 l    d  .rela__libc_atexit 00000000
000214e0 l    d  .rela.eh_frame     00000000
00021a74 l    d  .rela.got2   00000000
00021b28 l    d  .rela.ctors  00000000
00021b34 l    d  .rela.got    00000000
00027e40 l    d  .rela.sdata  00000000
00028068 l    d  .rela.plt    00000000
00029720 l    d  .text  00000000
0010dc20 l    d  .fini  00000000
0010dc7c l    d  .fixup 00000000
0011fce0 l    d  .data  00000000
00135230 l    d  __libc_subfreeres  00000000
0013530c l    d  __libc_subinit     00000000
00135318 l    d  __libc_atexit      00000000
0013531c l    d  .interp      00000000
0013532c l    d  .eh_frame    00000000
001362bc l    d  .got2  00000000
001362f8 l    d  .ctors 00000000
00136304 l    d  .dtors 00000000
0013630c l    d  .got   00000000
00138420 l    d  .sdata2      00000000
00138420 l    d  .dynamic     00000000
001384d0 l    d  .sdata 00000000
00138700 l    d  .sbss  00000000
00138be0 l    d  .plt   00000000
0013a2d8 l    d  .bss   00000000

This loads libc.so's plt at 0x17eabe0 through 0x17ec2d8 (is spans the last
page of the 2nd mmaped file region to the 2nd page of the anonymous
region).



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]