[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Exec-Shield vs. PaX



[metanote: as you can see, we're entering the meta-discussion part
and i can very well understand that it's of little if any interest
to most you (that includes me btw), so i'll try not to post more
here except maybe to discuss technical issues]

> > 1. 'It seems that exec-shield does 99% of what PaX does'
> 
> this is not the case and i'm not claiming it. If you feel attacked, please
> dont - i'll stipulate that PaX gives better security than exec-shield, ok?

in case you didn't realize it, it was not directed at you either.

> >   - PaX implements perfect non-executable pages on amd64, i386,
> >     ia64, parisc, ppc, sparc and sparc64 whereas Exec-Shield has
> >     some imitation of it only on i386 (it's not true per-page).
> 
> non-executable pages on anything else but i386 is a triviality, as the
> hardware and the kernel supports it. There's virtually nothing that PaX or
> exec-shield has to add to enable them - they are there.

that's what you say because apparently you have never checked
it let alone tried. here's a few of these 'trivial' questions
for you to answer:

1. how do you do per page non-exec pages on ppc/ppc64? hint,
   there's no NX bit in their PTE format. try to answer that
   without looking at PaX first ;-)

2. how do you do per page non-exec pages on mips/mips64? hint,
   there's no split TLB (let alone NX PTE bit) in the base
   architecture definition.

3. how do you do per page non-exec pages on sparc64 under
   linux 2.6? hint, you've reused the last free bit in the PTE.
   and linux didn't support NX on sparc64 even before 2.6.

4. how do you do per page non-exec pages on sh[34]? hint, there's
   at most a 'half' split TLB only and no NX PTE bit.

5. how do you do per page non-exec pages without a TLB/MMU
   (you did claim 'trivial' support for anything but i386)?

next, what will you do with the archs where the .plt is in the
rwx ELF segment and hence under your scheme would force all of
.data/.bss to become executable as well?

> lets also point out that exec-shield offers relative randomization of DSOs
> to each other, while PaX only randomizes a single base of the DSOs, their
> relative addresses remain constant. This way the randomization bits of
> exec-shield add up for brute-force attacks. Lets add it that if a limited
> exploit can be turned into an information leak then relative randomization
> does not help - but it does help if the first exploit itself needs precise
> addresses from multiple DSOs.

all correct, except for the fact that the whole exercise of per-library
randomization is pointless. i say that based on my experience in analyzing
bugs and writing exploits for them - admittedly something i can't share
with you, so feel free to think otherwise. what i can offer however is
a simple observation: if an attacker needs code addresses from more than
one library, then he can get them even under Exec-Shield. this is because
he can just use the .plt entries of the library whose base address he
learned via info-leaking. also, the most likely information leaks that
contain library addresses are on the stack - and you can imagine that
the stack will likely contain such addresses from more than one region,
hence there's little if any advantage of separate randomization.

in any case, you're missing the point behind randomization. it's an
obscurity feature, however efficient it may turn out to be in certain
cases. i did it because it was extremely cheap (speaking of the PaX
implementation, not Exec-Shield) so i said 'why not'. randomization
serves NO purpose in the grand scheme, it does not provide guaranteed
protection against the PaX attack model (arbitrary read/write access
to the address space). you don't have an attack model so you can say
whatever you want about the details of your randomization, they will
of course be 'true' by definition.

> >   second, paxtest had some bugs which Exec-Shield exposed and made
> >   Exec-Shield appear better than it is. i've fixed them here and
> >   expect to release 0.9.5 today or so. the results now look like:
> 
> ( how fair that you give me a chance to run it ... not. )

from the email headers of your answer:

Date: Wed, 5 Nov 2003 00:58:30 +0100 (CET)
From: Ingo Molnar <mingo@elte.hu>

paxtest 0.9.5 was released hours (!) before that, what are you talking
about?

> >   (1) introduce/execute arbitrary code
> >   (2) execute existing code out of original program order
> >   (3) execute existing code in original program order with arbitrary data
> 
> no.

no what? are you telling me you know of an exploit technique against
a memory corruption bug that does not belong to any of the above
categories? because that's what my statement was about.

> No offense meant, but i say so because right now i dont see the way to
> have a generic and usable Linux system with all the restrictions you are
> talking about. If you complete your project and everything works and it's
> still the same live, flexible and kicking Linux system that we all know
> and love then i was clearly wrong.

http://gentoo.oregonstate.edu/experimental/x86/stages/

(i apologize for the inadvertant advocacy here, it's just to show a
point, i don't want to start a distro war)

the above is the beginning of such work with full PIE and propolice
support. or if you're into server-land, check out Adamantix [1] (it
was released before Exec-Shield).

> Right now it seems to be heading more
> in the direction of a prison - but this is just my judgement. In any case,
> i did not want to add any of that to exec-shield. I'll leave the prison
> guard work to selinux.

you're mixing up intrusion prevention (PaX) with access control. see
more below for the 'prison' argument.

> you do realise that most of those 'exploit techniques' overlap with some
> programming concepts, and you think that those concepts are flawed by
> design and should be eliminated - i dont agree with this characterisation.

putting words into my mouth or can you actually quote me on that?
what i'm saying is that there are programming techniques (runtime
code generation in this case) that should be handled more carefully
than they have been. what PaX does by default FOR NOW is the result
of me being cautious (and i have not heard of a single PaX user yet
who did not appreciate it) and not having the resources to fix up
userland all by myself. this also brings me back to your 'prison'
argument and a bigger issue you seem to be not talking about:

you said a lot about what you don't agree with in PaX, what
exactly prevented you from changing it *yourself*? what prevents
*you* from disabling MPROTECT by default for example?

speaking further about the 'prison' thing, you said this earlier
in another thread:

> if you could get rid of the 1.5 GB VM limitation of PaX and if you could
> change it to use PT_GNU_STACK to set the process stack's protection bits
> then i think there's no need for exec-shield - PaX will provide better
> protection at no cost and no tradeoffs.

have you changed your mind since then?

> >   - apps that by their nature want to generate code runtime (e.g.,
> >     java). they're  broken for good which many people noticed by now.
> >     that's good, that was my purpose because i wanted to draw
> >     attention to the fact that runtime code generation is an
> >     important privilege that should be carefully managed (as it
> >     happens to be also one of the exploit techniques). [...]
> 
> i think here we are in a fundamental disagreement. To take it to the
> extreme, being able to 'generate code' [ie. allow an application to write
> code, etc.] is one of the fundamental properties of any Linux user
> account, and hopefully remains so in the future.

the ability to create/execute one's own binaries is a privilege
too, that's what ACL and Trusted Path Execution systems allow you
to control (before you talk about 'fundamental properties' please
ask some administrators of user accounts in a corporate or
government/military environment). in any case, this is no longer
about PaX but how a secure system is to be created - there are
as many approaches as many people tried, PaX is only one (piece)
of them.

> If you take that 'privilege' away you'll take away what drives
> Linux forward - a constantly growing pool of programmers.

i have the impression that you believe i'm trying to promote PaX
to enter the 'main' kernels in its current from. to be clear about
it: i am *not*. if someone wanted to do it, i'd have several
suggestions before that should happen. such as deciding what is
acceptable to be default, how it should be controlled (configure
or runtime, etc), how and to what extent buggy userland should
be fixed, etc. all these concerns are irrelevant in the current
discussion because we're talking about technical merits (or
their lack of) of different approaches, not how they should be
deployed in the 'real world' - that's a whole another problem
and requires more parties to participate.

> I dont want good security to rely on the
> system's insistence to remove the ability to generate code from as many
> codepaths as possible.

again, nothing is removed, it's just taken under control (as i said
above, don't mistake current PaX defaults with how it should be done
when the other building blocks are done).

> There's got to be another way to secure those damn
> apps ... the price you are willing to pay is i believe way too high.

good luck in your trying to fix the problem (speaking of the PaX attack
model again here), you'd be the first one to do it without the measures
that PaX takes.

> >   about PaX breaking specs: i urge Ingo and others saying this to
> >   point me to the precise location in SUSv3 or POSIX 1003.1-2001
> >   that PaX conflicts with. [...]
> 
> many areas of PaX conflict with one of the most basic rule of Linux:
> 
>    http://lwn.net/Articles/32980/

i hope you realize that Linus's declaration is not on the same level
as internationally accepted standards, don't mix them up. as for not
breaking userland: sure, that's what i'd like to have as well, but
i have only so many hours in a day to work on that. also, you did
break userland yourself as well, otherwise how would you explain the
patches RedHat made to the XFree86 server? see, there're just cases
when userland is plain wrong and must be fixed. on another note, how
did you get java to work under Exec-Shield while maintaining all those
non-executable regions (see more on this below)?

> >   about SEGMEXEC and the 1.5GB limit: yes, it's true, yes, it could
> >   be changed (if one can live with a more limited range for executable
> >   mappings), [...]
> 
> i'm not sure it's acceptable to put _any_ restriction on the layout of the
> user VM.

no problem, PaX as it is makes no restrictions on the layout, we'll just
be stuck with the 1.5 GB task size on i386 (or the usual 3 GB if you can
take the performance hit of PAGEEXEC on i386).

> The rule exec-shield follows is this: whenever the kernel gets a
> chance to chose it will group mappings smartly, but it will follow
> requests for executability no matter what. So while this doesnt _force_
> good protection, for most apps it provides a pretty acceptable layout.
> 
> i guess this is a hard-to-solve philosophy difference again.

indeed, especially since your philosophy seems to be 'do something
while breaking absolutely no apps' where 'something' is yet to be
explained and whatever it is, you still broke apps with it (such
as XFree86). 

> a fair number of users got real happy when we extended the x86 user VM
> from 3GB to 4GB. Going from 3 GB to 1.5 GB is really not an option i'm
> afraid. It's also not an option to say that "your app is secure only as
> long as it fits into 1.5 GB". It also not an option to say "this box is
> pretty secure, except for your huge database server".

that's your personal opinion. others (e.g., PaX users) have the
exact opposite as their personal opinions, so be it ;-). since
you've talked so much about what does not fit into 1.5 GB, could
you please provide us with a list of applications that are used by
the majority of users and fail when run in a 1.5 GB address space?

> obsoleted by ia64/amd64 systems anyway. But i'd hate to lose users to
> Windows just because distros only support 1.5GB of VM.

Windows has a 2 GB userland, seems to be closer to 1.5 than 3. other
than that, Microsoft is moving into the PaX direction [2] (i'm referring
to runtime code generation and memory protection in particular).

> i really dont think we can realistically isolate the code generation
> capability and still have a nice and flexible system.

it's not about 'isolation' (did you mean 'removal'?) but control.
control by the distro maker, system administrator or the end user.
what is subject to discussion how it should best be done. you say
it should not be done at all, that's your opinion and is in
complete disagreement with experts in the information security field.

> I dont see anything wrong in apps executing scripts. Or apps writing
> scripts and executing them. Or apps doing JIT stuff, or just doing
> some quick runtime fixup.

there's nothing wrong with it as long as you write bugfree code or
don't want guaranteed security from certain exploit methods. there
are people who want the latter because they have much at stake and
know that the former is not true.

> It's quite widely done and it would not be Linux anymore if we try to
> exterminate or second-class such techniques. And it's even more common in
> the Windows world, and i really hope those Windows apps continue to come
> over to Linuxland.

i know i'm repeating myself, but i'll say it again: there's no problem
with runtime code generation as long as it's under control. let's do it,
but be aware of it when it's done because it's a dangerous privilege
when abused. come up with a system that allows one to easily define and
maintain defaults and policies, and i'll be the happiest person.

> static predictable addresses. I dont think this should be tagged via the
> binary itself - that is too inflexible. There's already one 'VM size bit'
> in the personality mask in the upstream 2.6 kernel: the 3GB flag for
> amd64.

personalities are something i was thinking of before, but i had a
problem which i forget now, i'll take another look at it later.

> no, this is not how PT_GNU_STACK works. PT_GNU_STACK not only detects
> trampolines, but all those techniques that _might_ point in the direction
> of process-stack executability. Such as the use of inline assembly. So the
> toolchain pessimistically turns on executability and guarantees that _if_
> the object is marked non-executable, that it certainly needs no executable
> stack.

i was referring to this patch [3] which deals with trampolines only,
thanks for clarifying it.

> even the above conservative scheme gave a very high coverage rates, with
> just a couple of (well below 10% of all) important apps/libs falling out
> of the nonexecutability umbrella.

what about code not compiled by gcc? are all those users running with
an unsafe default (executable stack) or have broken binaries?

> To solve these cases, application writers/packagers can further improve
> the accuracy of this scheme by declaring said pieces of code as permitting
> non-executable, but it's the right place and the best way to document it:
> in the source. It cannot get lost, it will be updated when the code is
> changed, etc. Tags tend to get lost, or tend to get incorrect over time.

doing it in the source code is what i suggested as well, read the
proposal in mprotect.txt.

[now in order to save some round-trip time, i'll answer your second
mail here as well]

> i downloaded the new 0.9.5 paxtest package and amongst other changes it
> has the following oneliner change:
> 
> --- paxtest-0.9.4/body.c
> +++ paxtest-0.9.5/body.c
> @@ -29,6 +29,7 @@
>   fflush( stdout );
> 
>   if( fork() == 0 ) {
> +		do_mprotect((unsigned long)argv & ~4095U, 4096,
> +PROT_READ|PROT_WRITE|PROT_EXEC);
>    doit();
>   } else {
>    wait( &status );
> 
> this intentionally calls mprotect(PROT_EXEC) for the highest possible
> address one can think of. This call has no useful purpose at all. In other
> words, this is a specific, underhand cheat to trigger 'Vulnerable'
> messages for all items when running paxtest on exec-shield kernels. Bravo!

> frankly, i've never experienced anything like this in my many years in the
> Linux world. You so far gave the impression of a reasonable and balanced
> person but this is as low as it gets. Shame on you.

several things come to my mind.

1. it's called paxtest for a reason. it's a regression test suite that
   demonstrates basic exploit techniques and how PaX foils them (or not,
   as the case may be). in case you don't understand 'regression', it's
   not about what works, but what does not, therefore it is entirely
   appropriate for PaX to show its strengths even under circumstances
   where Exec-Shield fails. as i explain below, chosing between mprotect()
   and threads came down to the usual question: what takes less time yet
   demonstrates the effect (one line vs. a hundred or so in my case).

   beyond all this, feel free to write your own suite.

2. did you miss this in my first post:

> Executable anonymous mapping             : Vulnerable
> Executable bss                           : Vulnerable
> Executable data                          : Vulnerable
> Executable heap                          : Vulnerable
> Executable stack                         : Vulnerable

>  the above changes are the result of Ingo's approach to create
>  non-executable memory on i386, they're not per page as a simple
>  mprotect on the top of the stack shows. before i get accused of
>  specifically rigging the tests, i'll tell you that running
>  multithreaded apps would have almost the same effect (only the
>  main stack would stay non-exec under Exec-Shield). needless to
>  say, PaX passes all the above as before.

   do you understand what i'm saying there? did you also check the
   changelog which says this:

  * Non-executable page tests expose incomplete implementations

   do you disagree that paxtest exposes a weakness in Exec-Shield
   or not? do you disagree that the exposed weakness can very well
   occur in real life or not?

   let me get back to the topic of java as i promised above. java
   is a nice animal as it shows several issues with Exec-Shield.

   first of all, it's multithreaded. glibc creates executable
   thread stacks by default. unfortunately for Exec-Shield, when
   such stacks are created, everything below them becomes
   executable as well, even if it was not requested by the
   application. you call that a feature i assume, i call it a bug
   (if i mmap() something without PROT_EXEC i don't want the OS
   to change it to executable behind my back - *that* is really
   not compliant with standards).

   second, java has a small piece of executable code in its
   .data segment - that should break it quite early during
   startup. how come you never run into it if, as you claim,
   .data is non-executable?

3. you and others have (ab)used paxtest long enough to justify
   the approach taken by Exec-Shield while 'forgetting' to point
   out the weaknesses/limitations (e.g., show me a single post
   of yours where you discuss the problem with multithreaded
   apps, or the more generic issue of unexpected and standard
   breaking memory protection changes). forgive me if i'm not
   willing to assist to this any longer, but *that* would make
   me feel really ashamed.


[1] http://adamantix.org
[2] http://msdn.microsoft.com/security/default.aspx?pull=/library/en-us/dnwxp/html/securityinxpsp2.asp
[3] http://gcc.gnu.org/ml/gcc-patches/2003-06/msg00302.html



Reply to: