Re: Exec-Shield vs. PaX
On Tue, 4 Nov 2003 firstname.lastname@example.org wrote:
> since a few points have been made regarding $subject, let me clear
> up a few of them:
> 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?
> i don't know the origin of that number above, for now i'll just
> stick to the facts i know:
> - 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. [there's the minor
issue of the process stack's protection bits.]
> - PaX implements best-effort randomization of the entire
> address space, Exec-Shield does it too but at a higher
> code complexity and a lower entropy rate while having
> a worse effect on the kernel entropy pool.
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. (I agree that exec-shield drains the entropy
pool more, i've got this on my TODO.)
> 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. )
> 3. MPROTECT is bogus
> it is not. Ingo says so because he did not understand how
> PaX works. [...]
[ ... to 100% prevent: ]
> (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 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. 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 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.
denying executability of non-executable memory is a fair game - well
specified and a clear-cut goal. Restricting an OS to do what is arguably a
fair thing to do in a number of cases did not sound so clear-cut to me -
end of story. You might still be right in the long run, but it wasnt
obviously right at first sight, and was not complete either so it had
limited value at this stage.
> 4. PaX breaks apps, specs, whatnot
> - 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. If you take that
'privilege' away you'll take away what drives Linux forward - a constantly
growing pool of programmers. 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. 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.
i find your approach interesting nevertheless, and i wish you good luck in
bringing it to completion.
> 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:
[ that i was part of that discussion is only an annoying accident, ending
up in an API/ABI discussion again was unintended. ]
> 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. 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.
> [...] yes, it would need some userland tagging, yes, i have
> ideas for it, no, it's got nothing to do with PT_GNU_STACK. the
> longer story is that the majority of users don't need to care about
> this address space limit, it's mainly databases and some scientific
> applications that run into. mind you, they already had this problem
> before when people were using 1-2 GB userlands (which back then
> was the way to allow the kernel to use more than 1 GB RAM, and even
> these days it's the only way to go if you don't want HIGHMEM).
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".
and it's not an issue on all the sane architectures, fortunately. So i
think having the non-exact protection method of exec-shield will slowly be
obsoleted by ia64/amd64 systems anyway. But i'd hate to lose users to
Windows just because distros only support 1.5GB of VM.
> as for userland tagging: i'd like to have much more control over
> what userland can request from the kernel than what PT_GNU_STACK
> allows. [...]
agreed. But the process stack is arguably a special thing so PT_GNU_STACK
isnt incorrect per se. But we'd like to know and say more, i agree fully.
> [...] for one, requesting executable stacks is irrelevant, it
> should be about requesting permission to generate code at runtime
> (or just use my proposed mmap() interface changes), request
> randomization, etc. [...]
i really dont think we can realistically isolate the code generation
capability and still have a nice and flexible system. 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.
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.
randomization is something that is still open. How we solved it in
exec-shield is via personalities: it's something that can be set runtime,
is inherited across fork() and exec(). If you do "i386 gdb ./a.out" under
exec-shield then you'll get a non-randomized ordinary VM layout with
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
> [...] i'd also like to have control over the placement of the stack
this wouldnt be too hard, but on x86 it's not a good idea i think. But we
can definitely do it on 64-bit platforms, where there's much less danger
of vmas crossing each other.
as you might have noticed, in recent 2.6.0-test kernels there's already
one mprotect() extension that we added to support non-executable stacks:
the addition of PROT_GROWSDOWN and PROT_GROWSUP. This new syscall variant
enables the dynamic linker to change the process stack's permission
without having to know the precise edge of the stack. So the direction is
definitely towards having a more flexible layout for processes.
> [...] and the userland address space size in
> the future. for now chpax is the quick & dirty solution for
> tagging, although users of complete systems with ACLs (grsec
> or RSBAC in Adamantix) can control the PaX flags via ACLs,
> no need for binary modifications. mind you, it's somewhat
> misleading to state that PT_GNU_STACK is a better solution
> than chpax, after all, someone HAS to decide whether a given
> module needs it or not (before someone points it out, trampolines
> are only a small and least important part of the problem), the
> toolchain cannot automatically determine it, so it needs the
> exact same manual work as chpax.
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
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.
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.
this approach saved tons of work and the system was fully usable all