kernel-hardening.lists.openwall.com archive mirror
 help / color / mirror / Atom feed
From: Andy Lutomirski <luto@amacapital.net>
To: Elena Reshetova <elena.reshetova@intel.com>, jpoimboe@redhat.com
Cc: kernel-hardening@lists.openwall.com, luto@kernel.org,
	tglx@linutronix.de, mingo@redhat.com, bp@alien8.de,
	peterz@infradead.org, keescook@chromium.org
Subject: Re: [RFC PATCH] x86/entry/64: randomize kernel stack offset upon system call
Date: Fri, 8 Feb 2019 08:34:36 -0800	[thread overview]
Message-ID: <1D62D311-DD73-43BD-9ED1-8B9450842B89@amacapital.net> (raw)
In-Reply-To: <1549628149-11881-2-git-send-email-elena.reshetova@intel.com>



> On Feb 8, 2019, at 4:15 AM, Elena Reshetova <elena.reshetova@intel.com> wrote:
> 
> If CONFIG_RANDOMIZE_KSTACK_OFFSET is selected,
> the kernel stack offset is randomized upon each
> exit from a system call via the trampoline stack.
> 
> This feature is based on the original idea from
> the PaX's RANDKSTACK feature:
> https://pax.grsecurity.net/docs/randkstack.txt
> All the credits for the original idea goes to the PaX team.
> However, the implementation of RANDOMIZE_KSTACK_OFFSET
> differs greatly from the RANDKSTACK feature (see below).
> 
> Reasoning for the feature:
> 
> This feature should make considerably harder various
> stack-based attacks that are based upon overflowing
> a kernel stack into adjusted kernel stack with a
> possibility to jump over a guard page.
> Since the stack offset is randomized upon each
> system call, it is very hard for attacker to reliably
> land in any particular place on the adjusted stack.
> 

I think we need a better justification. With VLAs gone, it should be statically impossible to overflow past a guard page.

> Design description:
> 
> During most of the kernel's execution, it runs on the "thread
> stack", which is allocated at fork.c/dup_task_struct() and stored in
> a per-task variable (tsk->stack). Since stack is growing downwards,
> the stack top can be always calculated using task_top_of_stack(tsk)
> function, which essentially returns an address of tsk->stack + stack
> size. When VMAP_STACK is enabled, the thread stack is allocated from
> vmalloc space.
> 
> Thread stack is pretty deterministic on its structure - fixed in size,
> and upon every enter from a userspace to kernel on a
> syscall the thread stack is started to be constructed from an
> address fetched from a per-cpu cpu_current_top_of_stack variable.
> This variable is required since there is no way to reference "current"
> from the kernel entry/exit code, so the value of task_top_of_stack(tsk)
> is "shadowed" in a per-cpu variable each time the kernel context
> switches to a new task.
> 
> The RANDOMIZE_KSTACK_OFFSET feature works by randomizing the value of
> task_top_of_stack(tsk) every time a process exits from a syscall. As
> a result the thread stack for that process will be constructed from a
> random offset from a fixed tsk->stack + stack size value upon subsequent
> syscall.
> 

There is a vastly simpler way to do this: leave pt_regs in place and subtract a random multiple of 8 before pushing anything else onto the stack.  This gets most of the benefit with much less complexity.

It’s maybe even better. If you can overflow a stack buffer to rewrite pt_regs, you gain control of all registers. If the stack to pt_regs offset is randomized, then this gets much harder.


>  - random bits are taken from get_random_long() instead of
>    rdtsc() for a better randomness. This however has a big
>    performance impact (see above the numbers) and additionally
>    if we happen to hit a point when a generator needs to be
>    reseeded, we might have an issue.

NAK.  I do not want entry code calling non-arch C code that is not explicitly intended to be used from entry code like this. You may be violating all kinds of rules about context tracking and even stack usage.

Just use ALTERNATIVE to select between RDTSC and RDRAND.  This isn’t used for crypto — refusing to “trust” the CPU here makes no sense.

I think that, if you make these two changes, you’ll have a very straightforward 50-ish line patch.  The only real complication is how to find pt_regs on the way out. I think you could use RBP for this — just make it look like you have a regular frame-pointer-using stack frame between do_syscall_whatever and pt_regs. Josh Poimboeuf can help make sure you get all the unwinding details right. It should be straightforward.

  parent reply	other threads:[~2019-02-08 16:34 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-02-08 12:15 [RFC PATCH] Early version of thread stack randomization Elena Reshetova
2019-02-08 12:15 ` [RFC PATCH] x86/entry/64: randomize kernel stack offset upon system call Elena Reshetova
2019-02-08 13:05   ` Peter Zijlstra
2019-02-08 13:20     ` Reshetova, Elena
2019-02-08 14:26       ` Peter Zijlstra
2019-02-09 11:13         ` Reshetova, Elena
2019-02-09 18:25           ` Andy Lutomirski
2019-02-11  6:39             ` Reshetova, Elena
2019-02-11 15:54               ` Andy Lutomirski
2019-02-12 10:16                 ` Perla, Enrico
2019-02-14  7:52                   ` Reshetova, Elena
2019-02-19 14:47                     ` Jann Horn
2019-02-20 22:20                     ` Kees Cook
2019-02-21  6:37                       ` Andy Lutomirski
2019-02-21 13:20                         ` Jann Horn
2019-02-21 15:49                           ` Andy Lutomirski
2019-02-20 22:15                   ` Kees Cook
2019-02-20 22:53                     ` Kees Cook
2019-02-21 23:29                       ` Kees Cook
2019-02-27 11:03                         ` Reshetova, Elena
2019-02-21  9:35                     ` Perla, Enrico
2019-02-21 17:23                       ` Kees Cook
2019-02-21 17:48                         ` Perla, Enrico
2019-02-21 19:18                           ` Kees Cook
2019-02-20 21:51         ` Kees Cook
2019-02-08 15:15       ` Peter Zijlstra
2019-02-09 11:38         ` Reshetova, Elena
2019-02-09 12:09           ` Greg KH
2019-02-11  6:05             ` Reshetova, Elena
2019-02-08 16:34   ` Andy Lutomirski [this message]
2019-02-20 22:03     ` Kees Cook
2019-02-08 21:28   ` Kees Cook
2019-02-11 12:47     ` Reshetova, Elena
2019-02-20 22:04   ` Kees Cook

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1D62D311-DD73-43BD-9ED1-8B9450842B89@amacapital.net \
    --to=luto@amacapital.net \
    --cc=bp@alien8.de \
    --cc=elena.reshetova@intel.com \
    --cc=jpoimboe@redhat.com \
    --cc=keescook@chromium.org \
    --cc=kernel-hardening@lists.openwall.com \
    --cc=luto@kernel.org \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --subject='Re: [RFC PATCH] x86/entry/64: randomize kernel stack offset upon system call' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).