Re: [PATCH] x86/entry/64: randomize kernel stack offset upon syscall

From: Kees Cook
Date: Sun May 12 2019 - 10:34:46 EST


On Sun, May 12, 2019 at 10:02:45AM +0200, Ingo Molnar wrote:
> * Kees Cook <keescook@xxxxxxxxxxxx> wrote:
> > I still think just using something very simply like rdtsc would be good
> > enough.
> >
> > This isn't meant to be a perfect defense: it's meant to disrupt the
> > ability to trivially predict (usually another thread's) stack offset.
>
> But aren't most local kernel exploit attacks against the current task?
> Are there any statistics about this?

I don't think I have any meaningful statistics on this any more. As
mentioned ealier, virtually all the known stack-based attack methods
have been mitigated:
- stack canaries: no linear buffer overflows
- thread_info moved: no more addr_limit games
- VMAP_STACK (i.e. guard page): no more linear overflows/exhaustion
overwriting neighboring memory
- no VLAs: no more index overflows of stack arrays
- stack variable initialization: vastly reduced chance of memory exposures
or use of "uninitialized" variables

One thing we don't have is a shadow call stack. i.e. the return addresses
are still mixed in with local variables, argument spills, etc. This is
still a potential target for attack, as ROP would need to get at the
return addresses. (Though creating a shadow stack just moves the problem,
but in theory to a place where there would be better control over it.)

As for current vs not, yes, many past exploits have been against the
current thread, though it's always been via the various low-hanging fruit
we've hopefully eliminated now. What I think remains interesting are
the attacks where there is some level of "spraying". It seems like this
happens more as mitigations land. For example, while trying to overwrite
a close() function pointer and an attacker can't target a specific heap
allocation, they make lots of sockets, and just close them all after
blindly poking memory. Similar things have been seen for thread-based
attacks (though that predated VMAP_STACK).

So, right now this mitigation remains a "what are we able to do to disrupt
the reliability of an attack that is targetting the stack?" without
a specific threat model in mind. I don't want the answer to be "we do
nothing because we can't find a way to perfectly construct entropy that
resists one threat model of many possible threats."

> > And any sufficiently well-positioned local attacker can defeat this no
> > matter what the entropy source, given how small the number of bits
> > actually ends up being, assuming they can just keep launching whatever
> > they're trying to attack. (They can just hold still and try the same
> > offset until the randomness aligns: but that comes back to us also
> > needing a brute-force exec deterance, which is a separate subject...)
> >
> > The entropy source bikeshedding doesn't seem helpful given how few bits
> > we're dealing with.
>
> The low number of bits is still useful in terms of increasing the
> probability of crashing the system if the attacker cannot guess the stack
> offset.

Right, we have the benefit of many attacks in the kernel being fragile,
but it's possible that it may only wreck the thread and not take out
the kernel itself. (Or the attack is depending on some kind of stack
information exposure, not a write.)

> With 5 bits there's a ~96.9% chance of crashing the system in an attempt,
> the exploit cannot be used for a range of attacks, including spear
> attacks and fast-spreading worms, right? A crashed and inaccessible
> system also increases the odds of leaving around unfinished attack code
> and leaking a zero-day attack.

Yup, which is why I'd like to have _something_ here without us getting
lost in the "perfect entropy" weeds. :)

--
Kees Cook