linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@kernel.org>
To: Kees Cook <keescook@chromium.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	Elena Reshetova <elena.reshetova@intel.com>,
	x86@kernel.org, Andy Lutomirski <luto@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Alexander Potapenko <glider@google.com>,
	Alexander Popov <alex.popov@linux.com>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Jann Horn <jannh@google.com>, Vlastimil Babka <vbabka@suse.cz>,
	David Hildenbrand <david@redhat.com>,
	Mike Rapoport <rppt@linux.ibm.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Jonathan Corbet <corbet@lwn.net>,
	Randy Dunlap <rdunlap@infradead.org>,
	kernel-hardening@lists.openwall.com,
	linux-hardening@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org,
	linux-kernel@vger.kernel.org,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Borislav Petkov <bp@alien8.de>
Subject: Re: [PATCH v7 4/6] x86/entry: Enable random_kstack_offset support
Date: Sat, 20 Mar 2021 12:58:20 +0100	[thread overview]
Message-ID: <20210320115820.GA4151166@gmail.com> (raw)
In-Reply-To: <20210319212835.3928492-5-keescook@chromium.org>


* Kees Cook <keescook@chromium.org> wrote:

> Allow for a randomized stack offset on a per-syscall basis, with roughly
> 5-6 bits of entropy, depending on compiler and word size. Since the
> method of offsetting uses macros, this cannot live in the common entry
> code (the stack offset needs to be retained for the life of the syscall,
> which means it needs to happen at the actual entry point).

>  __visible noinstr void do_syscall_64(unsigned long nr, struct pt_regs *regs)
>  {
> +	add_random_kstack_offset();
>  	nr = syscall_enter_from_user_mode(regs, nr);

> @@ -83,6 +84,7 @@ __visible noinstr void do_int80_syscall_32(struct pt_regs *regs)
>  {
>  	unsigned int nr = syscall_32_enter(regs);
>  
> +	add_random_kstack_offset();

>  	unsigned int nr = syscall_32_enter(regs);
>  	int res;
>  
> +	add_random_kstack_offset();

> @@ -70,6 +71,13 @@ static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
>  	 */
>  	current_thread_info()->status &= ~(TS_COMPAT | TS_I386_REGS_POKED);
>  #endif
> +
> +	/*
> +	 * x86_64 stack alignment means 3 bits are ignored, so keep
> +	 * the top 5 bits. x86_32 needs only 2 bits of alignment, so
> +	 * the top 6 bits will be used.
> +	 */
> +	choose_random_kstack_offset(rdtsc() & 0xFF);
>  }

1)

Wondering why the calculation of the kstack offset (which happens in 
every syscall) is separated from the entry-time logic and happens 
during return to user-space?

The two methods:

+#define add_random_kstack_offset() do {                                        \
+       if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \
+                               &randomize_kstack_offset)) {            \
+               u32 offset = this_cpu_read(kstack_offset);              \
+               u8 *ptr = __builtin_alloca(offset & 0x3FF);             \
+               asm volatile("" : "=m"(*ptr) :: "memory");              \
+       }                                                               \
+} while (0)
+
+#define choose_random_kstack_offset(rand) do {                         \
+       if (static_branch_maybe(CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, \
+                               &randomize_kstack_offset)) {            \
+               u32 offset = this_cpu_read(kstack_offset);              \
+               offset ^= (rand);                                       \
+               this_cpu_write(kstack_offset, offset);                  \
+       }                                                               \
+} while (0)

choose_random_kstack_offset() basically calculates the offset and 
stores it in a percpu variable (mixing it with the previous offset 
value), add_random_kstack_offset() uses it in an alloca() dynamic 
stack allocation.

Wouldn't it be (slightly) lower combined overhead to just do it in a 
single step? There would be duplication along the 3 syscall entry 
points, but this should be marginal as this looks small, and the entry 
points would probably be cache-hot.

2)

Another detail I noticed: add_random_kstack_offset() limits the offset 
to 0x3ff, or 1k - 10 bits.

But the RDTSC mask is 0xff, 8 bits:

+       /*
+        * x86_64 stack alignment means 3 bits are ignored, so keep
+        * the top 5 bits. x86_32 needs only 2 bits of alignment, so
+        * the top 6 bits will be used.
+        */
+       choose_random_kstack_offset(rdtsc() & 0xFF);

alloca() itself works in byte units and will round the allocation to 8 
bytes on x86-64, to 4 bytes on x86-32, this is what the 'ignored bits' 
reference in the comment is to, right?

Why is there a 0x3ff mask for the alloca() call and a 0xff mask to the 
RDTSC randomizing value? Shouldn't the two be synced up? Or was the 
intention to shift the RDTSC value to the left by 3 bits?

3)

Finally, kstack_offset is a percpu variable:

  #ifdef CONFIG_HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
  ...
  DEFINE_PER_CPU(u32, kstack_offset);

This is inherited across tasks on scheduling, and new syscalls will 
mix in new RDTSC values to continue to randomize the offset.

Wouldn't it make sense to further mix values into this across context 
switching boundaries? A really inexpensive way would be to take the 
kernel stack value and mix it into the offset, and maybe even the 
randomized t->stack_canary value?

This would further isolate the syscall kernel stack offsets of 
separate execution contexts from each other, should an attacker find a 
way to estimate or influence likely RDTSC values.

Thanks,

	Ingo


  reply	other threads:[~2021-03-20 11:58 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-19 21:28 [PATCH v7 0/6] Optionally randomize kernel stack offset each syscall Kees Cook
2021-03-19 21:28 ` [PATCH v7 1/6] jump_label: Provide CONFIG-driven build state defaults Kees Cook
2021-03-19 21:28 ` [PATCH v7 2/6] init_on_alloc: Optimize static branches Kees Cook
2021-03-19 21:28 ` [PATCH v7 3/6] stack: Optionally randomize kernel stack offset each syscall Kees Cook
2021-03-28 14:42   ` Thomas Gleixner
2021-03-29 18:41     ` Kees Cook
2021-03-19 21:28 ` [PATCH v7 4/6] x86/entry: Enable random_kstack_offset support Kees Cook
2021-03-20 11:58   ` Ingo Molnar [this message]
2021-03-21 17:03     ` Kees Cook
2021-03-28 14:18   ` Thomas Gleixner
2021-03-29 18:43     ` Kees Cook
2021-03-19 21:28 ` [PATCH v7 5/6] arm64: entry: " Kees Cook
2021-04-01  8:34   ` Will Deacon
2021-03-19 21:28 ` [PATCH v7 6/6] lkdtm: Add REPORT_STACK for checking stack offsets 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=20210320115820.GA4151166@gmail.com \
    --to=mingo@kernel.org \
    --cc=a.p.zijlstra@chello.nl \
    --cc=akpm@linux-foundation.org \
    --cc=alex.popov@linux.com \
    --cc=ard.biesheuvel@linaro.org \
    --cc=bp@alien8.de \
    --cc=catalin.marinas@arm.com \
    --cc=corbet@lwn.net \
    --cc=david@redhat.com \
    --cc=elena.reshetova@intel.com \
    --cc=glider@google.com \
    --cc=jannh@google.com \
    --cc=keescook@chromium.org \
    --cc=kernel-hardening@lists.openwall.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=luto@kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=peterz@infradead.org \
    --cc=rdunlap@infradead.org \
    --cc=rppt@linux.ibm.com \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=vbabka@suse.cz \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /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
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).